/// <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(); }