聚合扩展是解决此问题的最佳方法还是我应该尝试对分组进行一些操作?

发布于 2024-10-03 09:20:22 字数 3924 浏览 6 评论 0原文

我正在使用股票数据源,并且想根据数据构建分钟柱(烛台)。我认为我有一个非常好的查询,可以为我提供所需的数据,但我不确定这是最好的方法。请提出您的任何意见或批评,我愿意接受您想要提供的任何意见。

左边输入,右边输出

class StockTick
{
    public DateTime Timestamp { get; set; }

    public int Id { get; set; }

    public decimal LastPrice { get; set; }
}

class FirstUda : CepAggregate<decimal, decimal>
{
    public override decimal GenerateOutput(IEnumerable<decimal> payloads)
    {
        return payloads.First();
    }
}

class LastUda : CepAggregate<decimal, decimal>
{
    public override decimal GenerateOutput(IEnumerable<decimal> payloads)
    {
        return payloads.Last();
    }
}

public static class CepExtensions
{
    [CepUserDefinedAggregate(typeof(FirstUda))]
    public static decimal First<InputT>(this CepWindow<InputT> window, Expression<Func<InputT, decimal>> map)
    {
        throw CepUtility.DoNotCall();
    }

    [CepUserDefinedAggregate(typeof(LastUda))]
    public static decimal Last<InputT>(this CepWindow<InputT> window, Expression<Func<InputT, decimal>> map)
    {
        throw CepUtility.DoNotCall();
    }
}

class Program
{
    static void Main(string[] args)
    {
        using (var server = Server.Create("Default"))
        {
            var app = server.CreateApplication("app");

            var source = GetStockTick();

            var input = source.ToPointStream(
                app,
                t => PointEvent.CreateInsert(t.Timestamp, t),
                AdvanceTimeSettings.IncreasingStartTime);

            var minuteWindows = input.AlterEventDuration(e => TimeSpan.FromTicks(TimeSpan.TicksPerMinute - (e.StartTime.Ticks % TimeSpan.TicksPerMinute)));

            var highLowTicks = from e in minuteWindows
                               group e by e.Id into g
                               from win in g.SnapshotWindow(SnapshotWindowOutputPolicy.Clip)
                               select new
                               {
                                   Id = g.Key,
                                   Timestamp = win.Max(e => e.Timestamp.AddSeconds(e.Timestamp.Second * -1)),
                                   OpenPrice = win.First(e => e.LastPrice),
                                   HighPrice = win.Max(t => t.LastPrice),
                                   LowPrice = win.Min(t => t.LastPrice),
                                   ClosePrice = win.Last(e => e.LastPrice)
                               };

            foreach (var hl in highLowTicks.ToEnumerable())
            {
                Console.WriteLine(hl);
            }

            Console.ReadKey();
        }
    }

    private static IEnumerable<StockTick> GetStockTick()
    {
        var ticks = new List<StockTick>();

        var baseTime = new DateTime(2010, 1, 1, 12, 0, 0);

        ticks.Add(new StockTick() { Id = 1, Timestamp = baseTime.AddSeconds(1), LastPrice = 10 });
        ticks.Add(new StockTick() { Id = 1, Timestamp = baseTime.AddSeconds(15), LastPrice = 8 });
        ticks.Add(new StockTick() { Id = 1, Timestamp = baseTime.AddSeconds(30), LastPrice = 12 });
        ticks.Add(new StockTick() { Id = 1, Timestamp = baseTime.AddSeconds(45), LastPrice = 11 });
        ticks.Add(new StockTick() { Id = 1, Timestamp = baseTime.AddSeconds(65), LastPrice = 13 });

        ticks.Add(new StockTick() { Id = 2, Timestamp = baseTime.AddSeconds(11), LastPrice = 35 });
        ticks.Add(new StockTick() { Id = 2, Timestamp = baseTime.AddSeconds(13), LastPrice = 37 });
        ticks.Add(new StockTick() { Id = 2, Timestamp = baseTime.AddSeconds(50), LastPrice = 22 });
        ticks.Add(new StockTick() { Id = 2, Timestamp = baseTime.AddSeconds(55), LastPrice = 32 });
        ticks.Add(new StockTick() { Id = 2, Timestamp = baseTime.AddSeconds(61), LastPrice = 36 });

        return ticks.OrderBy(t => t.Timestamp);
    }
}

I a working with a stock data feed and I want to build minute bars (candlesticks) out of the data. I think that I have a pretty good query that will give me the data that I need but I am not sure that it is the best way to go about it. Please give any comments or critisisms that you have, I am open to any input you want to give.

Input on the left and output on the right

class StockTick
{
    public DateTime Timestamp { get; set; }

    public int Id { get; set; }

    public decimal LastPrice { get; set; }
}

class FirstUda : CepAggregate<decimal, decimal>
{
    public override decimal GenerateOutput(IEnumerable<decimal> payloads)
    {
        return payloads.First();
    }
}

class LastUda : CepAggregate<decimal, decimal>
{
    public override decimal GenerateOutput(IEnumerable<decimal> payloads)
    {
        return payloads.Last();
    }
}

public static class CepExtensions
{
    [CepUserDefinedAggregate(typeof(FirstUda))]
    public static decimal First<InputT>(this CepWindow<InputT> window, Expression<Func<InputT, decimal>> map)
    {
        throw CepUtility.DoNotCall();
    }

    [CepUserDefinedAggregate(typeof(LastUda))]
    public static decimal Last<InputT>(this CepWindow<InputT> window, Expression<Func<InputT, decimal>> map)
    {
        throw CepUtility.DoNotCall();
    }
}

class Program
{
    static void Main(string[] args)
    {
        using (var server = Server.Create("Default"))
        {
            var app = server.CreateApplication("app");

            var source = GetStockTick();

            var input = source.ToPointStream(
                app,
                t => PointEvent.CreateInsert(t.Timestamp, t),
                AdvanceTimeSettings.IncreasingStartTime);

            var minuteWindows = input.AlterEventDuration(e => TimeSpan.FromTicks(TimeSpan.TicksPerMinute - (e.StartTime.Ticks % TimeSpan.TicksPerMinute)));

            var highLowTicks = from e in minuteWindows
                               group e by e.Id into g
                               from win in g.SnapshotWindow(SnapshotWindowOutputPolicy.Clip)
                               select new
                               {
                                   Id = g.Key,
                                   Timestamp = win.Max(e => e.Timestamp.AddSeconds(e.Timestamp.Second * -1)),
                                   OpenPrice = win.First(e => e.LastPrice),
                                   HighPrice = win.Max(t => t.LastPrice),
                                   LowPrice = win.Min(t => t.LastPrice),
                                   ClosePrice = win.Last(e => e.LastPrice)
                               };

            foreach (var hl in highLowTicks.ToEnumerable())
            {
                Console.WriteLine(hl);
            }

            Console.ReadKey();
        }
    }

    private static IEnumerable<StockTick> GetStockTick()
    {
        var ticks = new List<StockTick>();

        var baseTime = new DateTime(2010, 1, 1, 12, 0, 0);

        ticks.Add(new StockTick() { Id = 1, Timestamp = baseTime.AddSeconds(1), LastPrice = 10 });
        ticks.Add(new StockTick() { Id = 1, Timestamp = baseTime.AddSeconds(15), LastPrice = 8 });
        ticks.Add(new StockTick() { Id = 1, Timestamp = baseTime.AddSeconds(30), LastPrice = 12 });
        ticks.Add(new StockTick() { Id = 1, Timestamp = baseTime.AddSeconds(45), LastPrice = 11 });
        ticks.Add(new StockTick() { Id = 1, Timestamp = baseTime.AddSeconds(65), LastPrice = 13 });

        ticks.Add(new StockTick() { Id = 2, Timestamp = baseTime.AddSeconds(11), LastPrice = 35 });
        ticks.Add(new StockTick() { Id = 2, Timestamp = baseTime.AddSeconds(13), LastPrice = 37 });
        ticks.Add(new StockTick() { Id = 2, Timestamp = baseTime.AddSeconds(50), LastPrice = 22 });
        ticks.Add(new StockTick() { Id = 2, Timestamp = baseTime.AddSeconds(55), LastPrice = 32 });
        ticks.Add(new StockTick() { Id = 2, Timestamp = baseTime.AddSeconds(61), LastPrice = 36 });

        return ticks.OrderBy(t => t.Timestamp);
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

迟到的我 2024-10-10 09:20:22

瑞安,
看起来不错 - 只需检查这是否是预期的语义:

您将在每分钟内获得多个结果。对于每个输入事件,您将获得具有相同开始时间的结果事件,其中包含第一个(这一分钟内)和当前价格,以及迄今为止这一分钟内发生的最小值和最大值。因此,只有每分钟内的最后一个结果事件才会包含整分钟的第一个、最后一个、最小、最大。正确的?您不想每一分钟只发生一个事件吗?

罗马

Ryan,
Looks good - just checking whether this is the intended semantics:

You will get several results within each minute. For every input event, you will get a result event with the same start time, containing the first (in this minute) and the current price, as well as the min and max occurred in this minute so far. So only the very last result event within each minute will contain the first, last, min, max of the entire minute. Correct? You don't want just one event for each entire minute?

Roman

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文