private void OnQuoteReady(FiveLevelQuote[] quotes, string[] errors) { if (quotes == null || quotes.Length == 0) { return; } lock (_orderLockObj) { if (_activeOrders.Count == 0) { return; } } for (int i = 0; i < quotes.Length; ++i) { var quote = quotes[i]; if (quote == null) { continue; } float maxBuyPrice = quote.BuyPrices.Max(); float minBuyPrice = quote.BuyPrices.Min(v => v == 0.0f ? float.MaxValue : v); int totalBuyVolume = ChinaStockHelper.ConvertHandToVolume(quote.BuyVolumesInHand.Sum()); lock (_orderLockObj) { List <StoplossOrder> orders; if (!_activeOrders.TryGetValue(quote.SecurityCode, out orders)) { continue; } // duplicate orders to avoid the "orders" object being updated in // SendStoploosOrder function. var duplicatedOrders = orders.ToArray(); foreach (var order in duplicatedOrders) { if (ShouldStoploss(quote, maxBuyPrice, minBuyPrice, totalBuyVolume, order)) { SendStoplossOrder(order); } } } } }
private bool ShouldStoploss(FiveLevelQuote quote, float maxBuyPrice, float minBuyPrice, int totalBuyVolume, StoplossOrder order) { bool shouldStoploss = false; if (order.StoplossPrice < minBuyPrice) { if (totalBuyVolume > order.ExistingVolume) { } else { // no solution yet, need to predicate volume. // TODO: predicate volume } } else { if (order.StoplossPrice >= maxBuyPrice) { // need to stop loss immediately. shouldStoploss = true; } else { // order stop loss price is between minBuyPrice and maxBuyPrice // we count the buy volume above stop loss price. int aboveStoplossBuyVolume = ChinaStockHelper.ConvertHandToVolume( Enumerable .Range(0, quote.BuyPrices.Length) .Where(index => quote.BuyPrices[index] >= order.StoplossPrice) .Sum(index => quote.BuyVolumesInHand[index])); if (aboveStoplossBuyVolume <= order.ExistingVolume * 5) { shouldStoploss = true; } else { // there is enough buy volume now, so don't be rush. } } } return(shouldStoploss); }