private static ArbitrageTask CreateTask() { ArbitrageTask task = new ArbitrageTask(); task.TaskId = 100; //task.TaskState = ArbitrageOrderTaskState.Finish; //task.Instrument = new USeInstrument("CF1701", "CF1701", USeMarket.CFFE); //task.OrderPriceType = ArbitrageOrderPriceType.LastPrice; //task.OrderSide = USeOrderSide.Buy; //task.OffsetType = USeOffsetType.Close; //task.PlanOrderQty = 3; //List<USeOrderBook> use_order_booklist = new List<USeOrderBook>(); //use_order_booklist.Add(CreateUseOrderBook()); //task.OrderBooks = use_order_booklist; task.UnFinishOrderBooks.Add(CreateUseOrderBook()); List <USeOrderBook> orderBookList = new List <USeOrderBook>(); orderBookList.Add(CreateUseOrderBook()); return(task); }
public ArbitrageTask Clone() { ArbitrageTask task = new ArbitrageTask(); task.TaskId = this.TaskId; task.TaskState = this.TaskState; task.OrderReason = this.OrderReason; task.PriceSpread = this.PriceSpread; task.FirstSubTask = m_firstSubTask == null ? null : m_firstSubTask.Clone(); task.SecondSubTask = m_secondSubTask == null ? null : m_secondSubTask.Clone(); return(task); }
/// <summary> /// 检查前置任务是否完成反手合约委托。 /// </summary> /// <param name="taskIndex">任务索引。</param> /// <returns></returns> public bool CheckSecondTaskIsPlaceOrder(int taskIndex) { if (taskIndex < 0) { return(true); } for (int i = 0; i < m_taskList.Count && i < taskIndex; i++) { ArbitrageTask task = m_taskList[i]; if (task.TaskState < ArbitrageTaskState.SecondPlaceOrderFinish) { return(false); } } return(true); }
/// <summary> /// 获取指定任务前的前置任务 反手合约未完全成交的任务数。 /// <param name="taskIndex">任务索引。</param> /// <returns></returns> public int GetUnTradeSecondTaskCount(int taskIndex) { if (taskIndex < 0) { return(0); } Debug.Assert(taskIndex < m_taskList.Count); int count = 0; for (int i = 0; i < m_taskList.Count && i < taskIndex; i++) { ArbitrageTask task = m_taskList[i]; if (task.TaskState < ArbitrageTaskState.SecondTradeFinish) { count++; } } return(count); }
/// <summary> /// 创建平仓任务组。 /// </summary> /// <param name="openTaskGroup">开仓任务组。</param> /// <param name="closeArg">平仓参数。</param> /// <returns></returns> private ArbitrageTaskGroup CreateCloseTaskGroup(ArbitrageTaskGroup openTaskGroup, ArbitrageArgument argument) { ArbitrageCloseArgument closeArg = argument.CloseArg; Debug.Assert(openTaskGroup.BuyInstrument == closeArg.SellInstrument); Debug.Assert(openTaskGroup.SellInstrument == closeArg.BuyInstrument); int buyPosition = openTaskGroup.SellSubTaskTradeQty; // 平仓买入量 = 开仓卖出量 int sellPosition = openTaskGroup.BuySubTaskTradeQty; // 平仓卖出量 = 开仓买入量 USeInstrument firstInstrument = null; USeInstrument secondInstrument = null; USeOrderSide firstOrderSide = USeOrderSide.Buy; USeOrderSide secondOrderSide = USeOrderSide.Sell; ArbitrageOrderPriceType firstOrderPriceType = ArbitrageOrderPriceType.Unknown; ArbitrageOrderPriceType secondOrderPriceType = ArbitrageOrderPriceType.Unknown; int firstPosition = 0; int secondPosition = 0; if (closeArg.PreferentialSide == USeOrderSide.Buy) { //优先买入 firstInstrument = closeArg.BuyInstrument; firstOrderSide = USeOrderSide.Buy; firstOrderPriceType = closeArg.BuyInstrumentOrderPriceType; secondInstrument = closeArg.SellInstrument; secondOrderSide = USeOrderSide.Sell; secondOrderPriceType = closeArg.SellInstrumentOrderPriceType; firstPosition = buyPosition; secondPosition = sellPosition; } else if (closeArg.PreferentialSide == USeOrderSide.Sell) { //优先卖出 firstInstrument = closeArg.SellInstrument; firstOrderSide = USeOrderSide.Sell; firstOrderPriceType = closeArg.SellInstrumentOrderPriceType; secondInstrument = closeArg.BuyInstrument; secondOrderSide = USeOrderSide.Buy; secondOrderPriceType = closeArg.BuyInstrumentOrderPriceType; firstPosition = sellPosition; secondPosition = buyPosition; } else { Debug.Assert(false); } Debug.Assert(closeArg.OrderQtyUint > 0); int maxPositon = Math.Max(buyPosition, sellPosition); int taskCount = maxPositon / closeArg.OrderQtyUint; if ((maxPositon % closeArg.OrderQtyUint) > 0) { taskCount += 1; } #region 构造任务组 ArbitrageTaskGroup taskGroup = new ArbitrageTaskGroup(); taskGroup.OpenCloseType = OpenCloseType.Close; taskGroup.BuyInstrument = closeArg.BuyInstrument; taskGroup.SellInstrument = closeArg.SellInstrument; taskGroup.BuyInstrumentOrderPriceType = closeArg.BuyInstrumentOrderPriceType; taskGroup.SellInstrumentOrderPriceType = closeArg.SellInstrumentOrderPriceType; taskGroup.OperationSide = argument.OperationSide.GetOppositeSide(); taskGroup.PreferentialSide = closeArg.PreferentialSide; List <ArbitrageTask> taskList = new List <ArbitrageTask>(); int remainFirstPlanQty = firstPosition; int remainSecondPlanQty = secondPosition; for (int i = 1; i <= taskCount; i++) { int firstPlanOrderQty = Math.Min(closeArg.OrderQtyUint, remainFirstPlanQty); remainFirstPlanQty -= firstPlanOrderQty; int secondPlanOrderQty = Math.Min(closeArg.OrderQtyUint, remainSecondPlanQty); remainSecondPlanQty -= secondPlanOrderQty; ArbitrageTask task = new ArbitrageTask(); task.TaskId = i; task.TaskState = ArbitrageTaskState.None; ArbitrageSubTask firstSubTask = new ArbitrageSubTask() { Instrument = firstInstrument, OrderPriceType = firstOrderPriceType, OrderSide = firstOrderSide, PlanOrderQty = firstPlanOrderQty, OffsetType = USeOffsetType.Close, }; ArbitrageSubTask secondSubTask = new ArbitrageSubTask() { Instrument = secondInstrument, OrderPriceType = secondOrderPriceType, OrderSide = secondOrderSide, PlanOrderQty = secondPlanOrderQty, OffsetType = USeOffsetType.Close }; task.FirstSubTask = firstSubTask; task.SecondSubTask = secondSubTask; taskList.Add(task); } Debug.Assert(remainFirstPlanQty == 0); Debug.Assert(remainSecondPlanQty == 0); taskGroup.TaskList = taskList; #endregion return(taskGroup); }
/// <summary> /// 创建开仓任务组。 /// </summary> /// <param name="openArg">开仓参数。</param> /// <returns></returns> private static ArbitrageTaskGroup CreateOpenTaskGroup(ArbitrageArgument argument) { ArbitrageOpenArgument openArg = argument.OpenArg; USeInstrument firstInstrument = null; USeInstrument secondInstrument = null; USeOrderSide firstOrderSide = USeOrderSide.Buy; USeOrderSide secondOrderSide = USeOrderSide.Sell; ArbitrageOrderPriceType firstOrderPriceType = ArbitrageOrderPriceType.Unknown; ArbitrageOrderPriceType secondOrderPriceType = ArbitrageOrderPriceType.Unknown; if (openArg.PreferentialSide == USeOrderSide.Buy) { //优先买入 firstInstrument = openArg.BuyInstrument; firstOrderSide = USeOrderSide.Buy; firstOrderPriceType = openArg.BuyInstrumentOrderPriceType; secondInstrument = openArg.SellInstrument; secondOrderSide = USeOrderSide.Sell; secondOrderPriceType = openArg.SellInstrumentOrderPriceType; } else if (openArg.PreferentialSide == USeOrderSide.Sell) { //优先卖出 firstInstrument = openArg.SellInstrument; firstOrderSide = USeOrderSide.Sell; firstOrderPriceType = openArg.SellInstrumentOrderPriceType; secondInstrument = openArg.BuyInstrument; secondOrderSide = USeOrderSide.Buy; secondOrderPriceType = openArg.BuyInstrumentOrderPriceType; } else { Debug.Assert(false); } Debug.Assert(openArg.OrderQtyUint > 0); int taskCount = openArg.TotalOrderQty / openArg.OrderQtyUint; if ((openArg.TotalOrderQty % openArg.OrderQtyUint) > 0) { taskCount += 1; } #region 构造任务组 ArbitrageTaskGroup taskGroup = new ArbitrageTaskGroup(); taskGroup.OpenCloseType = OpenCloseType.Open; taskGroup.BuyInstrument = openArg.BuyInstrument; taskGroup.SellInstrument = openArg.SellInstrument; taskGroup.BuyInstrumentOrderPriceType = openArg.BuyInstrumentOrderPriceType; taskGroup.SellInstrumentOrderPriceType = openArg.SellInstrumentOrderPriceType; taskGroup.OperationSide = argument.OperationSide; taskGroup.PreferentialSide = openArg.PreferentialSide; List <ArbitrageTask> taskList = new List <ArbitrageTask>(); int remainPlanQty = openArg.TotalOrderQty; for (int i = 1; i <= taskCount; i++) { int planOrderQty = Math.Min(openArg.OrderQtyUint, remainPlanQty); Debug.Assert(planOrderQty > 0 && planOrderQty <= openArg.OrderQtyUint); remainPlanQty -= planOrderQty; ArbitrageTask task = new ArbitrageTask(); task.TaskId = i; task.TaskState = ArbitrageTaskState.None; ArbitrageSubTask firstSubTask = new ArbitrageSubTask() { Instrument = firstInstrument, OrderPriceType = firstOrderPriceType, OrderSide = firstOrderSide, PlanOrderQty = planOrderQty, OffsetType = USeOffsetType.Open, }; ArbitrageSubTask secondSubTask = new ArbitrageSubTask() { Instrument = secondInstrument, OrderPriceType = secondOrderPriceType, OrderSide = secondOrderSide, PlanOrderQty = planOrderQty, OffsetType = USeOffsetType.Open }; task.FirstSubTask = firstSubTask; task.SecondSubTask = secondSubTask; taskList.Add(task); } Debug.Assert(remainPlanQty == 0); taskGroup.TaskList = taskList; #endregion return(taskGroup); }
/// <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="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="g"></param> //private void DrawTaskList_2(Graphics g) //{ // ArbitrageTaskGroup taskGroup = m_taskGroup; // float xBegin = 35.0f; // float yBegin = 10.0f; // List<ArbitrageTask> taskList = taskGroup.TaskList; // if (taskList != null && taskList.Count > 0) // { // for (int i = 0; i < taskList.Count; i++) // { // ArbitrageTask task = taskList[i]; // float x = xBegin + (i * m_itemInterval); // float y = yBegin; // ArbitrageSubTask firstSubTask = task.FirstSubTask; // ArbitrageSubTask secondSubTask = task.SecondSubTask; // //优先任务 // Brush firstTaskBrush = m_taskNoExceuctBrush; // if (firstSubTask.TradeQty == firstSubTask.PlanOrderQty) // { // firstTaskBrush = m_taskFinishBrush; // } // else if (firstSubTask.OrderQty > 0) // { // firstTaskBrush = m_taskInExecuteBrush; // } // else // { // firstTaskBrush = m_taskNoExceuctBrush; // } // g.FillEllipse(firstTaskBrush, x, y, m_taskDotWidth, m_taskDotHeight); // g.DrawString(string.Format("{0}/{1}", firstSubTask.TradeQty, firstSubTask.PlanOrderQty), // m_font, firstTaskBrush, new RectangleF(x + m_taskDotWidth / 2 - 15, y + 13, 30, 10), m_centerStringFormat); // //反手任务 // Brush secondTaskBrush = m_taskNoExceuctBrush; // if (secondSubTask.TradeQty == secondSubTask.PlanOrderQty) // { // secondTaskBrush = m_taskFinishBrush; // } // else if (secondSubTask.OrderQty > 0) // { // secondTaskBrush = m_taskInExecuteBrush; // } // else // { // secondTaskBrush = m_taskNoExceuctBrush; // } // //反手任务 // g.FillEllipse(secondTaskBrush, x, y + 30, m_taskDotWidth, m_taskDotHeight); // g.DrawString(string.Format("{0}/{1}", secondSubTask.TradeQty, secondSubTask.PlanOrderQty), // m_font, secondTaskBrush, new RectangleF(x + m_taskDotWidth / 2 - 15, y + 30 + 13, 30, 10), m_centerStringFormat); // } // } //} private void DrawTaskList(Graphics g) { float xBegin = 45.0f; // 起始x坐标 float yBegin = 10.0f; // 起始y坐标 float y_f_NegativeQtyOffset = 0; // 优先任务反手量偏移位置 float y_f_taskOffset = 13f; // 优先任务主图标偏移位置 float y_f_QtyOffset = 26f; // 优先任务正手量偏移位置 float y_s_taskOffset = 45f; // 反手任务主图标偏移位置 float y_s_QtyOffset = 58f; // 反手任务正手量偏移位置 ArbitrageTaskGroup taskGroup = m_taskGroup; List <ArbitrageTask> taskList = taskGroup.TaskList; if (taskList == null || taskList.Count <= 0) { return; } for (int i = 0; i < taskList.Count; i++) { ArbitrageTask task = taskList[i]; float x = xBegin + (i * m_itemInterval); float y = yBegin; ArbitrageSubTask firstSubTask = task.FirstSubTask; ArbitrageSubTask secondSubTask = task.SecondSubTask; Brush firstTaskBrush = GetSubTaskBrush(firstSubTask); Brush secondTaskBrush = GetSubTaskBrush(secondSubTask); Pen tmpPen = new Pen(Color.Red); //优先合约反向委托量 if (firstSubTask.NegativeOrderQty > 0) //if (i == 2) { float rectWidth = 30f; float rectHeight = 10f; RectangleF rect = new RectangleF(x - (rectWidth / 2), y + y_f_NegativeQtyOffset, rectWidth, rectHeight); string text = string.Format("{0}/{1}", firstSubTask.NegativeTradeQty, firstSubTask.NegativeOrderQty); g.DrawString(text, m_negativeFont, m_negativeTaskBrush, rect, m_centerStringFormat); } //优先任务点 g.FillEllipse(firstTaskBrush, x - m_taskDotDiameter / 2, y + y_f_taskOffset, m_taskDotDiameter, m_taskDotDiameter); //g.DrawRectangle(tmpPen, x, y + f_y_taskOffset, m_taskDotWidth, m_taskDotHeight); { float rectWidth = 30f; float rectHeight = 10f; RectangleF rect = new RectangleF(x - rectWidth / 2, y + y_f_QtyOffset, rectWidth, rectHeight); string text = string.Format("{0}/{1}", firstSubTask.TradeQty, firstSubTask.PlanOrderQty); g.DrawString(text, m_font, firstTaskBrush, rect, m_centerStringFormat); } //反手任务点 g.FillEllipse(secondTaskBrush, x - m_taskDotDiameter / 2, y + y_s_taskOffset, m_taskDotDiameter, m_taskDotDiameter); //g.DrawRectangle(tmpPen, x, y + s_y_taskOffset, m_taskDotWidth, m_taskDotHeight); { float rectWidth = 30f; float rectHeight = 10f; RectangleF rect = new RectangleF(x - rectWidth / 2, y + y_s_QtyOffset, rectWidth, rectHeight); string text = string.Format("{0}/{1}", secondSubTask.TradeQty, secondSubTask.PlanOrderQty); g.DrawString(text, m_font, secondTaskBrush, rect, m_centerStringFormat); } } }