public PartiallyClosedOrdersAdjuster(List <IOrderInfo> live, List <IOrderInfo> history) { _live = live; _history = history; _toResolve = new List <IOrderInfo>(); _history.Sort((o1, o2) => { try { var cmp = o1.GetCloseTime().CompareTo(o2.GetCloseTime()); if (cmp == 0) { cmp = string.Compare(o1.GetSymbol(), o2.GetSymbol(), StringComparison.Ordinal); if (cmp == 0) { cmp = o1.GetTradeOperation() - o2.GetTradeOperation(); if (cmp == 0) { var d = o1.GetOpenPrice() - o2.GetOpenPrice(); cmp = d == 0 ? 0 : (d > 0 ? 1 : -1); if (cmp == 0) { var t = o1.GetOpenTime() - o2.GetOpenTime(); cmp = t.TotalSeconds == 0 ? 0 : (t.TotalSeconds > 0 ? 1 : -1); if (cmp == 0) { cmp = o1.GetMagic() - o2.GetMagic(); if (cmp == 0) { var t1 = o1.Ticket(); var t2 = o2.Ticket(); cmp = t1 > t2 ? -1 : (t1 < t2 ? 1 : 0); // reverse order for stack } } } } } } return(cmp); } catch (Exception e) { Console.WriteLine(e); return(0); } }); _live.Sort((o1, o2) => o1.Ticket() > o2.Ticket() ? 1 : -1); // var notBuySellOrders = new List <IOrderInfo>(); _orders = _live.ToDictionary(info => info.Ticket()); _buySide = new List <Stack <IOrderInfo> >(); _sellSide = new List <Stack <IOrderInfo> >(); _buyAtTop = new Dictionary <long, bool>(); _sellAtTop = new Dictionary <long, bool>(); _hedgedBy = new Dictionary <long, long>(); _closedBy = new Dictionary <long, long>(); OComparator lastOrderCmpInfo = null; var closeHedgeBy = @"close hedge by #"; foreach (var o in history) { _orders[o.Ticket()] = o; var tradeOperation = o.GetTradeOperation(); if (tradeOperation != TradeOperation.OP_BUY && tradeOperation != TradeOperation.OP_SELL) { notBuySellOrders.Add(o); continue; } // if (o.GetComment().StartsWith(closeHedgeBy)) { long t; if (long.TryParse(o.GetComment().Substring(closeHedgeBy.Length), out t)) { _hedgedBy[o.Ticket()] = t; _closedBy[t] = o.Ticket(); } else { Logger.Warn($"Not expected, not numeric ticket in comment: {o.GetComment()}"); } } // var side = tradeOperation == TradeOperation.OP_BUY ? _buySide : _sellSide; var top = tradeOperation == TradeOperation.OP_BUY ? _buyAtTop : _sellAtTop; // if (lastOrderCmpInfo == null || !lastOrderCmpInfo.IsSameOrder(o)) { lastOrderCmpInfo = new OComparator(o); var stack = new Stack <IOrderInfo>(); stack.Push(o); side.Add(stack); } else { var stack = side[side.Count - 1]; top.Remove(stack.Peek().Ticket()); stack.Push(o); } top[o.Ticket()] = true; } // history.Clear();//rebuilding historical orders history.AddRange(notBuySellOrders); }
private bool CheckHedges(Stack <IOrderInfo> bStack) { Stack <IOrderInfo> cbStack = null; Stack <IOrderInfo> hdgStack = null; long tmpTicket; if (_closedBy.TryGetValue(bStack.Peek().Ticket(), out tmpTicket)) { cbStack = bStack; if (_sellAtTop.ContainsKey(tmpTicket)) { hdgStack = _sellSide.FirstOrDefault(sellStack => sellStack.Peek().Ticket() == tmpTicket); } } if (_hedgedBy.TryGetValue(bStack.Peek().Ticket(), out tmpTicket)) { hdgStack = bStack; if (_sellAtTop.ContainsKey(tmpTicket)) { cbStack = _sellSide.FirstOrDefault(sellStack => sellStack.Peek().Ticket() == tmpTicket); } } if (cbStack != null && hdgStack != null) { var cbOrder = cbStack.Pop(); var hdgOrder = hdgStack.Pop(); // _history.Add(hdgOrder); _history.Add(cbOrder); // IOrderInfo cbNext = null; IOrderInfo hdgNext = null; // Dictionary <long, bool> cbTop = cbOrder.GetTradeOperation() == TradeOperation.OP_BUY ? _buyAtTop : _sellAtTop; Dictionary <long, bool> hdgTop = hdgOrder.GetTradeOperation() == TradeOperation.OP_BUY ? _buyAtTop : _sellAtTop; cbTop.Remove(cbOrder.Ticket()); hdgTop.Remove(hdgOrder.Ticket()); if (cbStack.Count > 0) { cbTop[(cbNext = cbStack.Peek()).Ticket()] = true; } if (hdgStack.Count > 0) { hdgTop[(hdgNext = hdgStack.Peek()).Ticket()] = true; } // cbOrder.SetClosedBy(hdgOrder); if (cbNext == null && hdgNext == null) { //check live orders for next var cbC = new OComparator(cbOrder); var hdgC = new OComparator(hdgOrder); cbNext = _live.FirstOrDefault( order => order.Ticket() > cbOrder.Ticket() && cbC.IsSameLiveOrder(order)); hdgNext = _live.FirstOrDefault( order => order.Ticket() > hdgOrder.Ticket() && hdgC.IsSameLiveOrder(order)); } var next = cbNext == null ? hdgNext : (hdgNext == null ? cbNext : (cbNext.Ticket() > hdgNext.Ticket() ? hdgNext : cbNext)); // use minimal ticket number for next order if (next != null) { if (ReferenceEquals(next, cbNext)) { cbOrder.SetNext(next); } if (ReferenceEquals(next, hdgNext)) { hdgOrder.SetNext(next); } } // // remove empty stack from a side if (cbStack.Count == 0) { (cbOrder.GetTradeOperation() == TradeOperation.OP_BUY ? _buySide : _sellSide).Remove(cbStack); } if (hdgStack.Count == 0) { (hdgOrder.GetTradeOperation() == TradeOperation.OP_BUY ? _buySide : _sellSide).Remove(hdgStack); } // return(true); } return(false); }