Rx.Net - 获取股票价格变化并处理它们

时间:2017-07-02 17:56:49

标签: system.reactive

我正在努力解决的问题

  1. 获取股票评分
  2. 始终考虑最新股票价格
  3. 每个 x 秒获取刻度线的快照并发送处理
  4. 所以我有一个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内,除非确实有更好的东西。

1 个答案:

答案 0 :(得分:3)

一些事情:

  1. 您希望利用Sample运算符:
  2. 您可能需要DistinctUntilChanged而不是Distinct。如果您使用Distinct,那么如果MSFT从$ 1变为$ 2然后又回到$ 1,那么您将不会在第三个滴答中获得一个事件。
  3. 我想你的解决方案看起来像这样:

    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股,你就会遇到越来越多的问题。

相关问题