private void RebalanceOrder(ProposedOrder propOrder, bool useLock = false) { foreach (var legs in propOrder.OrderLegs.GroupBy(o => o.LegLevel).OrderByDescending(o => o.Key).Skip(1)) { var sellQuantity = legs.Sum(l => l.ProposedSellQuantity); var nextLevelOrderLegs = propOrder.GetOrderLegs(legs.Key + 1); if (nextLevelOrderLegs == null) { break; } var buyQuantity = nextLevelOrderLegs.Sum(o => o.ProposedBuyQuantity); if (buyQuantity == sellQuantity) { continue; } if (sellQuantity <= 0 || buyQuantity <= 0) { break; } if (sellQuantity < buyQuantity) { long newBuyQuantity = sellQuantity; foreach (var orderLeg in nextLevelOrderLegs.OrderBy(o => (double)o.ProposedBuyQuantity / (double)o.ProposedSellQuantity)) { var adj = RebalanceOrderLegForBuy(propOrder, orderLeg, newBuyQuantity, useLock); buyQuantity += adj; newBuyQuantity -= orderLeg.ProposedBuyQuantity; if (buyQuantity <= sellQuantity) { break; } } } else { long newSellQuantity = buyQuantity; foreach (var orderLeg in legs.OrderBy(o => (double)o.ProposedBuyQuantity / (double)o.ProposedSellQuantity)) { var adj = RebalanceOrderLegForSell(propOrder, orderLeg, newSellQuantity, useLock); sellQuantity += adj; newSellQuantity -= orderLeg.ProposedSellQuantity; if (sellQuantity <= buyQuantity) { break; } } } if (!propOrder.OrderQuantitiesInSync && sellQuantity > 0 && buyQuantity > 0) { RebalanceOrder(propOrder); break; } else if (sellQuantity <= 0 || buyQuantity <= 0) { break; } } }
private void RebalanceOrderLegsForSell(ThreadSafeAsk ask, IEnumerable <ProposedOrderLeg> orderLegs, int legLevel, long sellQuantity, ProposedOrder propOrder, bool useLock = false) { var previousOrderLegs = propOrder.GetOrderLegs(legLevel); while (previousOrderLegs != null) { ClearProposedOrderLegs(previousOrderLegs, useLock: useLock); var newLegs = FillProposedOrderLegsForRebalanceForSell(ask, sellQuantity, orderLegs.Where(o => o.LegLevel == legLevel), useLock); sellQuantity = newLegs.Sum(p => p.ProposedSellQuantity); if (sellQuantity > 0) { propOrder.SetOrderLegs(newLegs); } legLevel--; previousOrderLegs = propOrder.GetOrderLegs(legLevel); } }
private void BuildProposedOrderForSell(ThreadSafeAsk ask, long askQuantity, IEnumerable <ProposedOrderLeg> orderLegs, ProposedOrder propOrder, bool useLock = false) { bool isFirst = true; int maxLegLevel = orderLegs.Max(l => l.LegLevel); foreach (var legs in orderLegs.GroupBy(o => o.LegLevel).OrderBy(o => o.Key)) { long buyCap = long.MaxValue; if (ask.Legs.Count > 0 && legs.Key == maxLegLevel) { int commodityBuyID = orderLegs.Where(l => l.LegLevel == maxLegLevel).First().CommodityBuyID; var askLeg = ask.Legs.Where(l => l.CommodityID == commodityBuyID).First(); if (askLeg.AvailableQuantityWithoutLockExecute != null) { buyCap = askLeg.AvailableQuantityWithoutLockExecute.Value; } } var propOrderLegs = FillProposedOrderLegsForSell(ask, askQuantity, legs, useLock: useLock, buyCap: buyCap); if (propOrderLegs.Count == 0) { break; } propOrder.SetOrderLegs(propOrderLegs); long sellQuantity = propOrderLegs.Sum(p => p.ProposedSellQuantity); if (askQuantity > sellQuantity && sellQuantity > 0 && !isFirst) { RebalanceOrderLegsForSell(ask, orderLegs, legs.Key - 1, sellQuantity, propOrder, useLock); var previousOrderLegs = propOrder.GetOrderLegs(legs.Key - 1); if (previousOrderLegs != null) { ClearProposedOrderLegs(propOrderLegs, useLock: useLock); askQuantity = previousOrderLegs.Sum(p => p.ProposedBuyQuantity); propOrderLegs = FillProposedOrderLegsForSell(ask, askQuantity, legs, useLock: useLock); if (propOrderLegs.Count == 0 || askQuantity <= 0) { break; } propOrder.SetOrderLegs(propOrderLegs); } } askQuantity = propOrderLegs.Sum(p => p.ProposedBuyQuantity); if (askQuantity <= 0 || sellQuantity <= 0) { break; } isFirst = false; } }