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