如何通过LINQ将一个列表转换为另一个半聚合列表?

时间:2010-05-10 21:57:10

标签: c# .net linq dynamic aggregate

我是Linq的初学者,所以只是想找人告诉我是否可以通过Linq实现以下操作,如果有的话,可以指出如何实现。

我想将一个金融时间序列列表转换为另一个金融时间序列列表,其中第二个系列列表将与第一个列表相同或更短(通常它会更短,即,它变成一个新列表,其中元素本身代表聚合来自第1列表的一个或多个元素的信息)。它如何将列表从一个折叠到另一个取决于第一个列表中的数据。该算法需要跟踪在添加到第二个列表的新元素时重置的计算。通过示例描述可能更容易:

清单1(从收尾价格和交易量的开始到结束系列订购的时间):

{P = 7,V = 1},{P = 10,V = 2},{P = 10,V = 1},{P = 10,V = 3},{P = 11,V = 5},{P = 12,V = 1},{P = 13,V = 2},{P = 17,V = 1},{P = 15,V = 4},{P = 14,V = 10},{P = 14,V = 8},{P = 10,V = 2},{P = 9,V = 3},{P = 8,V = 1}

列表2(使用这两个参数设置将列表1转换为列表2的这一范围周期的系列开/关价格范围和总和:参数1:价格范围步长= 3,参数2:价格范围逆转步长= 6):

{O = 7,C = 10,V = 1 + 2 + 1},{O = 10,C = 13,V = 3 + 5 + 1 + 2},{O = 13,C = 16, V = 0},{O = 16,C = 10,V = 1 + 4 + 10 + 8 + 2},{O = 10,C = 8,V = 3 + 1}

在列表2中,我明确地显示了列表2中列表1的V属性的总和。但是V只是一个长的所以它实际上只是一个数字。所以这是如何工作的开放时间序列价格是7.然后我们正在寻找从这个初始起始价格的第一个价格,其中delta是3离3(通过参数1设置)。在列表1中,当我们通过列表移动时,下一步是向上移动到10,因此我们已经建立了“上升趋势”。所以现在我们在列表2中构建我们的第一个元素,其中Open = 7,Close = 10并总结第一个列表中使用的所有条形的体积以进入列表2中的第一步。现在,下一个元素起始点是10.建立另一个上升步骤,我们需要向上推进另外3个以创建另一个上升步骤,或者我们可以反转并向下移动6(参数2)。使用列表1中的数据,我们首先达到13,因此在列表2中构建我们的第二个元素,并总结用于执行此步骤的所有V属性。我们继续这个过程,直到列表1处理结束。

注意列表1中发生的间隙跳转。我们仍然想要创建{O = 13,C = 16,V = 0}的步长元素。 V的0只是简单地说我们有一个范围移动通过这一步但是体积为0(这里没有列表1的实际价格 - 它高于它但是我们想要建立导致价格的一组步骤它在它之上)。

列表2中的倒数第二个条目表示从上到下的反转。

列表2中的最终条目仅使用列表1中的最终关闭,即使它尚未完成建立全范围步骤。

感谢您提供有关如何通过Linq进行此操作的指示。

1 个答案:

答案 0 :(得分:1)

我的第一个想法是,为什么要尝试使用LINQ呢?对于使用Enumerable关键字进行部分处理然后吐出答案来制作新yield似乎更好的情况。

有些事情如下:

public struct PricePoint
{
    ulong price;
    ulong volume;
}

public struct RangePoint
{
    ulong open;
    ulong close;
    ulong volume;
}

public static IEnumerable<RangePoint> calculateRanges(IEnumerable<PricePoint> pricePoints)
{
    if (pricePoints.Count() > 0)
    {
        ulong open = pricePoints.First().price;
        ulong volume = pricePoints.First().volume;

        foreach(PricePoint pricePoint in pricePoints.Skip(1))
        {
            volume += pricePoint.volume;
            if (pricePoint.price > open)
            {
                if ((pricePoint.price - open) >= STEP)
                {
                    // We have established a up-trend.
                    RangePoint rangePoint;
                    rangePoint.open = open;
                    rangePoint.close = close;
                    rangePoint.volume = volume;

                    open = pricePoint.price;
                    volume = 0;

                    yield return rangePoint;
                }
            }
            else
            {
                if ((open - pricePoint.price) >= REVERSAL_STEP)
                {
                    // We have established a reversal.
                    RangePoint rangePoint;
                    rangePoint.open = open;
                    rangePoint.close = pricePoint.price;
                    rangePoint.volume = volume;

                    open = pricePoint.price;
                    volume = 0;

                    yield return rangePoint;
                }
            }
        }

        RangePoint lastPoint;
        lastPoint.open = open;
        lastPoint.close = pricePoints.Last().price;
        lastPoint.volume = volume;
        yield return lastPoint;
    }
}

这还没有完成。例如,它不处理间隙,并且存在未处理的边缘情况,其中可能消耗最后一个数据点,但它仍将处理“lastPoint”。但它应该足以开始。