private void HeartBeatThreadProc(object para) { int threadCount = (int)para; DateTime lastSubHeaartBeat = DateTime.Now; //子线程最后发送心跳时间 while (true) { Thread.Sleep(10); if ((DateTime.Now - GlobalHeartBeat.GetGlobalTime()).TotalMinutes > 10) { log.LogEvent("心跳线程即将退出"); break; } //向子线程发送存活心跳,一旦心跳停止,则子线程死亡 if (DateTime.Now.Second % 5 == 0 && DateTime.Now.Second != lastSubHeaartBeat.Second) { lastSubHeaartBeat = DateTime.Now; for (int i = 0; i < threadCount; i++) { //如果发送空列表,则为心跳线程 List <TradeOrderStruct> o = new List <TradeOrderStruct>(); queue_future_excuteThread.GetQueue(i).Enqueue((object)o); } } } Thread.CurrentThread.Abort(); }
private void ThreadProc() { //本地股市信息存入stockTable 中 StockInfoClient client = new StockInfoClient(); KeyValuePair <string, object> message1 = new KeyValuePair <string, object>("THREAD_MARKET", (object)true); queue_system_status.GetQueue().Enqueue((object)message1); DateTime lastmessage = DateTime.Now; MarketData info = new MarketData(); while (true) { if (DateTime.Now.Second != lastmessage.Second) { KeyValuePair <string, object> message3 = new KeyValuePair <string, object>("THREAD_MARKET", (object)false); queue_system_status.GetQueue().Enqueue((object)message3); lastmessage = DateTime.Now; Thread.Sleep(1); } if ((DateTime.Now - GlobalHeartBeat.GetGlobalTime()).TotalMinutes > 10) { log.LogEvent("本模块供血不足,线程即将死亡"); KeyValuePair <string, object> message = new KeyValuePair <string, object>("THREAD_MARKET", (object)false); queue_system_status.GetQueue().Enqueue((object)message); break; } int count = 0; while (count < 100) { try { info = client.DeQueueInfo(); } catch { break; } if (info == null) { break; } else { lock (Queue_Operation_Data.GetQueue()) { Queue_Operation_Data.GetQueue().Enqueue((object)info); } } count++; } } }
private void threadproc() { while (true) { Thread.Sleep(1); if ((DateTime.Now - GlobalHeartBeat.GetGlobalTime()).TotalMinutes > 5) { log.LogEvent("由于供血不足,委托查询线程即将退出。"); break; } //单次循环最多查询100个交易的委托情况 int maxCount = 100; if (!_classTradeStock.getConnectStatus()) { _classTradeStock.Init(login, ErrorMsg); } if (lastmessagetime.Second != DateTime.Now.Second) { KeyValuePair <string, object> message1 = new KeyValuePair <string, object>("THREAD_ENTRUST_WORKER", (object)(DateTime.Now)); queue_system_status.GetQueue().Enqueue((object)message1); lastmessagetime = DateTime.Now; } while (maxCount > 0 && queue_query_entrust.GetQueueNumber() > 0) { maxCount--; //获取新委托 QueryEntrustOrderStruct_M item = (QueryEntrustOrderStruct_M)queue_query_entrust.GetQueue().Dequeue(); string err = string.Empty; //查询委托及获取实例 managedEntrustreturnstruct ret = new managedEntrustreturnstruct(); //ordersysid 首字母 为 'T' 是测试交易 if (item.OrderSysID.Length > 0 && item.OrderSysID[0] == 'T') { var temps = test.QueryEntrust(item); ret = temps; } else { var temps = _classTradeStock.QueryEntrust(item, err); if (temps.Length == 0) { continue; } ret = temps.ToList()[0]; } if (ret == null) { continue; } OrderViewItem order = new OrderViewItem( item.OrderRef.ToString(), ret.cOrderSysID, ret.cSecurity_code, item.Direction.ToString(), "NA", ret.nVolumeTotalOriginal.ToString(), ret.nVolumeTotal.ToString(), item.OrderPrice.ToString(), GetStatusWord(ret.cOrderStatus), ret.cInsertTime); if (!UserRequestMap.GetInstance().Keys.Contains(item.OrderRef)) { UserRequestMap.GetInstance().AddOrUpdate(item.OrderRef, item.User, (key, oldValue) => oldValue = item.User); } String USERNAME = UserRequestMap.GetInstance()[item.OrderRef]; TradeMonitor.Instance.updateOrderList(USERNAME, order); //目前仅考虑 1对1 返回的情况,不考虑出现1对多 ,类似基金交易的情况 //将委托变动返回更新数据库 if (DBAccessLayer.DBEnable == true) { //更新数据,记录入数据库 ThreadPool.QueueUserWorkItem(new WaitCallback(DBAccessLayer.UpdateERRecord), (object)(ret)); //修改委托缓存数据 EntrustRecord.ModifyEntrustPosition(item.OrderRef, Convert.ToInt32(ret.frozen_amount), Convert.ToDouble(ret.frozen_money)); //此处判断,相应代码的委托是否完成 //此处逻辑需要待返回报文内容确认后修改 //测试使用 if ((ret.cOrderStatus.ToString() != ((int)(EntrustStatus.Dealed)).ToString()) && (!(ret.cOrderStatus.ToString() == ((int)EntrustStatus.Canceled).ToString() && ret.nVolumeTotal == 0))) { queue_query_entrust.GetQueue().Enqueue((object)item); continue; } //委托已经完成,进入成交状态查询 managedBargainreturnstruct bargin = new managedBargainreturnstruct(); if (item.OrderSysID.Length > 0 && item.OrderSysID[0] == 'T') { bargin = test.QueryTrader(item); } else { var retbargin = _classTradeStock.QueryTrader(item, err).ToList(); //将查询信息记录成交表 if (retbargin.Count > 0) { bargin = retbargin.ToList()[0]; } } bargin.strategyId = item.StrategyId; bargin.direction = item.Direction; bargin.User = USERNAME; bargin.OrderType = Convert.ToSByte("49"); if (ret.cOrderStatus.ToString() == ((int)(EntrustStatus.Dealed)).ToString()) { bargin.OrderMark = Deal_Status.DEAL; } else if (ret.cOrderStatus.ToString() == ((int)EntrustStatus.Canceled).ToString()) { bargin.OrderMark = Deal_Status.CANCELED; } else if (ret.nVolumeTotal == 0) { bargin.OrderMark = Deal_Status.PARTIALDEAL; } ThreadPool.QueueUserWorkItem(new WaitCallback(DBAccessLayer.CreateDLRecord), (object)bargin); EntrustRecord.DeleteEntrustRecord(item.OrderRef); ThreadPool.QueueUserWorkItem(new WaitCallback(DBAccessLayer.DeleteERRecord), (object)(item.OrderRef)); //更新持仓列表 if (ret.nVolumeTraded != 0) { //需要修改数据 //仅存在成交记录时才更改持仓 ThreadPool.QueueUserWorkItem(new WaitCallback(DBAccessLayer.UpdateCCRecords), (object)bargin); } } } } }
/// <summary> /// 期货交易工作线程 /// </summary> /// <param name="para"></param> public void FutureTradeSubThreadProc(object para) { string ErrorMsg = string.Empty; //令该线程为前台线程 Thread.CurrentThread.IsBackground = true; DateTime lastmessagetime = DateTime.Now; TradeParaPackage _tpp = (TradeParaPackage)para; //当前线程编号 int _threadNo = _tpp._threadNo; sublog.LogEvent("线程 :" + _threadNo.ToString() + " 开始执行"); //用作发送心跳包的时间标记 DateTime _markedTime = DateTime.Now; //控制期货交易线程执行 bool _threadRunControl = true; //获取未成交期货委托 List <ER_TAOLI_TABLE> ERs = DBAccessLayer.GetInCompletedERRecord("F"); if (ERs != null) { foreach (ER_TAOLI_TABLE ER in ERs) { decimal price = (ER.ER_VOLUME_TOTAL_ORIGINAL == 0 ? 0 : Convert.ToDecimal(ER.ER_FROZEN_MONEY / ER.ER_VOLUME_TOTAL_ORIGINAL)); string code = ER.ER_CODE; TradeRecord.GetInstance().SubscribeIncompleteOrder("F", ER.ER_CODE, ER.ER_ID, ER.ER_DIRECTION.ToString(), Convert.ToInt16(ER.ER_VOLUME_TOTAL_ORIGINAL), price, Convert.ToInt16(ER.ER_ORDER_REF), Convert.ToInt16("0"), Convert.ToInt16(ER.ER_OFFSETFLAG.Trim()), ER.ER_USER); } } while (_threadRunControl) { //初始化完成前,不接收实际交易 queue_future_excuteThread.SetThreadBusy(_threadNo); _client.Connect(); //状态 DISCONNECTED -> CONNECTED while (status != FutureTradeThreadStatus.CONNECTED) { Thread.Sleep(10); } _client.ReqUserLogin(); //状态 CONNECTED -> LOGIN while (status != FutureTradeThreadStatus.LOGIN) { Thread.Sleep(10); } if (ERs != null) { foreach (ER_TAOLI_TABLE ER in ERs) { _client.QryOrder(ER.ER_ORDER_EXCHANGE_ID, "", "", "", ER.ER_ID.PadLeft(12)); } } while (true) { Thread.Sleep(10); if ((DateTime.Now - GlobalHeartBeat.GetGlobalTime()).TotalMinutes > 10) { sublog.LogEvent("线程 :" + _threadNo.ToString() + "心跳停止 , 最后心跳 : " + GlobalHeartBeat.GetGlobalTime().ToString()); _threadRunControl = false; break; } if (lastmessagetime.Second != DateTime.Now.Second) { KeyValuePair <string, object> message1 = new KeyValuePair <string, object>("THREAD_FUTURE_TRADE_WORKER", (object)_threadNo); queue_system_status.GetQueue().Enqueue((object)message1); } if (queue_future_excuteThread.GetQueue(_threadNo).Count < 2) { queue_future_excuteThread.SetThreadFree(_threadNo); status = FutureTradeThreadStatus.FREE; } else { status = FutureTradeThreadStatus.BUSY; } if (queue_future_excuteThread.GetQueue(_threadNo).Count > 0) { List <TradeOrderStruct> trades = (List <TradeOrderStruct>)queue_future_excuteThread.FutureExcuteQueue[_threadNo].Dequeue(); if (trades == null) { continue; } if (trades.Count > 0) { sublog.LogEvent("线程 :" + _threadNo.ToString() + " 执行交易数量 : " + trades.Count); } if (trades.Count == 0) { continue; } foreach (TradeOrderStruct order in trades) { CTP_CLI.CThostFtdcInputOrderField_M args = new CThostFtdcInputOrderField_M(); //填写委托参数 args.BrokerID = CommConfig.BROKER; args.InvestorID = CommConfig.INVESTOR; args.InstrumentID = order.cSecurityCode; args.Direction = Convert.ToByte(order.cTradeDirection); args.CombOffsetFlag_0 = Convert.ToByte(order.cOffsetFlag); args.VolumeTotalOriginal = Convert.ToInt16(order.nSecurityAmount); args.LimitPrice = Convert.ToDouble(order.dOrderPrice); args.OrderRef = order.OrderRef.ToString(); args.OrderPriceType = Convert.ToByte("50"); args.CombHedgeFlag_0 = Convert.ToByte('1'); args.MinVolume = 1; args.ContingentCondition = Convert.ToByte('1'); args.TimeCondition = Convert.ToByte('3'); args.VolumeCondition = Convert.ToByte('1'); args.UserID = order.cUser; args.ForceCloseReason = Convert.ToByte('0'); args.IsAutoSuspend = 0; args.UserForceClose = 0; //提交报单委托 //步骤完成后线程任务结束 //返回工作交由回调函数处理 _client.OrderInsert(args); //创建记录 RecordItem item = new RecordItem(); item.AveragePrice = 0; item.Code = order.cSecurityCode; item.CombOffsetFlag = Convert.ToInt16(order.cOffsetFlag); item.OrderRef = order.OrderRef; item.OrderStatus = 0; item.OrderSysID = "0"; item.Orientation = order.cTradeDirection; item.Price = Convert.ToDecimal(order.dOrderPrice); item.Status = TradeDealStatus.ORDERING; item.StrategyId = order.belongStrategy; item.Type = "1"; item.VolumeTotalOriginal = item.VolumeTotal = Convert.ToInt32(order.nSecurityAmount); item.VolumeTraded = 0; item.User = order.cUser; TradeRecord.GetInstance().CreateOrder(order.OrderRef, item); } } } } }
private void ThreadProc() { //初始化子线程 int futureNum = CONFIG.FUTURE_TRADE_THREAD_NUM; DateTime lastmessage = DateTime.Now; List <Task> TradeThreads = new List <Task>(); log.LogEvent("期货交易控制子线程启动: 初始化交易线程数 :" + futureNum.ToString()); //启动心跳和交易线程 Task.Factory.StartNew(() => HeartBeatThreadProc((object)futureNum)); for (int i = 0; i < futureNum; i++) { TradeParaPackage tpp = new TradeParaPackage(); tpp._threadNo = (i); object para = (object)tpp; FutureTrade trade = new FutureTrade(); trade.SetLog(sublog); TradeThreads.Add(Task.Factory.StartNew(() => trade.FutureTradeSubThreadProc(para))); } //此时按照配置,共初始化CONFIG.FUTURE_TRADE_THREAD_NUM 数量交易线程 // 交易线程按照方法 FutureTradeSubThreadProc 执行 //Loop 完成对于子线程的监控 //每一秒钟执行一次自检 //自检包含任务: // 1. 对每个线程,判断当前交易执行时间,超过 CONFIG.FUTURE_TRADE_OVERTIME 仍未收到返回将会按照 该参数备注执行 // 2. 判断当前线程空闲状态,整理可用线程列表 // 3. 若当前存在可用线程,同时消息队列(queue_prdTrade_FutureTradeMonitor) // 也包含新的消息送达,则安排线程处理交易 // 4. 记录每个交易线程目前处理的交易内容,并写入数据库 while (true) { Thread.Sleep(10); if ((DateTime.Now - GlobalHeartBeat.GetGlobalTime()).TotalMinutes > 10) { log.LogEvent("本模块供血不足,线程即将死亡"); break; } //获取下一笔交易 List <TradeOrderStruct> next_trade = new List <TradeOrderStruct>(); if (lastmessage.Second != DateTime.Now.Second) { KeyValuePair <string, object> message1 = new KeyValuePair <string, object>("THREAD_FUTURE_TRADE_MONITOR", (object)true); queue_system_status.GetQueue().Enqueue((object)message1); lastmessage = DateTime.Now; } if (QUEUE_FUTURE_TRADE.GetQueueNumber() > 0) { lock (QUEUE_FUTURE_TRADE.GetQueue().SyncRoot) { if (QUEUE_FUTURE_TRADE.GetQueue().Count > 0) { next_trade = (List <TradeOrderStruct>)QUEUE_FUTURE_TRADE.GetQueue().Dequeue(); } if (next_trade.Count > 0) { log.LogEvent("期货交易所出队交易数量:" + next_trade.Count.ToString()); } } } if (next_trade.Count == 0) { continue; } //此时next_trade中包含了交易参数 //判断空闲的线程 //利用随机选择,保证线程的平均使用 Random ran = new Random(); bool _bSearch = true; int _tNo = 0; //默认测试用户下,直接使用0号测试线程 if (next_trade[0].cUser != DebugMode.TestUser) { while (_bSearch) { _tNo = ran.Next(0, futureNum); if (queue_future_excuteThread.GetThreadIsAvailiable(_tNo)) { _bSearch = false; } } } log.LogEvent("安排线程 : " + _tNo + " 执行交易 数量: " + next_trade.Count); //选择第 _tNo 个线程执行交易 queue_future_excuteThread.GetQueue(_tNo).Enqueue((object)next_trade); queue_future_excuteThread.SetThreadBusy(_tNo); //************************************ //将交易发送到相应执行线程后需要做的事情 //************************************ } Thread.CurrentThread.Abort(); }
/// <summary> /// 策略管理线程工作函数 /// 任务: /// 1. 获取用户请求队列中的指令 /// 2. 巡检工作组中订阅列表修改 /// </summary> private void ThreadProc() { while (true) { if ((DateTime.Now - GlobalHeartBeat.GetGlobalTime()).TotalMinutes > 15) { log.LogEvent("系统供血模块无响应,策略管理线程即将停止!"); KeyValuePair <string, object> message2 = new KeyValuePair <string, object>("THREAD_STRATEGY_MANAGEMENT", (object)false); queue_system_status.GetQueue().Enqueue((object)message2); //管理策略线程退出前,对正在运行的工作策略执行“绞杀”,并维护数据库记录,这个过程称为 grace broken break; } while (QCommands.Count > 0) { object obj = QCommands.Dequeue(); #region 指令类型判断 if (obj is OPENCREATE) { RecruitNewWorker(obj); } else if (obj is OPENMODIFY) { UpdateWorker(obj); } else if (obj is OPENALLOW) { OPENALLOW value = (OPENALLOW)obj; AllowOperater((object)obj); } else if (obj is OPENRUN) { OPENRUN value = (OPENRUN)obj; RunOperater((object)value); } else if (obj is OPENDELETE) { DeleteWorker(obj); } else if (obj is CLOSECREATE) { RecruitNewWorker(obj); } else if (obj is CLOSEMODIFY) { UpdateWorker(obj); } else if (obj is CLOSERUN) { CLOSERUN value = (CLOSERUN)obj; RunOperater((object)value); } else if (obj is CLOSEALLOW) { CLOSEALLOW value = (CLOSEALLOW)obj; AllowOperater((object)obj); } else if (obj is CLOSEDELETE) { DeleteWorker(obj); } else { continue; } #endregion } if (DateTime.Now.Second % 2 == 0) { if (_logUpdateTime.Second != DateTime.Now.Second) { _logUpdateTime = DateTime.Now; KeyValuePair <string, object> message1 = new KeyValuePair <string, object>("THREAD_STRATEGY_MANAGEMENT", (object)true); queue_system_status.GetQueue().Enqueue((object)message1); int count_0 = (from item in WorkersStratus where item.Value == 0 select item).Count(); int count_12 = (from item in WorkersStratus where item.Value == 1 || item.Value == 2 select item).Count(); if (DateTime.Now.Second % 31 == 0 || DateTime.Now.Second % 32 == 0) { log.LogEvent("运行策略: " + (count_0 + count_12).ToString() + "\n问题或结束策略: " + count_0.ToString()); } Dictionary <String, StrategyInfo> strategyInfo = new Dictionary <string, StrategyInfo>(); foreach (var item in Workers) { WorkersStratus[item.Key] = item.Value.Status; item.Value.Status = 0; StrategyInfo info = new StrategyInfo() { BelongUser = item.Value.User, StrType = item.Value.Type, Contract = item.Value.CT, Status = item.Value.Status, StrategyInstanceID = item.Value.StrategyInstanceID, HandNum = item.Value.HD, SubscribeList = new List <string>(item.Value.SubscribeList.Count) }; strategyInfo.Add(item.Value.StrategyInstanceID, info); foreach (string s in item.Value.SubscribeList) { info.SubscribeList.Add(s); } } int count = Workers.Count; KeyValuePair <string, object> message2 = new KeyValuePair <string, object>("STRATEGY_N", (object)count); queue_system_status.GetQueue().Enqueue((object)message2); Dictionary <string, StrategyInfo> value = new Dictionary <string, StrategyInfo>(); foreach (KeyValuePair <string, StrategyWorker> pair in Workers) { StrategyInfo info = new StrategyInfo() { BelongUser = pair.Value.User, Contract = pair.Value.CT, HandNum = pair.Value.HD, Status = pair.Value.Status, StrategyInstanceID = pair.Value.StrategyInstanceID, StrType = pair.Value.Type, SubscribeList = pair.Value.SubscribeList }; value.Add(pair.Value.StrategyInstanceID, info); } KeyValuePair <string, object> message3 = new KeyValuePair <string, object>("STRATEGY_P", (object)value); queue_system_status.GetQueue().Enqueue((object)message3); KeyValuePair <string, object> message4 = new KeyValuePair <string, object>("THREAD_STRATEGY_WORKER", (object)WorkersStratus); queue_system_status.GetQueue().Enqueue((object)message4); } } //巡检工作组订阅内容修改 try { CheckSubscribeUpdate(); } catch (Exception ex) { DBAccessLayer.LogSysInfo("StrategyMonitorClass-ThreadProc", ex.ToString()); ex.ToString(); } Thread.Sleep(10); } }
/// <summary> /// 股票总控线程函数 /// </summary> private static void StockThreadProc() { log.LogEvent("股票退货线程启动!"); MCStockLib.managedStockClass _classTradeStock = new managedStockClass(); MCStockLib.managedLogin login = new managedLogin(CommConfig.Stock_ServerAddr, CommConfig.Stock_Port, CommConfig.Stock_Account, CommConfig.Stock_BrokerID, CommConfig.Stock_Password, CommConfig.Stock_InvestorID); //标记心跳包发送时间 DateTime _markedTime = DateTime.Now; DateTime lastmessage = DateTime.Now; string ErrorMsg = string.Empty; //初始化通信 //功能1 _classTradeStock.Init(login, ErrorMsg); while (true) { Thread.Sleep(10); if ((DateTime.Now - GlobalHeartBeat.GetGlobalTime()).TotalMinutes > 10) { log.LogEvent("股票退货线程心跳停止 , 最后心跳 : " + GlobalHeartBeat.GetGlobalTime().ToString()); KeyValuePair <string, object> message1 = new KeyValuePair <string, object>("THREAD_Stock_Refund_Control_MONITOR", (object)false); queue_system_status.GetQueue().Enqueue((object)message1); break; } if (lastmessage.Second != DateTime.Now.Second) { KeyValuePair <string, object> message1 = new KeyValuePair <string, object>("THREAD_Stock_Refund_Control_MONITOR", (object)true); queue_system_status.GetQueue().Enqueue((object)message1); lastmessage = DateTime.Now; } if (_markedTime.Minute != DateTime.Now.Minute) { //发送心跳包 //功能2 //_stockTradeAPI.heartBeat(); _classTradeStock.HeartBeat(); _markedTime = DateTime.Now; } if (queue_stock_refund_thread.GetQueueNumber() > 0) { RefundStruct refundItem = (RefundStruct)queue_stock_refund_thread.GetQueue().Dequeue(); QueryEntrustOrderStruct_M item = new QueryEntrustOrderStruct_M() { Code = refundItem.SecurityCode, Direction = Convert.ToInt32(refundItem.Direction), ExchangeID = (refundItem.ExchangeId == "SH" ? "1" : "2"), OrderPrice = 0, //撤单不用考虑价格 OrderRef = Convert.ToInt32(refundItem.OrderRef), OrderSysID = refundItem.OrderSysId, SecurityType = (sbyte)115, StrategyId = string.Empty //撤单不考虑策略编号 }; if (!_classTradeStock.getConnectStatus()) { _classTradeStock.Init(login, ErrorMsg); } String err = String.Empty; //发出撤单交易 _classTradeStock.CancelTrade(item, err); log.LogEvent("股票撤单已发出,本地编号:" + refundItem.OrderRef + " 系统编号:" + refundItem.OrderSysId); } } }
/// <summary> /// 退货总控线程函数 /// </summary> private static void ThreadProc() { //初始化股票 和 期货退货线程 DateTime lastmessage = DateTime.Now; log.LogEvent("退货控制线程启动"); Task StockRefundThread = new Task(StockThreadProc); Task FutureRefundThread = new Task(FutureThreadProc); StockRefundThread.Start(); FutureRefundThread.Start(); while (true) { Thread.Sleep(10); if ((DateTime.Now - GlobalHeartBeat.GetGlobalTime()).TotalMinutes > 10) { log.LogEvent("本模块供血不足,线程即将死亡"); KeyValuePair <string, object> message1 = new KeyValuePair <string, object>("THREAD_Refund_Control_MONITOR", (object)false); queue_system_status.GetQueue().Enqueue((object)message1); break; } if (lastmessage.Second != DateTime.Now.Second) { KeyValuePair <string, object> message1 = new KeyValuePair <string, object>("THREAD_Refund_Control_MONITOR", (object)true); queue_system_status.GetQueue().Enqueue((object)message1); lastmessage = DateTime.Now; } //获取下一笔交易 RefundStruct next_trade = new RefundStruct(); if (queue_refund_thread.GetQueueNumber() > 0) { lock (queue_refund_thread.GetQueue().SyncRoot) { if (queue_refund_thread.GetQueue().Count > 0) { next_trade = (RefundStruct)queue_refund_thread.GetQueue().Dequeue(); } if (next_trade != null && next_trade.OrderRef != string.Empty && next_trade.OrderSysId != string.Empty) { log.LogEvent("退货控制线程收到退货请求,交易编号:" + next_trade.OrderRef); } } } if (next_trade.OrderRef == null || next_trade.OrderRef == String.Empty || next_trade.OrderSysId == String.Empty) { continue; } //此时内存中包含了即将被进行的交易 next_trade.Direction = next_trade.Direction.Trim(); next_trade.ExchangeId = next_trade.ExchangeId.Trim(); next_trade.OffSetFlag = next_trade.OffSetFlag.Trim(); next_trade.OrderRef = next_trade.OrderRef.Trim(); next_trade.OrderSysId = next_trade.OrderSysId.Trim(); next_trade.SecurityCode = next_trade.SecurityCode.Trim(); next_trade.SecurityType = next_trade.SecurityType.Trim(); if (next_trade.SecurityType.ToUpper() == "S") { //股票退货 queue_stock_refund_thread.GetQueue().Enqueue(next_trade); } else if (next_trade.SecurityType.ToUpper() == "F") { //期货退货 queue_future_refund_thread.GetQueue().Enqueue(next_trade); } } Thread.CurrentThread.Abort(); }
/// <summary> /// 期货总控线程函数 /// </summary> private static void FutureThreadProc() { log.LogEvent("期货退货线程启动!"); string ErrorMsg = string.Empty; DateTime lastmessage = DateTime.Now; CTP_CLI.CCTPClient _client = new CTP_CLI.CCTPClient(CommConfig.INVESTOR, CommConfig.PASSWORD, CommConfig.BROKER, CommConfig.ADDRESS); _client.FrontConnected += _client_FrontConnected; _client.FrontDisconnected += _client_FrontDisconnected; _client.RspUserLogin += _client_RspUserLogin; //报单变化回调函数 _client.RtnOrder += FutureTrade._client_RtnOrder; //成交变化回调函数 _client.RtnTrade += FutureTrade._client_RtnTrade; //报单修改操作回调函数(暂时不用) _client.RspOrderAction += FutureTrade._client_RspOrderAction; //报单失败回调函数 _client.RspOrderInsert += FutureTrade._client_RspOrderInsert; //报单问题回调函数 _client.ErrRtnOrderInsert += FutureTrade._client_ErrRtnOrderInsert; _client.Connect(); //状态 DISCONNECTED -> CONNECTED while (status != FutureTradeThreadStatus.CONNECTED) { Thread.Sleep(10); } _client.ReqUserLogin(); //状态 CONNECTED -> LOGIN while (status != FutureTradeThreadStatus.LOGIN) { Thread.Sleep(10); } while (true) { if ((DateTime.Now - GlobalHeartBeat.GetGlobalTime()).TotalMinutes > 10) { log.LogEvent("期货退货线程心跳停止 , 最后心跳 : " + GlobalHeartBeat.GetGlobalTime().ToString()); KeyValuePair <string, object> message1 = new KeyValuePair <string, object>("THREAD_Future_Refund_Control_MONITOR", (object)false); queue_system_status.GetQueue().Enqueue((object)message1); break; } if (lastmessage.Second != DateTime.Now.Second) { KeyValuePair <string, object> message1 = new KeyValuePair <string, object>("THREAD_Future_Refund_Control_MONITOR", (object)true); queue_system_status.GetQueue().Enqueue((object)message1); lastmessage = DateTime.Now; } Thread.Sleep(10); if (queue_future_refund_thread.GetQueueNumber() > 0) { RefundStruct refundItem = (RefundStruct)queue_future_refund_thread.GetQueue().Dequeue(); RecordItem record = TradeRecord.GetInstance().getOrderInfo(Convert.ToInt32(refundItem.OrderRef)); refundItem.ExchangeId = record.ExchangeID; CTP_CLI.CThostFtdcInputOrderActionField_M item = new CTP_CLI.CThostFtdcInputOrderActionField_M() { BrokerID = CommConfig.BROKER, ExchangeID = refundItem.ExchangeId, OrderSysID = refundItem.OrderSysId.PadLeft(12), InvestorID = CommConfig.INVESTOR, ActionFlag = Convert.ToByte('0'), //删除标志 THOST_FTDC_AF_Delete InstrumentID = record.Code }; _client.ReqOrderAction(item); } } }
private void ThreadProc3() { DateTime lastmessage = DateTime.Now; MarketData info = new MarketData(); while (true) { if (DateTime.Now.Second != lastmessage.Second) { KeyValuePair <string, object> message = new KeyValuePair <string, object>("THREAD_MARKET_3", (object)false); queue_system_status.GetQueue().Enqueue((object)message); lastmessage = DateTime.Now; Thread.Sleep(1); } if ((DateTime.Now - GlobalHeartBeat.GetGlobalTime()).TotalMinutes > 10) { log.LogEvent("本模块供血不足,线程即将死亡"); KeyValuePair <string, object> message = new KeyValuePair <string, object>("THREAD_MARKET", (object)false); queue_system_status.GetQueue().Enqueue((object)message); break; } Thread.Sleep(1); if (Queue_Operation_Data_2.GetQueueNumber() > 0) { try { lock (Queue_Operation_Data_2.SyncLock) info = (MarketData)Queue_Operation_Data_2.GetQueue().Dequeue(); } catch { info = null; } } if (info == null || info.Code == null) { continue; } lock (StockTable) { if (StockTable.ContainsKey(info.Code)) { StockTable.Remove(info.Code); } StockTable.Add(info.Code, info); } if (!subscribeList.Keys.Contains(info.Code)) { try { subscribeList.Add(info.Code, new List <String>()); } catch { continue; } } if (subscribeList.Keys.Contains(info.Code)) { //如果没有实例订阅过该股票,就不用管了 List <String> _relatedStrategy = subscribeList[info.Code]; foreach (String strategy in _relatedStrategy) { if (refStrategyQueue.Keys.Contains(strategy)) { try { refStrategyQueue[strategy].Enqueue((object)info); } catch { break; } } else { //如果发现策略实例包含工作列表,却不包含消息队列,则应该报错。 continue; } } } } }
private void TreadProc2() { //发现行情有变动,更新本地股市 DateTime lastmessage = DateTime.Now; while (true) { Thread.Sleep(1); if (DateTime.Now.Second != lastmessage.Second) { KeyValuePair <string, object> message = new KeyValuePair <string, object>("THREAD_MARKET_2", (object)false); queue_system_status.GetQueue().Enqueue((object)message); lastmessage = DateTime.Now; //更新本地行情列表,每秒一次 updateNewSubscribeList(); Thread.Sleep(1); } if ((DateTime.Now - GlobalHeartBeat.GetGlobalTime()).TotalMinutes > 10) { log.LogEvent("本模块供血不足,线程即将死亡"); KeyValuePair <string, object> message = new KeyValuePair <string, object>("THREAD_MARKET", (object)false); queue_system_status.GetQueue().Enqueue((object)message); break; } MarketData info = null; lock (Queue_Operation_Data.GetQueue()) { if (Queue_Operation_Data.GetQueueNumber() > 0) { info = (MarketData)Queue_Operation_Data.GetQueue().Dequeue(); } } if (info == null) { continue; } string key = info.Code; if (key.Contains(".")) { key = key.Split('.')[0]; } lock (MarketPrice.market) { if (MarketPrice.market.ContainsKey(info.Code)) { MarketPrice.market[info.Code] = info.Match; } else { MarketPrice.market.Add(info.Code, info.Match); } } if (DateTime.Now.Second % 2 == 0) { lock (Queue_Cal_Market.SyncLock) { Queue_Cal_Market.GetQueue().Enqueue((object)info.Time); } } lock (Queue_Operation_Data_2.SyncLock) { Queue_Operation_Data_2.GetQueue().Enqueue((object)info); } } }
private static void ThreadProc() { //初始化子线程 int stockNum = CONFIG.STOCK_TRADE_THREAD_NUM; DateTime lastmessage = DateTime.Now; List <Task> TradeThreads = new List <Task>(); log.LogEvent("股票交易控制子线程启动: 初始化交易线程数 :" + stockNum.ToString()); //启动心跳和交易线程 Task.Factory.StartNew(() => HeartBeatThreadProc((object)stockNum)); for (int i = 0; i < stockNum; i++) { TradeParaPackage tpp = new TradeParaPackage(); tpp._threadNo = (i); object para = (object)tpp; TradeThreads.Add(Task.Factory.StartNew(() => StockTradeSubThreadProc(para))); } //此时按照配置,共初始化CONFIG.STOCK_TRADE_THREAD_NUM 数量交易线程 // 交易线程按照方法 StockTradeSubThreadProc 执行 //Loop 完成对于子线程的监控 //每一秒钟执行一次自检 //自检包含任务: // 1. 对每个线程,判断当前交易执行时间,超过 CONFIG.STOCK_TRADE_OVERTIME 仍未收到返回将会按照 该参数备注执行 // 2. 判断当前线程空闲状态,整理可用线程列表 // 3. 若当前存在可用线程,同时消息队列(queue_prdTrade_SH_tradeMonitor,queue_prdTrade_SZ_tradeMonitor) // 也包含新的消息送达,则安排线程处理交易 // 4. 记录每个交易线程目前处理的交易内容,并写入数据库 while (true) { Thread.Sleep(1); String logword = String.Empty; //获取下一笔交易 List <TradeOrderStruct> next_trade = new List <TradeOrderStruct>(); if (QUEUE_SH_TRADE.GetQueueNumber() > 0) { lock (QUEUE_SH_TRADE.GetQueue().SyncRoot) { if (QUEUE_SH_TRADE.GetQueue().Count > 0) { next_trade = (List <TradeOrderStruct>)QUEUE_SH_TRADE.GetQueue().Dequeue(); } if (next_trade.Count > 0) { log.LogEvent("上海交易所出队交易数量:" + next_trade.Count.ToString()); } } } else if (QUEUE_SZ_TRADE.GetQueueNumber() > 0) { lock (QUEUE_SZ_TRADE.GetQueue().SyncRoot) { if (QUEUE_SZ_TRADE.GetQueue().Count > 0) { next_trade = (List <TradeOrderStruct>)QUEUE_SZ_TRADE.GetQueue().Dequeue(); } log.LogEvent("深圳交易所出队交易数量:" + next_trade.Count.ToString()); } } if (next_trade.Count == 0) { if ((DateTime.Now - GlobalHeartBeat.GetGlobalTime()).TotalMinutes > 10) { log.LogEvent("本模块供血不足,线程即将死亡"); KeyValuePair <string, object> message1 = new KeyValuePair <string, object>("THREAD_STOCK_TRADE_MONITOR", (object)false); queue_system_status.GetQueue().Enqueue((object)message1); break; } if (lastmessage.Second != DateTime.Now.Second) { KeyValuePair <string, object> message1 = new KeyValuePair <string, object>("THREAD_STOCK_TRADE_MONITOR", (object)true); try { queue_system_status.GetQueue().Enqueue((object)message1); lastmessage = DateTime.Now; } catch { //do nothing } } continue; } else { //此时内存中包含了即将被进行的交易 //按照15个一组分割交易 List <TradeOrderStruct> tradeGroup = new List <TradeOrderStruct>(); foreach (TradeOrderStruct trade in next_trade) { if (tradeGroup.Count < 15) { tradeGroup.Add(trade); if (tradeGroup.Count == 15) { //判断空闲的线程 //利用随机选择,保证线程的平均使用 String para = JsonConvert.SerializeObject(tradeGroup); ThreadPool.QueueUserWorkItem(new WaitCallback(ChooseThread), (object)para); logword += " 发送交易: " + " 时间: " + DateTime.Now.ToString("yyyy-MM-dd hh-mm-ss") + " : " + DateTime.Now.Millisecond.ToString() + "\r\n"; tradeGroup.Clear(); } } } if (tradeGroup.Count > 0) { //判断空闲的线程 //利用随机选择,保证线程的平均使用 String para = JsonConvert.SerializeObject(tradeGroup); ThreadPool.QueueUserWorkItem(new WaitCallback(ChooseThread), (object)para); logword += " 发送交易: " + " 时间: " + DateTime.Now.ToString("yyyy-MM-dd hh-mm-ss") + " : " + DateTime.Now.Millisecond.ToString() + "\r\n"; tradeGroup.Clear(); } GlobalTestLog.LogInstance.LogEvent(logword); } } Thread.CurrentThread.Abort(); }
/// <summary> /// 执行交易线程处理逻辑 /// 包含功能: /// 1. 连接股票交易所(上海,深圳) /// 2. 心跳包发送/接收 /// 3. 发送交易,等待响应 /// </summary> private static void StockTradeSubThreadProc(object para) { MCStockLib.managedStockClass _classTradeStock = new managedStockClass(); MCStockLib.managedLogin login = new managedLogin(CommConfig.Stock_ServerAddr, CommConfig.Stock_Port, CommConfig.Stock_Account, CommConfig.Stock_BrokerID, CommConfig.Stock_Password, CommConfig.Stock_InvestorID); string ErrorMsg = string.Empty; bool DebugMark = false; //测试交易标志 StockTradeTest test = new StockTradeTest(); //测试类 //令该线程为前台线程 Thread.CurrentThread.IsBackground = true; TradeParaPackage _tpp = (TradeParaPackage)para; //当前线程编号 int _threadNo = _tpp._threadNo; sublog.LogEvent("线程 :" + _threadNo.ToString() + " 开始执行"); //用作发送心跳包的时间标记 DateTime _markedTime = DateTime.Now; DateTime lastmessagetime = DateTime.Now; //初始化通信 //功能1 _classTradeStock.Init(login, ErrorMsg); while (true) { Thread.Sleep(10); if ((DateTime.Now - GlobalHeartBeat.GetGlobalTime()).TotalMinutes > 10) { sublog.LogEvent("线程 :" + _threadNo.ToString() + "心跳停止 , 最后心跳 : " + GlobalHeartBeat.GetGlobalTime().ToString()); break; } //Thread.CurrentThread.stat if (_markedTime.Minute != DateTime.Now.Minute) { //发送心跳包 //功能2 //_stockTradeAPI.heartBeat(); _classTradeStock.HeartBeat(); _markedTime = DateTime.Now; } if (lastmessagetime.Second != DateTime.Now.Second) { KeyValuePair <string, object> message1 = new KeyValuePair <string, object>("THREAD_STOCK_TRADE_WORKER", (object)_threadNo); try { queue_system_status.GetQueue().Enqueue((object)message1); lastmessagetime = DateTime.Now; } catch { //do nothing } } //if (!_classTradeStock.getConnectStatus()) //{ // _classTradeStock.Init(login, ErrorMsg); //} if (queue_stock_excuteThread.GetQueue(_threadNo).Count < 2) { queue_stock_excuteThread.SetThreadFree(_threadNo); } if (queue_stock_excuteThread.GetQueue(_threadNo).Count > 0) { List <TradeOrderStruct> Queuetrades = (List <TradeOrderStruct>)queue_stock_excuteThread.StockExcuteQueues[_threadNo].Dequeue(); List <TradeOrderStruct> trades = new List <TradeOrderStruct>(); int eni = 0; while (true) { try { TradeOrderStruct trade = Queuetrades[eni]; trades.Add(new TradeOrderStruct() { belongStrategy = trade.belongStrategy, cExhcnageID = trade.cExhcnageID, cOffsetFlag = trade.cOffsetFlag, cOrderexecutedetail = trade.cOrderexecutedetail, cOrderLevel = trade.cOrderLevel, cOrderPriceType = trade.cOrderPriceType, cSecurityCode = trade.cSecurityCode, cSecurityType = trade.cSecurityType, cTradeDirection = trade.cTradeDirection, cUser = trade.cUser, dOrderPrice = trade.dOrderPrice, nSecurityAmount = trade.nSecurityAmount, OrderRef = trade.OrderRef, SecurityName = trade.SecurityName }); eni++; } catch { break; } } Guid tradeuuid = Guid.NewGuid(); if (trades == null || trades.Count == 0) { continue; } if (trades[0].cUser == DebugMode.TestUser) { DebugMark = true; } else { DebugMark = false; } if (trades.Count > 0) { sublog.LogEvent("线程 :" + _threadNo.ToString() + " 执行交易数量 : " + trades.Count); } if (!_classTradeStock.getConnectStatus()) { _classTradeStock.Init(login, ErrorMsg); } //根据消息队列中发来的消息数量判断调用的接口 //当内容大于1 ,调用批量接口 //当内容等于1, 调用单笔接口 queue_stock_excuteThread.SetUpdateTime(_threadNo); List <QueryEntrustOrderStruct_M> entrustorli = new List <QueryEntrustOrderStruct_M>(); if (trades.Count > 1) { //trades Random seed = new Random(); sublog.LogEvent("线程 :" + _threadNo.ToString() + "进入执行环节 , 忙碌状态: " + queue_stock_excuteThread.GetThreadIsAvailiable(_threadNo)); TradeOrderStruct_M[] tradesUnit = new TradeOrderStruct_M[15]; int i = 0; QueryEntrustOrderStruct_M[] entrustUnit = new QueryEntrustOrderStruct_M[15]; string s = string.Empty; foreach (TradeOrderStruct unit in trades) { tradesUnit[i] = CreateTradeUnit(unit); i++; } string user = trades[0].cUser; //GlobalTestLog.LogInstance.LogEvent("线程 :" + _threadNo.ToString() + " 发送交易: " + tradeuuid.ToString() + " 时间: " + DateTime.Now.ToString("yyyy-MM-dd hh-mm-ss") + " : " + DateTime.Now.Millisecond.ToString()); if (DebugMark == true) { test.BatchTradeTest(tradesUnit, trades.Count, out entrustUnit, out s); } else { entrustUnit = _classTradeStock.BatchTrade(tradesUnit, trades.Count, s); } //GlobalTestLog.LogInstance.LogEvent("线程 :" + _threadNo.ToString() + " 收到交易回报: " + tradeuuid.ToString() + " 时间: " + DateTime.Now.ToString("yyyy-MM-dd hh-mm-ss") + " : " + DateTime.Now.Millisecond.ToString()); if (entrustUnit != null && entrustUnit.ToList().Count() > 0) { i = -1; foreach (QueryEntrustOrderStruct_M unit in entrustUnit.ToList()) { i++; if (unit == null) { continue; } if (unit.OrderSysID != null && unit.OrderSysID != String.Empty && unit.OrderSysID != "0") { entrustorli.Add(unit); } else { //委托失败处理 GlobalErrorLog.LogInstance.LogEvent("获取委托号失败!用户: " + user + ",代码:" + unit.Code); } if (unit.Direction == 49) { //清除风控冷冻金额 //只有股票买入,才需要移除风控列表 accountMonitor.UpdateRiskFrozonAccount(user, unit.Code, tradesUnit[i].SecurityAmount * (-1), tradesUnit[i].SecurityAmount * tradesUnit[i].OrderPrice * (-1), "S", "0"); } } } } else if (trades.Count == 1) { //trades Random seed = new Random(); TradeOrderStruct_M tradesUnit = CreateTradeUnit(trades[0]); QueryEntrustOrderStruct_M entrustUnit = new QueryEntrustOrderStruct_M(); string s = string.Empty; string user = trades[0].cUser; //GlobalTestLog.LogInstance.LogEvent("发送交易: " + tradeuuid.ToString() + " 时间: " + DateTime.Now.ToString("yyyy-MM-dd hh-mm-ss") + " : " + DateTime.Now.Millisecond.ToString()); if (DebugMark == true) { test.SingleTradeTest(tradesUnit, out entrustUnit, out s); } else { _classTradeStock.SingleTrade(tradesUnit, entrustUnit, s); } //GlobalTestLog.LogInstance.LogEvent("收到交易回报: " + tradeuuid.ToString() + " 时间: " + DateTime.Now.ToString("yyyy-MM-dd hh-mm-ss") + " : " + DateTime.Now.Millisecond.ToString()); if (entrustUnit.OrderSysID != null && entrustUnit.OrderSysID != String.Empty && entrustUnit.OrderSysID != "0") { entrustorli.Add(entrustUnit); } else { //委托失败处理 GlobalErrorLog.LogInstance.LogEvent("获取委托号失败!用户: " + user + ",代码:" + tradesUnit.SecurityCode); } if (entrustUnit.Direction.ToString() == TradeOrientationAndFlag.StockTradeDirectionBuy) { //清除风控冷冻金额,只有买入需要清除风控列表 accountMonitor.UpdateRiskFrozonAccount(user, tradesUnit.SecurityCode, tradesUnit.SecurityAmount * (-1), tradesUnit.SecurityAmount * tradesUnit.OrderPrice * (-1), "S", tradesUnit.TradeDirection.ToString()); } } //********************************* // 交易成功后执行的特殊处理 // 交易生成委托存入数据库,并将委托送往查询成交线程 //********************************* if (trades.Count != 0) { //存入数据库 if (entrustorli.Count() == 0) { continue; } for (int i = 0; i < trades.Count; i++) { entrustorli[i].Code = trades[i].cSecurityCode; entrustorli[i].StrategyId = trades[0].belongStrategy; entrustorli[i].Direction = Convert.ToInt32(trades[i].cTradeDirection); entrustorli[i].OrderRef = Convert.ToInt32(trades[i].OrderRef); entrustorli[i].OrderPrice = trades[i].dOrderPrice; entrustorli[i].SecurityType = (sbyte)115; entrustorli[i].User = trades[i].cUser; ThreadPool.QueueUserWorkItem(new WaitCallback(DBAccessLayer.CreateERRecord), (object)(entrustorli[i])); queue_query_entrust.GetQueue().Enqueue((object)entrustorli[i]); ERecord record = new ERecord() { UserName = trades[i].cUser, Amount = trades[i].nSecurityAmount, Code = trades[i].cSecurityCode, ExchangeId = trades[i].cExhcnageID, OrderPrice = trades[i].dOrderPrice, OrderRef = trades[i].OrderRef, StrategyNo = trades[i].belongStrategy, SysOrderRef = entrustorli[i].OrderSysID, Direction = trades[i].cTradeDirection }; EntrustRecord.AddEntrustRecord(record); } } } } //线程结束 Thread.CurrentThread.Abort(); }