예제 #1
0
        /// <summary>
        /// 套利单任务 -- 优先合约下单。
        /// </summary>
        /// <param name="taskGroup">开仓/平仓 任务组。</param>
        /// <param name="differentialUnit">最大仓差。</param>
        /// <returns></returns>
        private bool ProcessFirstSubTask(ArbitrageTaskGroup taskGroup, int differentialUnit)
        {
            #region 校验
            PriceSpreadCheckResult priceSpeadResult = CheckPriceSpread(taskGroup.OpenCloseType, m_arbitrageOrder.Argument);
            if (priceSpeadResult.OrderReason == TaskOrderReason.None)
            {
                WriteTraderDebugInfo("优先合约检查,不满足价差条件");
                return(false);
            }

            int firstUnExeTaskIndex = taskGroup.GetFirstTaskUnExecutIndex();
            if (firstUnExeTaskIndex < 0)
            {
                // 优先合约全部完成下单
                return(false);
            }

            bool secondTaskIsPlaceOrder = taskGroup.CheckSecondTaskIsPlaceOrder(firstUnExeTaskIndex);
            if (secondTaskIsPlaceOrder == false)
            {
                WriteTraderDebugInfo("反手合约还未下单,不许下单");
                return(false);
            }

            //反手仓位未成交任务数
            int secondUnTradeTaskCount = taskGroup.GetUnTradeSecondTaskCount(firstUnExeTaskIndex);
            if (secondUnTradeTaskCount >= differentialUnit)
            {
                WriteTraderDebugInfo("优先合约反手合约任务仓差大于等于允许最大仓差,不许下单");
                return(false);
            }

            ArbitrageTask task = taskGroup.TaskList[firstUnExeTaskIndex];
            Debug.Assert(task != null && task.TaskState == ArbitrageTaskState.None);
            ArbitrageSubTask firstSubTask = task.FirstSubTask;

            if (firstSubTask.TryOrderCount >= m_tryOrderCondition.MaxTryOrderCount)
            {
                m_backgroundRunFlag = false;

                string text = string.Format("流程暂停,{2}下单任务[{0}]超出最大尝试下单次数{1}次",
                                            task.TaskId, m_tryOrderCondition.MaxTryOrderCount, firstSubTask.Instrument.InstrumentCode);
                AutoTraderNotice notice = CreateTraderNotice(AutoTraderNoticeType.Order, text);
                SafeFireAutoTraderNotice(notice);

                AlarmNotice alarm = new AlarmNotice(AlarmType.AutoTraderWarning, text);
                SafeFireAutoTraderAlarm(alarm);

                WriteTraderNoticeLog(notice);

                return(false);
            }

            if (firstSubTask.CanPlaceNextOrder(m_tryOrderCondition.NextOrderInterval) == false)
            {
                WriteTraderDebugInfo("优先合约检查,距离上次下单时间过近,暂时不下单");
                return(false);
            }
            #endregion

            #region  单

            Debug.Assert(priceSpeadResult.OrderReason == TaskOrderReason.Open ||
                         priceSpeadResult.OrderReason == TaskOrderReason.Close ||
                         priceSpeadResult.OrderReason == TaskOrderReason.StopLoss);
            task.OrderReason = priceSpeadResult.OrderReason;
            task.PriceSpread = priceSpeadResult.PriceSpreadThreshold;

            //获取优先合约下单价格
            decimal orderPrice = GetFirstInstrumentOrderPrice(firstSubTask.Instrument, firstSubTask.OrderPriceType, firstSubTask.OrderSide);
            Debug.Assert(orderPrice > 0);
            int orderQty = firstSubTask.UnOrderQty;
            Debug.Assert(orderQty > 0);

            USeInstrument instrument = firstSubTask.Instrument;
            USeOffsetType offsetType = firstSubTask.OffsetType;
            USeOrderSide  orderSide  = firstSubTask.OrderSide;

            List <OrderCommand> commandList = null;
            lock (ms_orderSyncObj)
            {
                commandList = CreateOrderCommands(task.TaskId, instrument, orderSide, offsetType, orderQty, orderPrice, "优先合约");
                Debug.Assert(commandList != null && commandList.Count > 0);

                foreach (OrderCommand command in commandList)
                {
                    bool orderResult = PlaceOrderForOrderCommand(command);
                    if (orderResult)
                    {
                        firstSubTask.AddPositiveOrderBook(command.CreateOrignalOrderBook());
                        task.UpdateTaskState();
                        //task.TaskState = ArbitrageTaskState.FirstPlaceOrder;
                    }
                }
            }
            firstSubTask.AddTryOrderCount();  // 下单累加1次
            #endregion

            #region 通知
            foreach (OrderCommand command in commandList)
            {
                AutoTraderNotice notice = CreateTraderNotice(AutoTraderNoticeType.Order, command.ToDescription());
                SafeFireAutoTraderNotice(notice);
                WriteTraderNoticeLog(notice);
            }
            #endregion

            return(true);
        }
예제 #2
0
        /// <summary>
        /// 获取优先合约下单价格。
        /// </summary>
        /// <param name="instrument">优先合约。</param>
        /// <param name="orderPriceType">下单价格类型。</param>
        /// <param name="orderSide">买卖方向。</param>
        /// <returns></returns>
        private decimal GetFirstInstrumentOrderPrice(USeInstrument instrument, ArbitrageOrderPriceType orderPriceType, USeOrderSide orderSide)
        {
            USeMarketData marketData = m_quoteDriver.Query(instrument);

            Debug.Assert(marketData != null);

            switch (orderPriceType)
            {
            case ArbitrageOrderPriceType.LastPrice: return(marketData.LastPrice);

            case ArbitrageOrderPriceType.OpponentPrice:
            {
                if (orderSide == USeOrderSide.Buy)
                {
                    return(marketData.AskPrice);
                }
                else if (orderSide == USeOrderSide.Sell)
                {
                    return(marketData.BidPrice);
                }
                else
                {
                    Debug.Assert(false);
                    return(0m);
                }
            }

            case ArbitrageOrderPriceType.QueuePrice:
            {
                if (orderSide == USeOrderSide.Buy)
                {
                    return(marketData.BidPrice);
                }
                else if (orderSide == USeOrderSide.Sell)
                {
                    return(marketData.AskPrice);
                }
                else
                {
                    Debug.Assert(false);
                    return(0m);
                }
            }

            default:
                Debug.Assert(false);
                return(0m);
            }
        }
예제 #3
0
        /// <summary>
        /// 套利单任务--反手合约下单(优先合约已成交)
        /// </summary>
        /// <param name="taskGroup">开仓/平仓 任务组。</param>
        private bool ProcessSecondSubTask(ArbitrageTaskGroup taskGroup)
        {
            for (int i = 0; i < taskGroup.TaskList.Count; i++)
            {
                #region 校验
                ArbitrageTask task = taskGroup.TaskList[i];

                if (task.TaskState != ArbitrageTaskState.FirstTradeFinish)
                {
                    //优先合约未成交,无需做反手合约检查
                    continue;
                }

                ArbitrageSubTask secondSubTask = task.SecondSubTask;

                if (secondSubTask.TryOrderCount >= m_tryOrderCondition.MaxTryOrderCount)
                {
                    m_backgroundRunFlag = false;

                    string text = string.Format("流程暂停,{2}下单任务[{0}]超出最大尝试下单次数{1}次",
                                                task.TaskId, m_tryOrderCondition.MaxTryOrderCount, secondSubTask.Instrument.InstrumentCode);
                    AutoTraderNotice notice = CreateTraderNotice(AutoTraderNoticeType.Order, text);
                    SafeFireAutoTraderNotice(notice);

                    AlarmNotice alarm = new AlarmNotice(AlarmType.AutoTraderWarning, text);
                    SafeFireAutoTraderAlarm(alarm);

                    WriteTraderNoticeLog(notice);

                    return(false);
                }

                if (secondSubTask.CanPlaceNextOrder(m_tryOrderCondition.NextOrderInterval) == false)
                {
                    WriteTraderDebugInfo("反手合约检查,距离上次下单时间过近,暂时不下单");
                    continue;
                }
                #endregion

                #region  单
                //获取反手合约下单价格
                decimal orderPrice = GetSecondTaskOrderPrice(taskGroup.OperationSide, taskGroup.PreferentialSide, task.FirstSubTaskAvgTradePrice, task.PriceSpread);

                orderPrice = TrimOrderPrice(secondSubTask.Instrument, orderPrice, secondSubTask.OrderSide);
                int orderQty = secondSubTask.UnOrderQty;
                Debug.Assert(orderQty > 0);

                USeInstrument instrument = secondSubTask.Instrument;
                USeOffsetType offsetType = secondSubTask.OffsetType;
                USeOrderSide  orderSide  = secondSubTask.OrderSide;

                List <OrderCommand> commandList = null;
                lock (ms_orderSyncObj)
                {
                    commandList = CreateOrderCommands(task.TaskId, instrument, orderSide, offsetType, orderQty, orderPrice, "反手合约");
                    Debug.Assert(commandList != null && commandList.Count > 0);

                    foreach (OrderCommand command in commandList)
                    {
                        bool orderResult = PlaceOrderForOrderCommand(command);
                        if (orderResult)
                        {
                            secondSubTask.AddPositiveOrderBook(command.CreateOrignalOrderBook());
                            task.UpdateTaskState();
                            //task.TaskState = ArbitrageTaskState.FirstPlaceOrder;
                        }
                    }
                }
                secondSubTask.AddTryOrderCount();  // 下单累加1次
                #endregion

                #region 通知
                foreach (OrderCommand command in commandList)
                {
                    AutoTraderNotice notice = CreateTraderNotice(AutoTraderNoticeType.Order, command.ToDescription());
                    SafeFireAutoTraderNotice(notice);
                    WriteTraderNoticeLog(notice);
                }
                #endregion
            }

            return(false);
        }
        /// <summary>
        /// 获取下单价格。
        /// </summary>
        /// <param name="marketData"></param>
        /// <param name="orderPriceType"></param>
        /// <param name="orderSide"></param>
        /// <returns></returns>
        private decimal GetOrderPrice(USeMarketData marketData, ArbitrageOrderPriceType orderPriceType, USeOrderSide orderSide)
        {
            if (marketData == null)
            {
                return(0m);
            }
            if (orderPriceType == ArbitrageOrderPriceType.Unknown)
            {
                return(0m);
            }

            switch (orderPriceType)
            {
            case ArbitrageOrderPriceType.LastPrice: return(marketData.LastPrice);

            case ArbitrageOrderPriceType.OpponentPrice:
                if (orderSide == USeOrderSide.Buy)
                {
                    return(marketData.AskPrice);
                }
                else
                {
                    Debug.Assert(orderSide == USeOrderSide.Sell);
                    return(marketData.BidPrice);
                }

            case ArbitrageOrderPriceType.QueuePrice:
            {
                if (orderSide == USeOrderSide.Buy)
                {
                    return(marketData.BidPrice);
                }
                else
                {
                    return(marketData.AskPrice);
                }
            }

            default:
                Debug.Assert(false);
                return(0m);
            }
        }
예제 #5
0
 /// <summary>
 /// 委托下单。
 /// </summary>
 /// <param name="product">委托产品。</param>
 /// <param name="qty">委托量。</param>
 /// <param name="price">委托价格。</param>
 /// <param name="offsetType">开平仓方向。</param>
 /// <param name="orderSide">买卖方向。</param>
 /// <param name="error">[out]委托失败原因。</param>
 /// <returns>委托单号。</returns>
 /// <remarks>返回为null代表失败,否则为委托单号。</remarks>
 public abstract USeOrderNum PlaceOrder(USeInstrument product, int qty, decimal price, USeOffsetType offsetType, USeOrderSide orderSide, out string error);
예제 #6
0
        /// <summary>
        /// 委托下单。
        /// </summary>
        /// <param name="instrument">委托产品。</param>
        /// <param name="qty">委托量。</param>
        /// <param name="price">委托价格。</param>
        /// <param name="offsetType">开平仓方向。</param>
        /// <param name="orderSide">买卖方向。</param>
        /// <param name="error">[out]委托失败原因。</param>
        /// <returns>委托单号。</returns>
        /// <remarks>返回为null代表失败,否则为委托单号。</remarks>
        public override USeOrderNum PlaceOrder(USeInstrument instrument, int qty, decimal price, USeOffsetType offsetType, USeOrderSide orderSide, out string error)
        {
            error = "";
            System.Diagnostics.Debug.Assert(instrument != null);

            int orderNumValue = m_orderNumCreateor.Next();

            USeOrderBook orderBook = new USeOrderBook();

            orderBook.OrderNum    = new TestOrderNum(orderNumValue);
            orderBook.Account     = m_investorID;
            orderBook.Instrument  = instrument;
            orderBook.OrderQty    = qty;
            orderBook.OrderPrice  = price;
            orderBook.TradeQty    = 0;
            orderBook.TradeAmount = 0;
            orderBook.TradePrice  = 0;
            orderBook.TradeFee    = 0;
            orderBook.OrderStatus = USeOrderStatus.Unknown;
            orderBook.CancelQty   = 0;
            orderBook.OrderSide   = orderSide;
            orderBook.OffsetType  = offsetType;
            orderBook.Memo        = "";
            orderBook.OrderTime   = DateTime.Now;

            string error_orderInfo = string.Empty;

            VerfiyPlaceOrderToReturn(orderBook, out error_orderInfo);

            if (error_orderInfo == "开仓")
            {
                m_dataBuffer.OrderBookList.Add(orderBook);

                m_pushOrderBookList.Enqueue(orderBook);
                error = "Place Order Ok";

                return(orderBook.OrderNum);
            }
            else if (error_orderInfo == "CloseSuccessed")
            {
                //开仓
                orderBook.Memo = "平仓委托成功";
                m_dataBuffer.OrderBookList.Add(orderBook);

                m_pushOrderBookList.Enqueue(orderBook);
                error = "Place Order Ok";
                return(orderBook.OrderNum);
            }
            else
            {
                //平仓委托失败
                orderBook.Memo        = error_orderInfo;
                orderBook.OrderStatus = USeOrderStatus.BlankOrder;

                m_pushOrderBookList.Enqueue(orderBook);
                error = "Place Order Failed";
                return(orderBook.OrderNum);
            }
        }
예제 #7
0
        public ArbitrageCloseArgument GetCloseArgument(out string errorMessage)
        {
            if (VerifyCloseArgument(out errorMessage) == false)
            {
                return(null);
            }

            USeInstrument buyInstrument  = this.cbxBuyInstrument.SelectedItem as USeInstrument;
            USeInstrument sellInstrument = this.cbxSellInstrument.SelectedItem as USeInstrument;

            ArbitrageOrderPriceType buyOrderPriceType = ArbitrageOrderPriceType.Unknown;

            if (this.rbnBuyOrderPriceType_LastPrice.Checked)
            {
                buyOrderPriceType = ArbitrageOrderPriceType.LastPrice;
            }
            else if (this.rbnBuyOrderPriceType_OpponentPrice.Checked)
            {
                buyOrderPriceType = ArbitrageOrderPriceType.OpponentPrice;
            }
            else if (this.rbnBuyOrderPriceType_QueuePrice.Checked)
            {
                buyOrderPriceType = ArbitrageOrderPriceType.QueuePrice;
            }
            else
            {
                Debug.Assert(false);
            }

            ArbitrageOrderPriceType sellOrderPriceType = ArbitrageOrderPriceType.Unknown;

            if (this.rbnSellOrderPriceType_LastPrice.Checked)
            {
                sellOrderPriceType = ArbitrageOrderPriceType.LastPrice;
            }
            else if (this.rbnSellOrderPriceType_OpponentPrice.Checked)
            {
                sellOrderPriceType = ArbitrageOrderPriceType.OpponentPrice;
            }
            else if (this.rbnSellOrderPriceType_QueuePrice.Checked)
            {
                sellOrderPriceType = ArbitrageOrderPriceType.QueuePrice;
            }
            else
            {
                Debug.Assert(false);
            }

            USeOrderSide preferentialSide = USeOrderSide.Buy;

            if (this.rbnPreferentialSide_Buy.Checked)
            {
                preferentialSide = USeOrderSide.Buy;
            }
            else if (this.rbnPreferentialSide_Sell.Checked)
            {
                preferentialSide = USeOrderSide.Sell;
            }
            else
            {
                Debug.Assert(false);
            }

            PriceSpreadSide priceSpreadSide = PriceSpreadSide.Unknown;

            if (this.rbnPriceSpreadSide_Greater.Checked)
            {
                priceSpreadSide = PriceSpreadSide.GreaterOrEqual;
            }
            else if (this.rbnPriceSpreadSide_Less.Checked)
            {
                priceSpreadSide = PriceSpreadSide.LessOrEqual;
            }
            else
            {
                Debug.Assert(false);
            }

            ArbitrageCloseArgument closeArg = new ArbitrageCloseArgument();

            closeArg.BuyInstrument = buyInstrument;
            closeArg.BuyInstrumentOrderPriceType = buyOrderPriceType;
            closeArg.SellInstrument = sellInstrument;
            closeArg.SellInstrumentOrderPriceType = sellOrderPriceType;
            closeArg.PreferentialSide             = preferentialSide;
            closeArg.CloseCondition = new PriceSpreadCondition()
            {
                PriceSpreadSide      = priceSpreadSide,
                PriceSpreadThreshold = this.nudPriceSpreadThreshold.Value
            };
            closeArg.OrderQtyUint     = (int)this.nudOrderQtyUint.Value;
            closeArg.DifferentialUnit = (int)this.nudDifferentialUnit.Value;

            return(closeArg);
        }
예제 #8
0
        /// <summary>
        /// 平仓追单。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void WorkerDoWorkForCloseChaseOrder(object sender, DoWorkEventArgs e)
        {
            {
                AutoTraderNotice notice = CreateTraderNotice("平仓追单对齐操作");
                SafeFireAutoTraderNotice(notice);
                WriteTraderNoticeLog(notice);
            }

            //开仓追单
            //1.撤销掉当前所有未成交委托单
            //2.检查不对齐欠缺仓位,对欠缺仓位进行开仓追单
            //3.开仓以市价委托,尽量保证成交
            Debug.Assert(m_arbitrageOrder.State == ArbitrageOrderState.Closeing);

            if (m_arbitrageOrder.HasUnFinishOrderBook)
            {
                string           text   = "平仓追单有未完成委托单正在撤单";
                AutoTraderNotice notice = CreateTraderNotice(AutoTraderNoticeType.Order, text);
                SafeFireAutoTraderNotice(notice);
                WriteTraderNoticeLog(notice);

                List <USeOrderBook> unFinishOrderBook = m_arbitrageOrder.GetAllUnfinishOrderBooks();
                foreach (USeOrderBook orderBook in unFinishOrderBook)
                {
                    string errorMessage = string.Empty;
                    bool   cancelResult = m_orderDriver.CancelOrder(orderBook.OrderNum, orderBook.Instrument, out errorMessage);
                    if (cancelResult == false)
                    {
                        text   = string.Format("平仓追单{0} 撤单失败", orderBook.OrderNum);
                        notice = CreateTraderNotice(AutoTraderNoticeType.Order, text);
                        SafeFireAutoTraderNotice(notice);
                        WriteTraderNoticeLog(notice);

                        return;   // 退出流程,触发预警
                    }
                }

                text   = "平仓追单操作完成,等待撤单成功";
                notice = CreateTraderNotice(AutoTraderNoticeType.Order, text);
                SafeFireAutoTraderNotice(notice);
                WriteTraderNoticeLog(notice);

                while (true)
                {
                    //等待撤单完成
                    m_operatorEvent.WaitOne(EVENT_WAIT_Time);

                    if (m_backgroundRunFlag == false)
                    {
                        text   = string.Format("平仓追单流程退出");
                        notice = CreateTraderNotice(AutoTraderNoticeType.Infomation, text);
                        SafeFireAutoTraderNotice(notice);
                        WriteTraderNoticeLog(notice);
                        return;
                    }

                    if (m_arbitrageOrder.HasUnFinishOrderBook == false)
                    {
                        text   = string.Format("平仓追单已完成撤单");
                        notice = CreateTraderNotice(AutoTraderNoticeType.Order, text);
                        SafeFireAutoTraderNotice(notice);
                        WriteTraderNoticeLog(notice);
                        break;
                    }
                }
            }

            List <OrderCommand> commandList = new List <OrderCommand>();

            // 对欠缺仓位进行补单
            foreach (ArbitrageTask task in m_arbitrageOrder.CloseTaskGroup.TaskList)
            {
                if (task.FirstSubTask.TradeQty == task.SecondSubTask.TradeQty)
                {
                    continue;
                }

                Debug.Assert(task.FirstSubTask.TradeQty > task.SecondSubTask.TradeQty);

                //追单
                USeInstrument instrument = task.SecondSubTask.Instrument;
                USeOrderSide  orderSide  = task.SecondSubTask.OrderSide;
                int           orderQty   = task.FirstSubTask.TradeQty - task.SecondSubTask.TradeQty;
                Debug.Assert(orderQty > 0);
                decimal orderPrice = GetFirstInstrumentOrderPrice(instrument, ArbitrageOrderPriceType.OpponentPrice, orderSide);
                Debug.Assert(orderPrice > 0);
                USeOffsetType offsetType = USeOffsetType.Close;

                List <OrderCommand> subCommandList = CreateOrderCommands(task.TaskId, instrument, orderSide, offsetType, orderQty, orderPrice, "平仓追单");
                foreach (OrderCommand command in subCommandList)
                {
                    bool orderResult = PlaceOrderForOrderCommand(command);
                    if (orderResult)
                    {
                        task.SecondSubTask.AddPositiveOrderBook(command.CreateOrignalOrderBook());
                        task.UpdateTaskState();
                        //task.TaskState = ArbitrageTaskState.FirstPlaceOrder;
                    }
                }

                commandList.AddRange(subCommandList);
            }

            #region 通知
            foreach (OrderCommand command in commandList)
            {
                AutoTraderNotice notice = CreateTraderNotice(AutoTraderNoticeType.Order, command.ToDescription());
                SafeFireAutoTraderNotice(notice);
                WriteTraderNoticeLog(notice);
            }
            #endregion

            {
                string           text   = "平仓追单已完成追单,等待成交";
                AutoTraderNotice notice = CreateTraderNotice(AutoTraderNoticeType.Order, text);
                SafeFireAutoTraderNotice(notice);
                WriteTraderNoticeLog(notice);
            }
        }
        /// <summary>
        /// 委托下单。
        /// </summary>
        /// <param name="instrument">委托产品。</param>
        /// <param name="qty">委托量。</param>
        /// <param name="price">委托价格。</param>
        /// <param name="offsetType">开平仓方向。</param>
        /// <param name="orderSide">买卖方向。</param>
        /// <param name="error">[out]委托失败原因。</param>
        /// <returns>委托单号。</returns>
        /// <remarks>返回为null代表失败,否则为委托单号。</remarks>
        public override USeOrderNum PlaceOrder(USeInstrument instrument, int qty, decimal price, USeOffsetType offsetType, USeOrderSide orderSide, out string error)
        {
            if (m_ctpUser == null || m_ctpUser.IsLogin == false)
            {
                error = "OrderServer unable";
                return(null);
            }

            string orderRef  = m_orderRefIDCreator.Next().ToString(); // 生成报单引用
            int    requestID = m_requetSeqIDCreator.Next();

            error = string.Empty;

            try
            {
                OffsetFlagType ctpOffsetFlag;
                switch (offsetType)
                {
                case USeOffsetType.Open: ctpOffsetFlag = OffsetFlagType.Open; break;

                case USeOffsetType.Close: ctpOffsetFlag = OffsetFlagType.Close; break;

                case USeOffsetType.CloseToday: ctpOffsetFlag = OffsetFlagType.CloseToday; break;

                case USeOffsetType.CloseHistory: ctpOffsetFlag = OffsetFlagType.CloseYesterday; break;

                default:
                    throw new ArgumentException(string.Format("Invalid offsetType {0}.", offsetType), "offsetType");
                }

                DirectionType ctpDirection;
                switch (orderSide)
                {
                case USeOrderSide.Buy: ctpDirection = DirectionType.Buy; break;

                case USeOrderSide.Sell: ctpDirection = DirectionType.Sell; break;

                default:
                    throw new ArgumentException(string.Format("Invalid orderside {0}.", orderSide), "orderSide");
                }

                InputOrderField requestField = new InputOrderField();
                requestField.BrokerID            = m_brokerID;
                requestField.InvestorID          = m_investorID;
                requestField.InstrumentID        = instrument.InstrumentCode;
                requestField.OrderRef            = orderRef;
                requestField.UserID              = m_investorID;
                requestField.OrderPriceType      = OrderPriceType.LimitPrice;
                requestField.Direction           = ctpDirection;
                requestField.CombOffsetFlag1     = ctpOffsetFlag;
                requestField.CombHedgeFlag1      = HedgeFlagType.Speculation;
                requestField.LimitPrice          = Convert.ToDouble(price);
                requestField.VolumeTotalOriginal = qty;
                requestField.TimeCondition       = TimeConditionType.GFD;
                requestField.VolumeCondition     = VolumeConditionType.AV;
                requestField.MinVolume           = 1;
                requestField.ContingentCondition = ContingentConditionType.Immediately;
                requestField.ForceCloseReason    = ForceCloseReasonType.NotForceClose;
                requestField.IsAutoSuspend       = IntBoolType.No;
                requestField.BusinessUnit        = null;
                requestField.RequestID           = requestID;
                requestField.UserForceClose      = IntBoolType.No;

                //构造一个委托回报,防止报单不合规等问题遭CTP拒绝,但未有委托回报推送
                OrderField orderField = new OrderField();
                orderField.BrokerID            = m_brokerID;
                orderField.FrontID             = m_frontID;
                orderField.SessionID           = m_sessionID;
                orderField.OrderRef            = orderRef;
                orderField.OrderSysID          = string.Empty;
                orderField.InvestorID          = m_investorID;
                orderField.InstrumentID        = instrument.InstrumentCode;
                orderField.ExchangeID          = CtpProtocol.USeMarketToFtdcExchange(instrument.Market);
                orderField.VolumeTotalOriginal = qty;
                orderField.LimitPrice          = Convert.ToDouble(price);
                orderField.VolumeTraded        = 0;
                orderField.OrderStatus         = OrderStatusType.Unknown;
                orderField.Direction           = orderSide == USeOrderSide.Buy ? DirectionType.Buy : DirectionType.Sell;

                switch (offsetType)
                {
                case USeOffsetType.Open: orderField.CombOffsetFlag1 = OffsetFlagType.Open; break;

                case USeOffsetType.Close: orderField.CombOffsetFlag1 = OffsetFlagType.Close; break;

                case USeOffsetType.CloseHistory: orderField.CombOffsetFlag1 = OffsetFlagType.CloseYesterday; break;

                case USeOffsetType.CloseToday: orderField.CombOffsetFlag1 = OffsetFlagType.CloseToday; break;
                }
                orderField.InsertDate = DateTime.Now.ToString("yyyyMMdd");
                orderField.InsertTime = DateTime.Now.ToString("HH:mm:ss");

                m_dataBuffer.UpdateOrderField(orderField);


                m_ctpUser.ReqOrderInsert(ref requestField, requestID);

                USeOrderNum orderNum = new CtpOrderNum(m_frontID, m_sessionID, orderRef);

                m_logger.WriteInformation(string.Format("{0}.PlaceOrder() ok,[RequestID:{1}][Instrument:{2}][FulcOffsetType{3}][Qty:{4}][Price:{5}].",
                                                        ToString(), requestID, instrument.InstrumentCode, offsetType, qty, price));

                return(orderNum);
            }
            catch (Exception ex)
            {
                m_logger.WriteError(string.Format("{0} placeorder[Instrument:{1}][FulcOffsetType:{2}][Qty:{3}][Price:{4}] failed,Error:{5}.",
                                                  ToString(), instrument.InstrumentCode, offsetType, qty, price, ex.Message));
                error = ex.Message;
                return(null);
            }
        }
        private void btnOpenArbitrageOrder_Click(object sender, EventArgs e)
        {
            string errorMessage = string.Empty;

            if (VerifyOpenArgument(out errorMessage) == false)
            {
                USeFuturesSpiritUtility.ShowWarningMessageBox(this, errorMessage);
                return;
            }

            USeInstrument buyInstrument  = this.cbxBuyInstrument.SelectedItem as USeInstrument;
            USeInstrument sellInstrument = this.cbxSellInstrument.SelectedItem as USeInstrument;

            ArbitrageOrderPriceType buyOrderPriceType  = GetBuyOrderPriceTypeFromUI();
            ArbitrageOrderPriceType sellOrderPriceType = GetSellOrderPriceTypeFromUI();
            USeOrderSide            preferentialSide   = GetPreferentialSideFromUI();
            PriceSpreadSide         priceSpreadSide    = GetPriceSpreadSideFromUI();

            ArbitrageOpenArgument openArg = new ArbitrageOpenArgument();

            openArg.BuyInstrument = buyInstrument;
            openArg.BuyInstrumentOrderPriceType = buyOrderPriceType;
            openArg.SellInstrument = sellInstrument;
            openArg.SellInstrumentOrderPriceType = sellOrderPriceType;
            openArg.PreferentialSide             = preferentialSide;
            openArg.OpenCondition = new PriceSpreadCondition()
            {
                PriceSpreadSide      = priceSpreadSide,
                PriceSpreadThreshold = this.nudPriceSpreadThreshold.Value
            };
            openArg.TotalOrderQty    = (int)this.nudTotalOrderQty.Value;
            openArg.OrderQtyUint     = (int)this.nudOrderQtyUint.Value;
            openArg.DifferentialUnit = (int)this.nudDifferentialUnit.Value;

            if (VerifyMargin(openArg, out errorMessage) == false)
            {
                USeFuturesSpiritUtility.ShowWarningMessageBox(this, errorMessage);
                return;
            }

            decimal evaluateMargin = EvaluateMargin(openArg);
            string  text           = string.Format("套利单预计占用保证金 {0},确定跟单么?", evaluateMargin.ToString("#,0"));

            if (DialogResult.Yes != USeFuturesSpiritUtility.ShowYesNoMessageBox(this, text))
            {
                return;
            }

            //try
            //{
            //    AutoTraderManager traderManager = USeManager.Instance.AutoTraderManager;
            //    Debug.Assert(traderManager != null);

            //    AutoTrader trader = traderManager.CreateNewAutoTrader(openArg, USeManager.Instance.LoginUser);
            //    trader.BeginOpen();
            //    //[yangming]创建后应该启动跟单
            //    trader.StartOpenOrCloseMonitor();

            //    USeManager.Instance.DataSaver.AddSaveTask(trader.GetArbitrageOrder());
            //}
            //catch (Exception ex)
            //{
            //    USeFuturesSpiritUtility.ShowWarningMessageBox(this, ex.Message);
            //    return;
            //}
        }