private IEnumerable <OrderLeg> BuildOrderLegs(ThreadSafeAsk ask, ProposedOrder order, Dictionary <long, Tuple <ThreadSafeAsk, long> > asksInOrder, ref long orderQuanity, bool doLock = false, bool isMarketQuote = false) { bool hasBrokenLeg = false; List <OrderLeg> legs = new List <OrderLeg>(); IEnumerable <ProposedOrderLeg> orderLegs = null; if ((ask.IsBuy ? order.ProposedQuanityBuy : order.ProposedQuantitySell) + orderQuanity <= ask.LockExecuteQuantity) { orderLegs = ProcessOrderLegs(order.OrderLegs, legs, asksInOrder, out hasBrokenLeg); } else if (orderQuanity < ask.LockExecuteQuantity) { ClearProposedOrderLegs(order.OrderLegs, useLock: doLock); var newOrder = BuildProposedOrder(ask, ask.LockExecuteQuantity - orderQuanity, order.OrderLegs, useLock: doLock); if (newOrder.IsValidOrder && (isMarketQuote || newOrder.BuyRatio >= ask.GetBuyRatio(newOrder.SellCommodityID, newOrder.BuyCommodityID))) { orderLegs = ProcessOrderLegs(newOrder.OrderLegs, legs, asksInOrder, out hasBrokenLeg); } else { ClearProposedOrderLegs(newOrder.OrderLegs, useLock: doLock); return(new OrderLeg[] { }); } order = newOrder; } if (hasBrokenLeg) { ClearProposedOrderLegs(order.OrderLegs, asksInOrder, useLock: doLock); var newOrder = BuildProposedOrder(ask, ask.LockExecuteQuantity - orderQuanity, orderLegs, useLock: doLock); legs.Clear(); if (newOrder.IsValidOrder && (isMarketQuote || newOrder.BuyRatio >= ask.GetBuyRatio(newOrder.SellCommodityID, newOrder.BuyCommodityID))) { ProcessOrderLegs(order.OrderLegs, legs, asksInOrder, out hasBrokenLeg); if (hasBrokenLeg) { ClearProposedOrderLegs(newOrder.OrderLegs, asksInOrder, useLock: doLock); return(new OrderLeg[] { }); } } else { ClearProposedOrderLegs(newOrder.OrderLegs, asksInOrder, useLock: doLock); return(new OrderLeg[] { }); } } orderQuanity += ask.IsBuy ? legs.Where(l => l.CommodityBuyID == order.BuyCommodityID).Sum(l => l.BuyQuantity) : legs.Where(l => l.CommoditySellID == order.SellCommodityID).Sum(l => l.SellQuantity); return(legs); }
private void RemoveWorstOrderLeg(ThreadSafeAsk ask, ProposedOrder propOrder, bool useLock = false) { while (propOrder.IsValidOrder && propOrder.BuyRatio < ask.GetBuyRatio(propOrder.SellCommodityID, propOrder.BuyCommodityID) && propOrder.ProposedQuanityBuy > 0) { var worstPerfomingOrderLeg = propOrder.RemoveWorstPerforming(useLock); if (worstPerfomingOrderLeg == null) { break; } RebalanceOrder(propOrder, useLock); propOrder.CleanUpOrder(); } }
private IEnumerable <Order> BuildOrder(ThreadSafeAsk ask, IEnumerable <ProposedOrder> orders, out long orderQuanity, bool isMarketQuote = false, bool doLock = false) { orderQuanity = 0; Dictionary <Tuple <int, int>, Order> finalOrders = new Dictionary <Tuple <int, int>, Order>(); Dictionary <long, Tuple <ThreadSafeAsk, long> > asksInOrder = new Dictionary <long, Tuple <ThreadSafeAsk, long> >(); var orderBuyRatios = orders.GroupBy(o => new Tuple <int, int>(o.SellCommodityID, o.BuyCommodityID)).Select(g => new { SellBuyCommodities = g.Key, AskBuyRatio = ask.GetBuyRatio(g.Key.Item1, g.Key.Item2), AverageBuyRatio = g.Average(o => o.BuyRatio) }).ToDictionary(g => g.SellBuyCommodities); foreach (var propOrder in orders.Where( o => o.IsValidOrder && (isMarketQuote || o.BuyRatio >= orderBuyRatios[new Tuple <int, int>(o.SellCommodityID, o.BuyCommodityID)].AskBuyRatio)).OrderByDescending(o => isMarketQuote ? (o.BuyRatio - orderBuyRatios[new Tuple <int, int>(o.SellCommodityID, o.BuyCommodityID)].AverageBuyRatio) / orderBuyRatios[new Tuple <int, int>(o.SellCommodityID, o.BuyCommodityID)].AverageBuyRatio : (o.BuyRatio - orderBuyRatios[new Tuple <int, int>(o.SellCommodityID, o.BuyCommodityID)].AskBuyRatio) / orderBuyRatios[new Tuple <int, int>(o.SellCommodityID, o.BuyCommodityID)].AskBuyRatio)) { ClearProposedOrderLegs(propOrder.OrderLegs); ProposedOrder newOrder = BuildProposedOrder(ask, ask.LockExecuteQuantity - orderQuanity, propOrder.OrderLegs, useLock: doLock); if (newOrder.IsValidOrder && (isMarketQuote || newOrder.BuyRatio >= ask.GetBuyRatio(newOrder.SellCommodityID, newOrder.BuyCommodityID))) { foreach (var leg in BuildOrderLegs(ask, newOrder, asksInOrder, ref orderQuanity, doLock, isMarketQuote)) { Order order = null; if (!finalOrders.ContainsKey(new Tuple <int, int>(newOrder.SellCommodityID, newOrder.BuyCommodityID))) { order = new Order(); order.CommodityBuyID = newOrder.BuyCommodityID; order.CommoditySellID = newOrder.SellCommodityID; order.CommissionCommodityID = newOrder.Ask.GetApplyCommissionToBuy(newOrder.SellCommodityID, newOrder.BuyCommodityID) ? newOrder.BuyCommodityID : newOrder.SellCommodityID; finalOrders[new Tuple <int, int>(newOrder.SellCommodityID, newOrder.BuyCommodityID)] = order; } else { order = finalOrders[new Tuple <int, int>(newOrder.SellCommodityID, newOrder.BuyCommodityID)]; } order.OrderLegs.Add(leg); } } if (orderQuanity >= ask.LockExecuteQuantity) { break; } } orders = null; foreach (var order in finalOrders) { ApplyCommission(order.Value, ask.GetApplyCommissionToBuy(order.Key.Item1, order.Key.Item2)); } return(finalOrders.Values); }