// 这里假设已经挂的单子已经是按最优数量进行处理过,目标是直接挂单 // 目前对前两层做智能开平,后面的全用开仓单 // 因为后面的使用平仓单,还要处理复杂的大量开挂单的问题。 // 实际上不能太深,因为深了占用资金 public int 补单(OrderBook_OneSide_Order buy1, OrderBook_OneSide_Size buy2) { int cnt = 0; // 方向不对,不可能补单 if (buy1.Side != buy2.Side) { return(cnt); } int l = 0; // 由于在别的地方做了撤单,在这buy2中的数量是大于buy1的 foreach (var b2 in buy2.Grid) { ++l; int level = b2.Key; double size = b2.Value; // 要补单的数量 double leave = size - buy1.SizeByLevel(level); if (leave <= 0) { continue; } double price = PriceHelper.GetPriceByLevel(level); cnt += (int)leave; // 超过两层的全用开仓 if (l > 2) { SendLimitOrder(buy2.Side, leave, price, OpenCloseHelper.GetOpenCloseString(EnumOpenClose.OPEN)); continue; } // 应当对容易平仓的位置进行平仓 // 这个地方要测试一个,我只有10持仓,先挂10手平,第二个价格再挂自动生成的单是平还是开?检查数据计算是否正确 // 补单是一次性的,还是分两笔,还是分两笔吧 //double canqty = DualPosition.CanCloseQty(buy2.Side); //// 检查平仓,如果补单限为一次,那就把此行注释 //if (canqty > 0) //{ // double min = Math.Min(leave, canqty); // leave -= min; // SendLimitOrder(buy2.Side, min, price, // OpenCloseHelper.GetOpenCloseString(EnumOpenClose.CLOSE_TODAY)); //} if (leave > 0) { //SendLimitOrder(buy2.Side, leave, price, // OpenCloseHelper.GetOpenCloseString(DualPosition.CanClose(buy2.Side, leave))); } } return(cnt); }
// 此部分是因为确信此位置上不会挂单,所以撤了 public int 强行撤单部分(OrderBook_OneSide_Order buy1, OrderBook_OneSide_Size buy2) { int cnt = 0; return(cnt); }
// 检查对手,保证最不会自成交 // 这次有可能把平仓单全撤了,剩下的全是开仓单,有些风险 public int 单边防自成交(OrderBook_OneSide_Order sell, OrderBook_OneSide_Size buy) { int cnt = 0; // 同买卖是不可能自成交的 if (sell.Side == buy.Side) { return(cnt); } // 还没有挂单,不会自成交 if (sell.Count <= 0) { return(cnt); } // 对手单也是空的,不会自成交 if (buy.Count <= 0) { return(cnt); } // 取对手单的最高价 int level = buy.Grid.Keys[0]; // 将挂单列表中的单子撤单 foreach (var s in sell.Grid) { if (buy.Side == OrderSide.Buy) { if (s.Key <= level) { cnt += sell.Cancel(s.Value); } } else { if (s.Key >= level) { cnt += sell.Cancel(s.Value); } } } return(cnt); }
// 其它层好办,关键在第一层,第一层要保证排队和开平 // 没有竞争者就保证平仓 // 在第一层时,把后面几层能平的仓先平了 // 在第二层时,把 // 如果第一层有开仓单,把后面所有的平仓全撤了 // 如果第一层只有自己排队,把开仓单平了 // 排队要排第一,然后平仓单向前挪,只撤超出部分 // 前两层,数量超过得撤,先撤排后的,如果撤了后少于指定数就不撤 // 后两层,只要是平仓单就撤,我没法区分平仓单啊 public int 智能撤单逻辑(OrderBook_OneSide_Order buy1, OrderBook_OneSide_Size buy2) { List<Order> forCancel = new List<Order>(); int cnt = 0; // 方向不对,不可能补单 if (buy1.Side != buy2.Side) return cnt; lock(this) { // 撤单时按已有的挂单进行处理 foreach (var b1 in buy1.GridList) { int level = b1.Key; double size2 = buy2.SizeByLevel(level); if (size2 <= 0) { // 发现目标价上量为0,全撤 forCancel.AddRange(b1.Value); //cancelList.UnionWith(b1.Value); //cnt += buy1.Cancel(b1.Value); continue; } double size1 = buy1.Size(b1.Value); if (size1 <= size2) { // 量少于目标量,不动,等着补单 continue; } // 要撤单的量,实际上还剩的挂单量不由人为控制,所以这个地方可以多撤 double leave = size1 - size2; // 现在这个价位上挂了很多单,是撤开仓,还是撤新挂的? double count = 0; // 这个地方会出错,只好重新复制一下 foreach (Order o in b1.Value.ToList()) { count += o.LeavesQty; if (count >= leave) break; forCancel.Add(o); //cancelList.Add(o); //o.Cancel(); //++cnt; } } } foreach(var o in forCancel) { if (!o.IsDone) o.Cancel(); cancelList.Add(o); ++cnt; } return cnt; }
// 这里假设已经挂的单子已经是按最优数量进行处理过,目标是直接挂单 // 目前对前两层做智能开平,后面的全用开仓单 // 因为后面的使用平仓单,还要处理复杂的大量开挂单的问题。 // 实际上不能太深,因为深了占用资金 public int 单边全面补单(OrderBook_OneSide_Order buy1, OrderBook_OneSide_Size buy2) { int cnt = 0; List<CopyOrder> list = new List<CopyOrder>(); // 方向不对,不可能补单 if (buy1.Side != buy2.Side) return cnt; TextCommon tp = buy1.Side == OrderSide.Buy ? TextParameterBid : TextParameterAsk; PositionRecord LongShort = buy1.Side == OrderSide.Buy ? base.DualPosition.Short : base.DualPosition.Long; lock(this) { int l = 0; // 由于在别的地方做了撤单,在这buy2中的数量是大于等于buy1的 foreach (var b2 in buy2.GridList) { ++l; int level = b2.Key; double size = b2.Value; // 要补单的数量 double leave = size - buy1.SizeByLevel(level); if (leave <= 0) continue; double price = PriceHelper.GetPriceByLevel(level); cnt += (int)leave; // 超过两层的全用开仓 if (l > AlwaysOpenIfDepthGreatThan) { tp.OpenClose = EnumOpenClose.OPEN; tp.Text = string.Format("{0}层,开仓补单", l); } else { // 计算开平 double q = CloseTodayHelper.GetCloseAndQty(LongShort, out tp.OpenClose); if (q < leave) { tp.OpenClose = EnumOpenClose.OPEN; tp.Text = string.Format("开仓:可平量{0}<{1}", q, leave); } else { tp.Text = string.Format("平仓:可平量{0}>={1}", q, leave); } } // 入场下单 // 在模拟下,这个地方有可能导致成交回报lock //SendLimitOrder(buy2.Side, leave, price, tp.ToString()); list.Add(new CopyOrder() { Side = buy2.Side, Qty = leave, Price = price, Text = tp.ToString(), }); } } foreach(var o in list) { SendLimitOrder(o.Side, o.Qty, o.Price, o.Text); } return cnt; }
// 检查对手,保证不会自成交 // 这次有可能把平仓单全撤了,剩下的全是开仓单,有些风险 public int 单边防自成交撤单(OrderBook_OneSide_Order sell, OrderBook_OneSide_Size buy) { int cnt = 0; List<Order> forCancel = new List<Order>(); // 同买卖是不可能自成交的 if (sell.Side == buy.Side) return cnt; // 还没有挂单,不会自成交 if (sell.Count <= 0) return cnt; // 对手单也是空的,不会自成交 if (buy.Count <= 0) return cnt; lock(this) { // 取对手单的最高价 int level = buy.LevelByIndex(0); // 将挂单列表中的单子撤单 // 将挂单列表中的单子撤单 foreach (var s in sell.GridList) { if (buy.Side == OrderSide.Buy) { if (s.Key <= level) { forCancel.AddRange(s.Value); //cancelList.UnionWith(s.Value); //cnt += sell.Cancel(s.Value); } } else { if (s.Key >= level) { forCancel.AddRange(s.Value); //cancelList.UnionWith(s.Value); //cnt += sell.Cancel(s.Value); } } } } foreach (var o in forCancel) { if (!o.IsDone) o.Cancel(); cancelList.Add(o); ++cnt; } return cnt; }
// 检查对手,保证最不会自成交 // 这次有可能把平仓单全撤了,剩下的全是开仓单,有些风险 public int 单边防自成交(OrderBook_OneSide_Order sell,OrderBook_OneSide_Size buy) { int cnt = 0; // 同买卖是不可能自成交的 if(sell.Side == buy.Side) return cnt; // 还没有挂单,不会自成交 if (sell.Count <= 0) return cnt; // 对手单也是空的,不会自成交 if (buy.Count <= 0) return cnt; // 取对手单的最高价 int level = buy.Grid.Keys[0]; // 将挂单列表中的单子撤单 foreach(var s in sell.Grid) { if (buy.Side == OrderSide.Buy) { if (s.Key <= level) { cnt += sell.Cancel(s.Value); } } else { if (s.Key >= level) { cnt += sell.Cancel(s.Value); } } } return cnt; }
// 这里假设已经挂的单子已经是按最优数量进行处理过,目标是直接挂单 // 目前对前两层做智能开平,后面的全用开仓单 // 因为后面的使用平仓单,还要处理复杂的大量开挂单的问题。 // 实际上不能太深,因为深了占用资金 public int 补单(OrderBook_OneSide_Order buy1, OrderBook_OneSide_Size buy2) { int cnt = 0; // 方向不对,不可能补单 if (buy1.Side != buy2.Side) return cnt; int l = 0; // 由于在别的地方做了撤单,在这buy2中的数量是大于buy1的 foreach(var b2 in buy2.Grid) { ++l; int level = b2.Key; double size = b2.Value; // 要补单的数量 double leave = size - buy1.SizeByLevel(level); if (leave <= 0) continue; double price = PriceHelper.GetPriceByLevel(level); cnt += (int)leave; // 超过两层的全用开仓 if (l > 2) { SendLimitOrder(buy2.Side, leave, price, OpenCloseHelper.GetOpenCloseString(EnumOpenClose.OPEN)); continue; } // 应当对容易平仓的位置进行平仓 // 这个地方要测试一个,我只有10持仓,先挂10手平,第二个价格再挂自动生成的单是平还是开?检查数据计算是否正确 // 补单是一次性的,还是分两笔,还是分两笔吧 //double canqty = DualPosition.CanCloseQty(buy2.Side); //// 检查平仓,如果补单限为一次,那就把此行注释 //if (canqty > 0) //{ // double min = Math.Min(leave, canqty); // leave -= min; // SendLimitOrder(buy2.Side, min, price, // OpenCloseHelper.GetOpenCloseString(EnumOpenClose.CLOSE_TODAY)); //} if (leave > 0) { //SendLimitOrder(buy2.Side, leave, price, // OpenCloseHelper.GetOpenCloseString(DualPosition.CanClose(buy2.Side, leave))); } } return cnt; }
// 此部分是因为确信此位置上不会挂单,所以撤了 public int 强行撤单部分(OrderBook_OneSide_Order buy1, OrderBook_OneSide_Size buy2) { int cnt = 0; return cnt; }
// 其它层好办,关键在第一层,第一层要保证排队和开平 // 没有竞争者就保证平仓 // 在第一层时,把后面几层能平的仓先平了 // 在第二层时,把 // 如果第一层有开仓单,把后面所有的平仓全撤了 // 如果第一层只有自己排队,把开仓单平了 // 排队要排第一,然后平仓单向前挪,只撤超出部分 // 前两层,数量超过得撤,先撤排后的,如果撤了后少于指定数就不撤 // 后两层,只要是平仓单就撤,我没法区分平仓单啊 public int 智能撤单逻辑(OrderBook_OneSide_Order buy1, OrderBook_OneSide_Size buy2) { List <Order> forCancel = new List <Order>(); int cnt = 0; // 方向不对,不可能补单 if (buy1.Side != buy2.Side) { return(cnt); } lock (this) { // 撤单时按已有的挂单进行处理 foreach (var b1 in buy1.GridList) { int level = b1.Key; double size2 = buy2.SizeByLevel(level); if (size2 <= 0) { // 发现目标价上量为0,全撤 forCancel.AddRange(b1.Value); //cancelList.UnionWith(b1.Value); //cnt += buy1.Cancel(b1.Value); continue; } double size1 = buy1.Size(b1.Value); if (size1 <= size2) { // 量少于目标量,不动,等着补单 continue; } // 要撤单的量,实际上还剩的挂单量不由人为控制,所以这个地方可以多撤 double leave = size1 - size2; // 现在这个价位上挂了很多单,是撤开仓,还是撤新挂的? double count = 0; // 这个地方会出错,只好重新复制一下 foreach (Order o in b1.Value.ToList()) { count += o.LeavesQty; if (count >= leave) { break; } forCancel.Add(o); //cancelList.Add(o); //o.Cancel(); //++cnt; } } } foreach (var o in forCancel) { if (!o.IsDone) { o.Cancel(); } cancelList.Add(o); ++cnt; } return(cnt); }
// 这里假设已经挂的单子已经是按最优数量进行处理过,目标是直接挂单 // 目前对前两层做智能开平,后面的全用开仓单 // 因为后面的使用平仓单,还要处理复杂的大量开挂单的问题。 // 实际上不能太深,因为深了占用资金 public int 单边全面补单(OrderBook_OneSide_Order buy1, OrderBook_OneSide_Size buy2) { int cnt = 0; List <CopyOrder> list = new List <CopyOrder>(); // 方向不对,不可能补单 if (buy1.Side != buy2.Side) { return(cnt); } TextCommon tp = buy1.Side == OrderSide.Buy ? TextParameterBid : TextParameterAsk; PositionRecord LongShort = buy1.Side == OrderSide.Buy ? base.DualPosition.Short : base.DualPosition.Long; lock (this) { int l = 0; // 由于在别的地方做了撤单,在这buy2中的数量是大于等于buy1的 foreach (var b2 in buy2.GridList) { ++l; int level = b2.Key; double size = b2.Value; // 要补单的数量 double leave = size - buy1.SizeByLevel(level); if (leave <= 0) { continue; } double price = PriceHelper.GetPriceByLevel(level); cnt += (int)leave; // 超过两层的全用开仓 if (l > AlwaysOpenIfDepthGreatThan) { tp.OpenClose = EnumOpenClose.OPEN; tp.Text = string.Format("{0}层,开仓补单", l); } else { // 计算开平 double q = CloseTodayHelper.GetCloseAndQty(LongShort, out tp.OpenClose); if (q < leave) { tp.OpenClose = EnumOpenClose.OPEN; tp.Text = string.Format("开仓:可平量{0}<{1}", q, leave); } else { tp.Text = string.Format("平仓:可平量{0}>={1}", q, leave); } } // 入场下单 // 在模拟下,这个地方有可能导致成交回报lock //SendLimitOrder(buy2.Side, leave, price, tp.ToString()); list.Add(new CopyOrder() { Side = buy2.Side, Qty = leave, Price = price, Text = tp.ToString(), }); } } foreach (var o in list) { SendLimitOrder(o.Side, o.Qty, o.Price, o.Text); } return(cnt); }
// 检查对手,保证不会自成交 // 这次有可能把平仓单全撤了,剩下的全是开仓单,有些风险 public int 单边防自成交撤单(OrderBook_OneSide_Order sell, OrderBook_OneSide_Size buy) { int cnt = 0; List <Order> forCancel = new List <Order>(); // 同买卖是不可能自成交的 if (sell.Side == buy.Side) { return(cnt); } // 还没有挂单,不会自成交 if (sell.Count <= 0) { return(cnt); } // 对手单也是空的,不会自成交 if (buy.Count <= 0) { return(cnt); } lock (this) { // 取对手单的最高价 int level = buy.LevelByIndex(0); // 将挂单列表中的单子撤单 // 将挂单列表中的单子撤单 foreach (var s in sell.GridList) { if (buy.Side == OrderSide.Buy) { if (s.Key <= level) { forCancel.AddRange(s.Value); //cancelList.UnionWith(s.Value); //cnt += sell.Cancel(s.Value); } } else { if (s.Key >= level) { forCancel.AddRange(s.Value); //cancelList.UnionWith(s.Value); //cnt += sell.Cancel(s.Value); } } } } foreach (var o in forCancel) { if (!o.IsDone) { o.Cancel(); } cancelList.Add(o); ++cnt; } return(cnt); }