redis / redis-py

Redis Python client
MIT License
12.57k stars 2.51k forks source link

Inconsistent behavior of bucket_size_msec argument in createrule function for creating 1-minute candles #3173

Open Alireza-Sampour opened 7 months ago

Alireza-Sampour commented 7 months ago

Version: redis-py: 5.0.2 and redis: 7.2.3

Platform: Python3.12 on Ubuntu 22.04

Description: I am using Redis TimeSeries to create a raw bucket and four OHLC (Open, High, Low, Close) compacted buckets. I have encountered an issue with the createrule function, specifically with the bucket_size_msec argument.

According to the documentation and the variable name itself, bucket_size_msec should represent the bucket size in milliseconds. However, when I run my test code to create 1-minute candles, setting bucket_size_msec = 60 * 1000 (60,000 milliseconds) fails to create the candles as expected. Surprisingly, when I set this parameter to 60, it successfully creates the 1-minute candles.

This behavior is inconsistent with the expected functionality. The bucket_size_msec argument should accept the bucket size in milliseconds, but it seems to be treating the value as seconds instead.

Could you please clarify if the bucket_size_msec parameter should indeed be specified in milliseconds? If so, why am I encountering this issue where setting it to 60 * 1000 fails, but setting it to 60 works?

I would appreciate your guidance on resolving this inconsistency and ensuring that the bucket_size_msec argument behaves as expected based on the documentation.

Thank you for your attention to this matter.

import redis

from pytz import timezone
from datetime import datetime
from typing import List, Tuple
from random import randint, seed

seed(1)
rd_key = "test_candles"
start_time = "2024-02-28 09:00:00"
market_ticks = []
start_timestamp = int(datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S").timestamp())
rd = redis.Redis(host="HOST", password="PASS", db=1, decode_responses=True)
ts = rd.ts()

def setup():
    # Clearing the previous data
    rd.delete(rd_key)
    rd.delete(f"{rd_key}_open")
    rd.delete(f"{rd_key}_high")
    rd.delete(f"{rd_key}_low")
    rd.delete(f"{rd_key}_close")

    # Creating new time series
    ts.create(rd_key)
    ts.create(f"{rd_key}_open")
    ts.create(f"{rd_key}_high")
    ts.create(f"{rd_key}_low")
    ts.create(f"{rd_key}_close")

    # Creating rules for the time series
    ts.createrule(rd_key, f"{rd_key}_open", "first", 1000 * 60)
    ts.createrule(rd_key, f"{rd_key}_high", "max", 1000 * 60)
    ts.createrule(rd_key, f"{rd_key}_low", "min", 1000 * 60)
    ts.createrule(rd_key, f"{rd_key}_close", "last", 1000 * 60)

def get_prices() -> Tuple[List, List, List, List]:
    open_prices = ts.range(f"{rd_key}_open", "-", "+")
    high_prices = ts.range(f"{rd_key}_high", "-", "+")
    low_prices = ts.range(f"{rd_key}_low", "-", "+")
    close_prices = ts.range(f"{rd_key}_close", "-", "+")

    return open_prices, high_prices, low_prices, close_prices

def create_candles(open_prices: List, high_prices: List, low_prices: List, close_prices: List) -> List[Tuple[int, float, float, float, float]]:
    candles = []
    for i in range(len(open_prices)):
        candles.append((open_prices[i][0], open_prices[i][1], high_prices[i][1], low_prices[i][1], close_prices[i][1]))

    return candles

def print_candles(candles: List[Tuple[int, float, float, float, float]]):
    for timestamp, open, high, low, close in candles:
        print(f"{datetime.fromtimestamp(timestamp, tz=timezone('UTC')):%Y-%m-%d %H:%M:%S}, open: {open}, high: {high}, low: {low}, close: {close}")

if __name__ == "__main__":
    setup()
    for i in range(1, 1001):
        market_ticks.append((rd_key, int(start_timestamp), (i + randint(-100, 100))))
        start_timestamp += 12.6

    ts.madd(market_ticks)
    candles = create_candles(*get_prices())
    print_candles(candles)
sarabisohrab commented 7 months ago

I have the same problem!

atharva29 commented 6 months ago

Thank you so much brother, for highlighting this bug, I am also facing same issue