Reactive programming 如何在RxJava中计算移动平均

Reactive programming 如何在RxJava中计算移动平均,reactive-programming,rx-java,Reactive Programming,Rx Java,在金融领域,我们通常需要从时间序列数据流中计算移动窗口聚合值,以移动平均为例,假设我们有以下数据流(T为时间戳,V为实际值): 要根据我们得到的数据流计算移动平均值3: avg([T0,V0],[T1,V1],[T2,V2]), avg([T1,V1],[T2,V2],[T3,V3]), avg([T2,V2],[T3,V3],[T4,V4]), avg([T3,V3],[T4,V4],[T5,V5]), avg([T4,V4],[T5,V5],[T6,V6]),... 要计算移动平均线,我们

在金融领域,我们通常需要从时间序列数据流中计算移动窗口聚合值,以移动平均为例,假设我们有以下数据流(T为时间戳,V为实际值):

要根据我们得到的数据流计算移动平均值3:

avg([T0,V0],[T1,V1],[T2,V2]),
avg([T1,V1],[T2,V2],[T3,V3]),
avg([T2,V2],[T3,V3],[T4,V4]),
avg([T3,V3],[T4,V4],[T5,V5]),
avg([T4,V4],[T5,V5],[T6,V6]),...
要计算移动平均线,我们似乎可以通过以下方式进行计算:

  • 从原始流构建一个可观察的
  • 通过将值聚合到组中,从原始流中构建一个可观察值
  • 使用聚合运算符计算步骤2中可观察到的最终结果
  • 第1步和第3步实现起来很简单,但是,对于第2步来说,当前的RxJava似乎没有生成移动窗口组的内置操作符,窗口/groupBy操作符似乎不适合这种情况,我也没有找到一种简单的方法来从现有的操作符组成一个解决方案,有人能建议如何“优雅地”在RxJava中实现这一点吗时尚

    RxJava版本:0.15.1

    import java.util.List;
    进口接收。可观察;
    导入rx.util.functions.Action1;
    类条{
    公共静态void main(字符串args[]){
    整数arr[]={1,2,3,4,5,6};//N=6
    可观测oi=可观测自(arr);
    //1.-捆3,跳过1
    oi.缓冲区(3,1)
    /**                                                                     
    *2.-只取前X捆
    *当bundle 3时,X=N-2=>4
    *当bundle 4时,X=N-3=>3
    *当束a时,X=N-(a-1)
    */                                                                     
    .take(4)
    //3.计算平均值
    .subscribe(新操作1(){
    @凌驾
    公共作废调用(列表lst){
    整数和=0;
    对于(inti=0;i”+sum/lst.size());
    }                                                                   
    });                                                                     
    }                                                                           
    }  
    
    样本输出:

    MA(3)[1,2,3]=>2

    MA(3)[2,3,4]=>3

    MA(3)[3,4,5]=>4

    MA(3)[4,5,6]=>5

    我会这样做:

    公共静态可观测移动平均值(可观测o,int N){
    返回o.窗口(N,1).平面图(
    新功能1(){
    公共可观察呼叫(可观察窗口){
    返回可观察。平均双倍(窗口);
    }
    }
    );
    }
    
    • 我使用的是
      窗口
      (它发出可观察数据,只消耗恒定的内存量),而不是
      缓冲区
      (它发出列表,为每个项目消耗内存)
    • 这是一个例子,说明如何使用组合运算符而不是编写自己的循环,这是使用可见项时应该考虑的事情。
    更新:如果要过滤掉流末尾元素少于
    n
    的窗口,可以这样做:

    def移动平均值(o:Observable[Double],n:Int):Observable[Double]={
    类状态(值和:双精度,值n:Int)
    o、 窗口(n,1).flatMap(win=>
    win.foldLeft(新状态(0.0,0))((s,e)=>新状态(s.sum+e,s.n+1))
    .filter(s=>s.n==n)
    .map(s=>s.sum/s.n))
    }
    

    (我选择Scala是因为它写起来比较短,但在Java中,你也可以这么做,只需注意Scala的
    foldLeft
    在Java中被称为
    reduce

    谢谢你的回答,在这个例子中,我在缓冲区解决方案中提出了一个后续问题,因为它将值聚合到一个列表中,然后我们可以根据列表的大小进行筛选(假设我们只希望chunks大小为3,并且源代码只包含5个值,那么我们只关心前3个窗口,去掉尾部没有3个值),在这种情况下如何筛选?或者,这可能是一个更一般的问题,即如何根据窗口的大小过滤出窗口(观察)
    avg([T0,V0],[T1,V1],[T2,V2]),
    avg([T1,V1],[T2,V2],[T3,V3]),
    avg([T2,V2],[T3,V3],[T4,V4]),
    avg([T3,V3],[T4,V4],[T5,V5]),
    avg([T4,V4],[T5,V5],[T6,V6]),...