Files
ferro-ta/benchmarks/bench_batch.py
T
2026-03-23 23:34:28 +05:30

66 lines
2.4 KiB
Python

import time
import numpy as np
import ferro_ta
def _time_fn(fn, *args, **kwargs):
times = []
# Warmup
fn(*args, **kwargs)
for _ in range(5):
t0 = time.perf_counter()
fn(*args, **kwargs)
times.append(time.perf_counter() - t0)
return min(times)
def main():
n_samples = 100_000
n_series = 100
print(f"Batch Benchmark: {n_samples} bars, {n_series} series (Total: {n_samples*n_series/1e6:.1f} M bars)")
np.random.seed(42)
# contiguous array in row-major
close2d = np.random.uniform(100.0, 200.0, (n_samples, n_series))
h2d = close2d + np.random.uniform(0.1, 2.0, (n_samples, n_series))
l2d = close2d - np.random.uniform(0.1, 2.0, (n_samples, n_series))
print("-" * 50)
print(f"{'Indicator':<15} {'Batch (ms)':>12} {'Loop (ms)':>12} {'Speedup':>10}")
print("-" * 50)
# 1. SMA
kwargs = {"timeperiod": 14}
def loop_sma(arr):
for j in range(arr.shape[1]):
ferro_ta.SMA(arr[:, j], **kwargs)
t_batch_sma = _time_fn(ferro_ta.batch.batch_sma, close2d, **kwargs)
t_loop_sma = _time_fn(loop_sma, close2d)
print(f"SMA {t_batch_sma*1000:12.1f} {t_loop_sma*1000:12.1f} {t_loop_sma/t_batch_sma:9.1f}x")
# 2. RSI
def loop_rsi(arr):
for j in range(arr.shape[1]):
ferro_ta.RSI(arr[:, j], **kwargs)
t_batch_rsi = _time_fn(ferro_ta.batch.batch_rsi, close2d, **kwargs)
t_loop_rsi = _time_fn(loop_rsi, close2d)
print(f"RSI {t_batch_rsi*1000:12.1f} {t_loop_rsi*1000:12.1f} {t_loop_rsi/t_batch_rsi:9.1f}x")
# 3. ATR
def loop_atr(h, l, c):
for j in range(h.shape[1]):
ferro_ta.ATR(h[:, j], l[:, j], c[:, j], **kwargs)
t_batch_atr = _time_fn(ferro_ta.batch.batch_atr, h2d, l2d, close2d, **kwargs)
t_loop_atr = _time_fn(loop_atr, h2d, l2d, close2d)
print(f"ATR {t_batch_atr*1000:12.1f} {t_loop_atr*1000:12.1f} {t_loop_atr/t_batch_atr:9.1f}x")
# 4. ADX
def loop_adx(h, l, c):
for j in range(h.shape[1]):
ferro_ta.ADX(h[:, j], l[:, j], c[:, j], **kwargs)
t_batch_adx = _time_fn(ferro_ta.batch.batch_adx, h2d, l2d, close2d, **kwargs)
t_loop_adx = _time_fn(loop_adx, h2d, l2d, close2d)
print(f"ADX {t_batch_adx*1000:12.1f} {t_loop_adx*1000:12.1f} {t_loop_adx/t_batch_adx:9.1f}x")
if __name__ == '__main__':
main()