#!/usr/bin/env perl use strict; use warnings; use PDL; use PDL::NiceSlice; use Time::Local; # Sample tick data: array of arrays [timestamp, price, volume] # Example: ["2025-01-12 09:30:00", 100.5, 200] my $tick_data = [ ["2025-01-12 09:30:00", 100.5, 200], ["2025-01-12 09:30:15", 101.0, 150], ["2025-01-12 09:30:30", 100.8, 100], ["2025-01-12 09:30:45", 101.2, 300], ["2025-01-12 09:31:00", 101.0, 250], ]; # Group data into OHLCV intervals (e.g., 1 minute) my $interval_seconds = 20; # Set interval in seconds # Helper: Convert timestamp to epoch sub timestamp_to_epoch { my ($timestamp) = @_; my ($date, $time) = split(' ', $timestamp); my ($year, $month, $day) = split('-', $date); my ($hour, $min, $sec) = split(':', $time); return timelocal($sec, $min, $hour, $day, $month - 1, $year); } # Pre-process: Add epoch to data my $data = pdl([ map { my $epoch = timestamp_to_epoch($_->[0]); [$epoch, $_->[1], $_->[2]] } @$tick_data ]); for my $i (0..$data->dim(1)-1) { my $ts = $data->at(0,$i); my $p = $data->at(1,$i); my $v = $data->at(2,$i); } # Find unique interval buckets my $start_epoch = $data((0), 0); my $intervals = floor(($data(0, -1) - $start_epoch) / $interval_seconds); # Compute OHLCV my ($open, $high, $low, $close, $volume) = ([], [], [], [], []); for my $i (0 .. max($intervals)) { my $group = $data->where(floor(($data - $start_epoch) / $interval_seconds)== $i); next if $group->nelem == 0; # Skip empty groups # push @$open, $group(0, 1); # First price # push @$high, max($group(:, 1)); # push @$low, min($group(:, 1)); # push @$close, $group((($group->dim(0) - 1)), 1); # Last price # push @$volume, sum($group(:, 2)); } # Convert OHLCV to PDL for display #my $ohlcv = pdl($open, $high, $low, $close, $volume)->transpose; # Output results #print "OHLCV Format (Open, High, Low, Close, Volume):\n"; #print $ohlcv;