3

我正在尝试编写的实际查询比标题所暗示的要复杂一些。我有一个像这样的订单列表:List<Order>,订单看起来像这样:

public class Order
{
    private StockCodes _stockCode;
    private bool _bidSide;
    private int _volume;
    private decimal _price;
}

我需要在给定特定股票代码的情况下发布最佳买入价和成交量以及最佳卖出价和成交量。最佳买入价被定义为当bidSide 为真时的最高价。最佳卖出价定义为当bidSide 为假时的最低价。

例如,给定股票代码“ABC”的以下数据:

 { bidSide: true, volume: 25, price: 25  }
 { bidSide: true, volume: 25, price: 25  }
 { bidSide: true, volume: 25, price: 5  }

 { bidSide: false, volume: 100, price: 1  }
 { bidSide: false, volume: 50, price: 2}
 { bidSide: false, volume: 75, price: 8 }

最佳出价:价格 25,数量 50(因为有 2 个最高价格的订单) 最佳卖出:价格 1,数量 100(因为只有 1 个最低价格的订单)

最后,我需要考虑何时没有买入或卖出订单。效率是重中之重,所以如果我能够在一个 linq 语句中做到这一点,那将是首选。

4

3 回答 3

6

为了有效地做到这一点,你真的只想迭代数据一次。不幸的是,这使得用 LINQ 实现真的很痛苦,因为有很多工作要做。

我个人建议您不要使用 LINQ 执行此操作 - 您可以使用Aggregate. 不过,使用简单的foreach循环并不算太糟糕。就像是:

int buyVolume = -1;
int sellVolume = -1;
decimal buyPrice = decimal.MinValue;
decimal sellPrice = decimal.MaxValue;

foreach (var order in orders)
{
    if (order.bidSide)
    {
        if (order.Price > buyPrice)
        {
            buyPrice = order.Price;
            buyVolume = order.Volume;
        }
        else if (order.Price == buyPrice)
        {
            buyVolume += order.Volume;
        }
    }
    else
    {
        if (order.Price < sellPrice)
        {
            sellPrice = order.Price;
            sellVolume = order.Volume;
        }
        else if (order.Price == sellPrice)
        {
            sellVolume += order.Volume;
        }
    }
}

// Check sellVolume == -1 to verify whether we've seen any sale orders
// Check buyVolume == -1 to verify whether we've seen any buy orders
// Use buyPrice/buyVolume and sellPrice/sellVolume otherwise

在 LINQ 中尽可能高效地执行此操作实际上意味着将循环中的所有逻辑放入要传递的函数中Aggregate- 您可能希望创建一个自定义值类型来保存四个值,以避免创建比您更多的对象需要。这可能是矫枉过正,但你确实说过你希望它尽可能高效......

于 2012-04-15T20:01:58.487 回答
0
HIGHEST = orders.Max(x => x.bidSide ? x.price : (decimal?)null) ?? 0M

LOWEST 类似。

不幸的是,Linq2SQL 不会将其转换为有效的查询。它将在一个查询中执行,但每个 Max 操作将扫描一次数据(在您的情况下为两次:HIGHEST 和 LOWEST)。在原始 SQL 中,您可以一次通过数据执行此操作。

于 2012-04-15T19:54:35.450 回答
0

这可以明智地执行 LINQ ......

var bids = (from o in orders
                where o.StockCode == "ABC" && o.BidSide == true
                group o by o.Price)
                .OrderByDescending(g => g.Key)
                .FirstOrDefault();
var bidVolume = bids != null ? new Order { Price = bids.Key, Volume = bids.Sum(g => g.Volume) } : null;

var sells = (from o in orders
                where o.StockCode == "ABC" && o.BidSide == false
                group o by o.Price)
                .OrderBy(g => g.Key)
                .FirstOrDefault();
var sellVolume = sells != null ? new Order { Price = sells.Key, Volume = sells.Sum(g => g.Volume) } : null;
于 2012-04-15T20:08:20.980 回答