我正在努力解决的问题
所以我有一个Observable
股票代码来源。它只发送我感兴趣的股票的价格。我需要做的是获得这个股票价格,并在每个 x 秒之后(例如,假设每隔3秒)发送处理价格的快照。如果在3秒内我收到同一股票的2个刻度,我只需要最新的刻度。这个处理计算量很大,所以如果可能的话,我希望避免发送相同的股票价格进行两次处理。
举一个例子。
假设在序列开头我收到了2个刻度 - > MSFT:1 $,GOOG:2 $ 。
在接下来的3秒内我什么都没收到,所以 MSFT&应该发送GOOG 标记进行处理。
现在下一秒我收到新的蜱 - > MSFT:1 $,GOOG:3 $,INTL:3 $
再次让我们假设在接下来的3秒内没有任何东西进入。
在这里,由于 MSFT 价格没有变化(它仍然是1美元),只有 GOOG&应发送INTL 进行处理。
这一整天都在重复。
现在我认为Rx可以帮助解决这类问题。优雅的方式。但是我有一个问题需要正确的查询。 这就是我到目前为止所做的,将尝试解释它的作用以及它的问题
var finalQuery =
from priceUpdate in **Observable<StockTick>**
group priceUpdate by priceUpdate.Stock into grouped
from combined in Observable.Interval(TimeSpan.FromSeconds(3))
.CombineLatest(grouped, (t, pei) => new { PEI = pei, Interval = t })
group combined by new { combined.Interval } into combined
select new
{
Interval = combined.Key.Interval,
PEI = combined.Select(c => new StockTick(c.PEI.Stock, c.PEI.Price))
};
finalQuery
.SelectMany(combined => combined.PEI)
.Distinct(pu => new { pu.Stock, pu.Price })
.Subscribe(priceUpdate =>
{
Process(priceUpdate);
});
public class StockTick
{
public StockTick(string stock, decimal price)
{
Stock = stock;
Price = price;
}
public string Stock {get;set;}
public decimal Price {get;set;}
}
因此,这将获得股票价格,按股票分组,然后结合该组的最新信息
带Observable.Interval
的ed序列。通过这种方式,我试图确保只处理一只股票的最新价格,并且每隔3秒就会激活一次。
然后再次按间隔对其进行分组,结果我每隔3秒钟就有一组序列。
最后一步,我使用SelectMany
将此序列压缩为股票价格更新序列,并且我正在应用Distinct
以确保同一股票的相同价格不会被处理两次。< / p>
我不喜欢这个查询有2个问题。首先,我真的不喜欢双人组 - 是否有任何方法可以避免它?第二 - 通过这种方法,我必须逐个处理价格,我真正想要的是快照 - 这是在3秒内,无论我有什么,我会扣上并发送处理,但可以弄清楚如何扣上。
我很乐意提出以其他方式解决这个问题的建议,但我更愿意留在Rx内,除非确实有更好的东西。
答案 0 :(得分:3)
一些事情:
Sample
运算符:DistinctUntilChanged
而不是Distinct
。如果您使用Distinct
,那么如果MSFT从$ 1变为$ 2然后又回到$ 1,那么您将不会在第三个滴答中获得一个事件。我想你的解决方案看起来像这样:
IObservable<StockTick> source;
source
.GroupBy(st => st.Stock)
.Select(stockObservable => stockObservable
.Sample(TimeSpan.FromSeconds(3))
.DistinctUntilChanged(st => st.Price)
)
.Merge()
.Subscribe(st => Process(st));
编辑(Distinct
性能问题):
每个Distinct
运算符都必须在其中维护完整的不同历史记录。如果你有一个高价的股票,例如AMZN,今天迄今为止的价格从958美元到974美元不等,那么你可能会得到大量的数据。在您取消订阅Distinct
之前,必须有大约1600个可能的数据点。它最终也会降低性能,因为每个AMZN滴答必须在经过之前与1600-ish的当前数据点进行比较。如果这是一个长期运行的过程(跨越多个交易日),那么你最终会得到更多的数据点。
鉴于N股,您有N Distinct
个运营商需要相应运营。将这种行为乘以N股,你就会遇到越来越多的问题。