1

I want to convert tick by tick data to 1, 5,10 minutes, 1 hour, 2 hours time frame based on time frame. Data looks like below every second data.

var source = new List<TickData>()
    {
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:00:02.100"), Price = Convert.ToDouble("294.00"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:00:32.680"), Price = Convert.ToDouble("296"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:00:36.263"), Price = Convert.ToDouble("295.08"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:00:42.090"), Price = Convert.ToDouble("295.08"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:00:42.127"), Price = Convert.ToDouble("295.08"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:00:46.357"), Price = Convert.ToDouble("295.02"), Volume = Convert.ToInt32("500")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:00:46.357"), Price = Convert.ToDouble("292.00"), Volume = Convert.ToInt32("500")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:00:46.598"), Price = Convert.ToDouble("295.02"), Volume = Convert.ToInt32("500")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:00:47.168"), Price = Convert.ToDouble("295.02"), Volume = Convert.ToInt32("500")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:00:47.914"), Price = Convert.ToDouble("295.02"), Volume = Convert.ToInt32("500")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:00:48.290"), Price = Convert.ToDouble("295.02"), Volume = Convert.ToInt32("500")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:00:49.391"), Price = Convert.ToDouble("295.02"), Volume = Convert.ToInt32("500")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:00:49.854"), Price = Convert.ToDouble("295.02"), Volume = Convert.ToInt32("500")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:00:49.854"), Price = Convert.ToDouble("295.02"), Volume = Convert.ToInt32("500")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:00:50.024"), Price = Convert.ToDouble("295.99"), Volume = Convert.ToInt32("500")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:01:22.893"), Price = Convert.ToDouble("295.2"), Volume = Convert.ToInt32("100" )},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:02:36.026"), Price = Convert.ToDouble("295.21"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:02:43.101"), Price = Convert.ToDouble("295.21"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:02:46.025"), Price = Convert.ToDouble("295.2"), Volume = Convert.ToInt32("1900")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:02:46.526"), Price = Convert.ToDouble("295.21"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:02:46.527"), Price = Convert.ToDouble("295.2"), Volume = Convert.ToInt32("1900")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:02:54.163"), Price = Convert.ToDouble("295.21"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:02:56.029"), Price = Convert.ToDouble("295.2"), Volume = Convert.ToInt32("1900")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:02:56.370"), Price = Convert.ToDouble("295.21"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:02:56.371"), Price = Convert.ToDouble("295.2"), Volume = Convert.ToInt32("1900")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:02:56.530"), Price = Convert.ToDouble("295.21"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:03:34.546"), Price = Convert.ToDouble("295.41"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:04:27.331"), Price = Convert.ToDouble("295.41"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:04:35.805"), Price = Convert.ToDouble("295.35"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:06:34.495"), Price = Convert.ToDouble("295.37"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:06:48.211"), Price = Convert.ToDouble("295.37"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:06:48.857"), Price = Convert.ToDouble("295.37"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:06:52.385"), Price = Convert.ToDouble("295.37"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:06:57.519"), Price = Convert.ToDouble("295.37"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:07:14.514"), Price = Convert.ToDouble("295.55"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:07:15.370"), Price = Convert.ToDouble("295.41"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:08:14.167"), Price = Convert.ToDouble("295.55"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:08:14.167"), Price = Convert.ToDouble("295.41"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:08:16.583"), Price = Convert.ToDouble("295.41"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:08:16.590"), Price = Convert.ToDouble("295.41"), Volume = Convert.ToInt32("200")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:08:18.260"), Price = Convert.ToDouble("295.41"), Volume = Convert.ToInt32("200")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:08:18.857"), Price = Convert.ToDouble("295.41"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:08:20.425"), Price = Convert.ToDouble("295.41"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:08:22.247"), Price = Convert.ToDouble("295.41"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:09:19.030"), Price = Convert.ToDouble("295.5"), Volume = Convert.ToInt32("100" )},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:09:54.711"), Price = Convert.ToDouble("295.5"), Volume = Convert.ToInt32("100" )},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:10:10.505"), Price = Convert.ToDouble("295.5"), Volume = Convert.ToInt32("100" )},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:10:54.926"), Price = Convert.ToDouble("295.5"), Volume = Convert.ToInt32("100" )},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:11:01.927"), Price = Convert.ToDouble("295.5"), Volume = Convert.ToInt32("1100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:11:58.106"), Price = Convert.ToDouble("295.41"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:12:09.706"), Price = Convert.ToDouble("295.41"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:12:14.453"), Price = Convert.ToDouble("295.41"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:12:38.186"), Price = Convert.ToDouble("295.41"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:13:10.196"), Price = Convert.ToDouble("295.52"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:13:58.690"), Price = Convert.ToDouble("295.49"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:14:03.660"), Price = Convert.ToDouble("295.45"), Volume = Convert.ToInt32("100")},
            new TickData{ Timestamp = Convert.ToDateTime("2020-01-02 04:14:35.205"), Price = Convert.ToDouble("295.45"), Volume = Convert.ToInt32("100")}

    };

sample data can have multiple ticks/multiple data points in a seconds. I tried below, but it is not working as expected.

var period = TimeSpan.FromMinutes(1);


    var ohlcv = source.Select(d => new
    {
        Time = d.Timestamp,
        d.Price,

        d.Volume,
        Period = d.Timestamp.Ticks / period.Ticks
    })
         .GroupBy(d => d.Period)
         .Select(g => new Ohlc()
         {
             Timestamp = g.Min(d => d.Time),
             Open = g.FirstOrDefault().Price,
             Close = g.LastOrDefault().Price,
             Low = g.Min(d => d.Price),
             High = g.Max(d => d.Price),
             Volume = g.Sum(d => d.Volume)
         });

    foreach (var ohlc in ohlcv)
    {
        Console.WriteLine($"T:{ohlc.Timestamp} O:{ohlc.Open}, H:{ohlc.High}, C:{ohlc.Close}, L:{ohlc.Low}, V:{ohlc.Volume}");
    }

this gives following output, which is not correct.

T:02-01-2020 04:00:02 O:294, H:294, C:294, L:294, V:100
T:02-01-2020 04:00:32 O:296, H:296, C:296, L:296, V:100
T:02-01-2020 04:00:36 O:295.08, H:295.08, C:295.08, L:295.08, V:300
T:02-01-2020 04:00:46 O:295.02, H:295.02, C:295.02, L:295.02, V:4000
T:02-01-2020 04:00:46 O:292, H:292, C:292, L:292, V:500
T:02-01-2020 04:00:50 O:295.99, H:295.99, C:295.99, L:295.99, V:500
T:02-01-2020 04:01:22 O:295.2, H:295.2, C:295.2, L:295.2, V:7700
T:02-01-2020 04:02:36 O:295.21, H:295.21, C:295.21, L:295.21, V:600
T:02-01-2020 04:03:34 O:295.41, H:295.41, C:295.41, L:295.41, V:1600
T:02-01-2020 04:04:35 O:295.35, H:295.35, C:295.35, L:295.35, V:100
T:02-01-2020 04:06:34 O:295.37, H:295.37, C:295.37, L:295.37, V:500
T:02-01-2020 04:07:14 O:295.55, H:295.55, C:295.55, L:295.55, V:200
T:02-01-2020 04:09:19 O:295.5, H:295.5, C:295.5, L:295.5, V:1500
T:02-01-2020 04:13:10 O:295.52, H:295.52, C:295.52, L:295.52, V:100
T:02-01-2020 04:13:58 O:295.49, H:295.49, C:295.49, L:295.49, V:100
T:02-01-2020 04:14:03 O:295.45, H:295.45, C:295.45, L:295.45, V:200

OHLCV, Open is nothing but, first tick/second data point of that minute, High max value of price from Minute(or given time frame), Low is small value of time frame, Close is last value of that timeframe. Any help would be appreciated.

Python data frames are good for resample data in different time frame example python eg. Can it be possible to resample in different timeframe with c# code using linq or any other way?

Sample code of python, expecting same behavior.

df=pd.DataFrame(data,columns=['Date','Value'])
df['Date']=pd.to_datetime(df['Date'])
minutes=df.resample('1Min',on='Date').mean().dropna()
Venkat B
  • 73
  • 4
  • Can you give a better example and explanation of the input and expected output of your data? – gunr2171 Jul 22 '22 at 13:05
  • If you wanted to do this yourself you could show the code for your attempt or we could discuss the algorithm. But as it is, your question doesn't meet the minimum bar. – Wyck Jul 22 '22 at 13:05
  • @Wyck the question doesn't ask for library recommendations – Panagiotis Kanavos Jul 22 '22 at 13:06
  • Not even then. Google `Rx.NET`. The rule doesn't say "don't ask for recommendations" it say don't ask when it leads to opinions. There are similar questions already – Panagiotis Kanavos Jul 22 '22 at 13:07
  • I know. That's why I wrote `not even then`. The close reason says `This question is likely to lead to opinion-based answers.`. That's not the case here at all. Resampling is possible using both LINQ or Reactive Extensions which is tailor-made for event streams – Panagiotis Kanavos Jul 22 '22 at 13:11
  • @gunr2171 example is is available in mentioned link in python eg. By the way it is standard terminalogy in time series data. Resampling seconds data to different time frame. Yes I should have mentioned little clearly, how to resample seconds data to OHLCV. I will update question. – Venkat B Jul 22 '22 at 19:51
  • @Wyck update question with sample data and expected output. – Venkat B Jul 24 '22 at 13:51
  • You didn't post the expected output. You don't need to use `Convert.ToDouble("295.5")` to specify a double, just type the number `295.5`. Same with integers – Panagiotis Kanavos Jul 25 '22 at 07:41
  • This question is not about how to prepare data, this is sample data I was reading from csv, same code based used for easy understanding. Expected output is OHLCV. I don't have any custom output. OHLCV is standard output for stock data. Anyway I will add sample output also. – Venkat B Jul 25 '22 at 17:39

2 Answers2

3

The question doesn't explain what the expected results are, so this is a best guess.

One possibility is to calculate the interval by dividing the timestamp's Ticks property with the period we want, then group by that result :

var period = TimeSpan.FromMinutes(5);

var stats = source.Select(d => new
    {
        d.Timestamp,
        d.Price,
        d.Volume,
        Span = d.Timestamp.Ticks / period.Ticks
    })
    .GroupBy(d => d.Span)
    .Select(g => new Ohlc
    {
        Timestamp = new DateTime(period.Ticks*g.Key),
        Open = g.OrderBy(s => s.Timestamp).First().Price,
        Close = g.OrderBy(s => s.Timestamp).Last().Price,
        Low = g.Min(s => s.Price),
        High = g.Max(s => s.Price),
        Volume=g.Sum(s=>s.Volume)
    });

d.Timestamp.Ticks / period.Ticks calculates the Span we want to report on. The Span result is a long because the Ticks properties in both DateTime and Timespan are long. As a result, TickData.Timestamp values inside a specific span will be mapped to the same Span value, matching the start of that span.

To get back the start of that period we need to multiply it with the span's ticks, which just happen to be the group key :

Timestamp = new DateTime(period.Ticks*g.Key)

To calculate Open and Close we need to order the results again. Even if the original series was ordered, there's no guarantee the data inside the group will still be order. This will depend on the actual LINQ provider. If the data comes from a database, there won't be any order guarantee. Using PLINQ to speed up processing of large data volumes can also change the order.

Open = g.OrderBy(s => s.Timestamp).First().Price,
Close = g.OrderBy(s => s.Timestamp).Last().Price,

For the question's data set :

var source = new List<TickData>()
{
    new() {Timestamp = DateTime.Parse("2020-01-02 04:00:02.100"), Price = 294.00D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:00:32.680"), Price = 296.00D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:00:36.263"), Price = 295.08D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:00:42.090"), Price = 295.08D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:00:42.127"), Price = 295.08D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:00:46.357"), Price = 295.02D, Volume = 500},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:00:46.357"), Price = 292.00D, Volume = 500},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:00:46.598"), Price = 295.02D, Volume = 500},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:00:47.168"), Price = 295.02D, Volume = 500},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:00:47.914"), Price = 295.02D, Volume = 500},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:00:48.290"), Price = 295.02D, Volume = 500},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:00:49.391"), Price = 295.02D, Volume = 500},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:00:49.854"), Price = 295.02D, Volume = 500},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:00:49.854"), Price = 295.02D, Volume = 500},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:00:50.024"), Price = 295.99D, Volume = 500},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:01:22.893"), Price = 295.2D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:02:36.026"), Price = 295.21D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:02:43.101"), Price = 295.21D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:02:46.025"), Price = 295.2D, Volume = 1900},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:02:46.526"), Price = 295.21D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:02:46.527"), Price = 295.2D, Volume = 1900},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:02:54.163"), Price = 295.21D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:02:56.029"), Price = 295.2D, Volume = 1900},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:02:56.370"), Price = 295.21D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:02:56.371"), Price = 295.2D, Volume = 1900},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:02:56.530"), Price = 295.21D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:03:34.546"), Price = 295.41D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:04:27.331"), Price = 295.41D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:04:35.805"), Price = 295.35D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:06:34.495"), Price = 295.37D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:06:48.211"), Price = 295.37D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:06:48.857"), Price = 295.37D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:06:52.385"), Price = 295.37D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:06:57.519"), Price = 295.37D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:07:14.514"), Price = 295.55D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:07:15.370"), Price = 295.41D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:08:14.167"), Price = 295.55D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:08:14.167"), Price = 295.41D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:08:16.583"), Price = 295.41D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:08:16.590"), Price = 295.41D, Volume = 200},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:08:18.260"), Price = 295.41D, Volume = 200},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:08:18.857"), Price = 295.41D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:08:20.425"), Price = 295.41D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:08:22.247"), Price = 295.41D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:09:19.030"), Price = 295.5D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:09:54.711"), Price = 295.5D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:10:10.505"), Price = 295.5D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:10:54.926"), Price = 295.5D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:11:01.927"), Price = 295.5D, Volume = 1100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:11:58.106"), Price = 295.41D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:12:09.706"), Price = 295.41D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:12:14.453"), Price = 295.41D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:12:38.186"), Price = 295.41D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:13:10.196"), Price = 295.52D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:13:58.690"), Price = 295.49D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:14:03.660"), Price = 295.45D, Volume = 100},
    new() {Timestamp = DateTime.Parse("2020-01-02 04:14:35.205"), Price = 295.45D, Volume = 100}
};

This dotnetfiddle produces the following results for a 5 minute period:

T:2020-01-02T04:00:00 O:294.00, H:296.00, C:295.35, L:292.00, V:14100
T:2020-01-02T04:05:00 O:295.37, H:295.55, C:295.50, L:295.37, V:1900
T:2020-01-02T04:10:00 O:295.50, H:295.52, C:295.45, L:295.41, V:2100

Parallelizing the query only requires adding AsParallel(). That's guaranteed to produce the final results out-of-order though, so a final OrderBy(o=>o.Timestamp) is needed:

var stats = source.AsParallel()
    .Select(d => new
    {
        d.Timestamp,
        d.Price,
        d.Volume,
        Span = d.Timestamp.Ticks / period.Ticks
    })
    .GroupBy(d => d.Span)
    .Select(g => new Ohlc
    {
        Timestamp = new DateTime(period.Ticks*g.Key),
        Open = g.OrderBy(s => s.Timestamp).First().Price,
        Close = g.OrderBy(s => s.Timestamp).Last().Price,
        Low = g.Min(s => s.Price),
        High = g.Max(s => s.Price),
        Volume=g.Sum(s=>s.Volume)
    })
    .OrderBy(o=>o.Timestamp);
Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
  • 1
    This may not work if the time series data is not in chronological order I will check and update. Thank you – Venkat B Jul 22 '22 at 19:59
  • it is not working as expected, I have update question with sample data and expected output. – Venkat B Jul 24 '22 at 13:50
  • @VenkatB you hadn't provided *any* information when I posted this answer. This was more to prevent downvotes and closing the incomplete question. If the data isn't in chronological order, `OrderBy` will sort it. `Is not working as expected` doesn't explain anything. What *is* expected? Post the numbers, not descriptions of the numbers – Panagiotis Kanavos Jul 25 '22 at 07:42
  • What happens when the interval is larger than span of candles? Say I want to resample on a Daily interval, but my candles are only from 9AM-4PM? `Span = d.Timestamp.Ticks / period.Ticks` will not divide evenly, and since this is a long, you will loose the decimal points which when you convert back to Timestamp `Timestamp = new DateTime(period.Ticks*g.Key),` That decimal portion will be lost. – DevEng Apr 04 '23 at 05:02
  • Unless you do something like `Timestamp = s.OrderBy(o => o.Timestamp ).First().Timestamp` which might work instead of `new DateTime(period.Ticks*g.Key)`. You fetch the first date of the interval, just like the Open and Close – DevEng Apr 04 '23 at 05:33
0

Timeseries resampling to different time frame, equal to pandas.resample

var period = TimeSpan.FromMinutes(1);

var ohlcv = source.OrderBy(p=>p.Timestamp).Select(d => new
    {
        Time = d.Timestamp,
        d.Price,

        d.Volume,
        Period = d.Timestamp.Ticks / period.Ticks
    })
         .GroupBy(d => d.Period)
         .Select(g => new Ohlc()
         {
             Timestamp = g.Min(d => d.Time),
             Open = g.FirstOrDefault().Price,
             Close = g.LastOrDefault().Price,
             Low = g.Min(d => d.Price),
             High = g.Max(d => d.Price),
             Volume = g.Sum(d => d.Volume)
         });
Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
bommina
  • 307
  • 4
  • 16