3

私が書き込もうとしている実際のクエリは、タイトルが示唆するよりも少しトリッキーです。私はそのような注文のリストを持っています:List<Order>、注文は次のようになります:

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

特定の銘柄コードを指定して、最良の買値と出来高、および最良の売値と出来高を公開する必要があります。最高入札価格は、bidSideが真である最高価格として定義されます。ベストセル価格は、bidSideがfalseの場合の最低価格として定義されます。

たとえば、証券コード「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つの注文しかないため)

最後に、ビッドまたはセルの注文がない場合を考慮する必要があります。効率が最優先されるので、これを1つのlinqステートメントで実行できる場合はそれが望ましいでしょう。

4

3 に答える 3

6

これを効率的に行うには、実際にはデータを 1 回だけ反復処理する必要があります。残念ながら、やるべき作業が非常に多いため、LINQ を使用して実装するのは非常に困難です。

個人的には、LINQ でこれを行わないことをお勧めします。ただし、単純なループではそれほど悪くはありません。何かのようなもの:Aggregateforeach

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します。おそらく、4 つの値を保持するカスタム値型を作成して、自分よりも多くのオブジェクトを作成しないようにすることをお勧めします。する必要があります。それはやり過ぎかもしれませんが、できるだけ効率的にしたいとおっしゃいました...

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

LOWEST についても同様です。

残念ながら、Linq2SQL はこれを効率的なクエリに変換しません。単一のクエリで実行されますが、データは Max 操作ごとに 1 回スキャンされます (この場合、HIGHEST と LOWEST の 2 回)。生の SQL では、データに対する 1 回のパスでこれを行うことができます。

于 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 に答える