Metadata-Version: 2.4
Name: kline_timestamp
Version: 0.3.0
Summary: KlineTimestamp is a Python library designed to efficiently handle timestamps within discrete time intervals (klines/candlesticks), commonly used in financial data analysis.
Home-page: https://github.com/nand0san/kline_timestamp
Author: nand0san
Author-email: 
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Topic :: Office/Business :: Financial :: Investment
Classifier: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pandas<3.0,>=2.3.0
Requires-Dist: pytz>=2024.1
Dynamic: author
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: license-file
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary


# KlineTimestamp

**KlineTimestamp** is a Python library designed to accurately and efficiently handle timestamps within discrete time intervals (klines or candlesticks), commonly used in financial time series and market analysis.

It provides a clean, immutable, timezone-aware API that makes reasoning about candle boundaries extremely intuitive.

Repository:
https://github.com/nand0san/KlineTimestamp

---

## Features

- **Canonical open/close computation**
  Automatically snap any timestamp (ms) to the correct candle open/close.

- **Timezone-aware conversions**
  Built-in support for `pytz` with proper DST handling.

- **Clean datetime integration**
  Convert directly to `datetime.datetime` or `pandas.Timestamp`.

- **Immutable API**
  Every transformation returns a new instance (`with_timezone`, `with_interval`, addition/subtraction with `timedelta`).

- **Navigation between candles**
  Use `next()` and `prev()` to move through consecutive klines.

- **Strict comparison semantics**
  Candle identity depends only on `(open, tick_ms)`; timezone affects display only.

- **Guaranteed total ordering**
  Timestamps are comparable via lexicographic `(open, tick_ms)` ordering.

- **All Binance intervals**
  All fixed-duration Binance intervals (1m to 1w) plus the variable-duration monthly interval (`1M`).

- **Monthly candles (1M)**
  Calendar-aware: handles 28/29/30/31-day months correctly, including leap years.

---

## Installation

```bash
pip install kline_timestamp
```

Requires **Python 3.9+**.

---

## Dependencies

* `pandas>=2.3.0,<3.0`
* `pytz>=2024.1`

These are declared automatically in the installed package.

---

## Quick start

```python
from kline_timestamp import KlineTimestamp
```

### Constructor

```python
KlineTimestamp(timestamp_ms: int, interval: str, tzinfo: str | pytz.BaseTzInfo = "UTC")
```

| Parameter | Type | Description |
|---|---|---|
| `timestamp_ms` | `int` | Epoch milliseconds (UTC). Must be `int`. |
| `interval` | `str` | Candle interval (see table below). Case-insensitive except `1M`. |
| `tzinfo` | `str` or `pytz.BaseTzInfo` | Timezone for display. Default `"UTC"`. |

### Instance attributes

| Attribute | Type | Description |
|---|---|---|
| `open` | `int` | Candle open timestamp (epoch ms, UTC). |
| `close` | `int` | Candle close timestamp (epoch ms, UTC). |
| `tick_ms` | `int` | Duration of the candle in milliseconds. For `1M`, varies per month. |
| `interval` | `str` | Normalized interval string. |
| `tzinfo` | `pytz.BaseTzInfo` | Timezone instance. |

---

## Supported intervals

Fixed-duration intervals (constant `tick_ms`):

| Interval | Duration |
|---|---|
| `1m` | 1 minute |
| `3m` | 3 minutes |
| `5m` | 5 minutes |
| `15m` | 15 minutes |
| `30m` | 30 minutes |
| `1h` | 1 hour |
| `2h` | 2 hours |
| `4h` | 4 hours |
| `6h` | 6 hours |
| `8h` | 8 hours |
| `12h` | 12 hours |
| `1d` | 1 day |
| `3d` | 3 days |
| `1w` | 1 week |

Variable-duration interval:

| Interval | Duration |
|---|---|
| `1M` | 1 calendar month (28-31 days) |

**Important:** `1M` (uppercase) is monthly. `1m` (lowercase) is 1 minute. The interval is case-sensitive for `1M`; all others are case-insensitive.

---

## Methods

### Conversions

```python
kt.to_datetime()           # -> datetime.datetime (tz-aware)
kt.to_pandas_timestamp()   # -> pd.Timestamp (tz-aware)
```

### Immutable transformations

```python
kt.with_timezone("UTC")    # -> new KlineTimestamp, same candle, different tz
kt.with_interval("15m")    # -> new KlineTimestamp, re-snapped to new interval
```

### Navigation

```python
kt.next()                  # -> next candle (same interval)
kt.prev()                  # -> previous candle (same interval)
```

For `1M`, `next()`/`prev()` correctly navigate calendar months (handles Dec->Jan, Jan->Dec, variable month lengths).

### Arithmetic

```python
kt + timedelta(hours=1)    # -> new KlineTimestamp shifted forward
kt - timedelta(hours=1)    # -> new KlineTimestamp shifted backward
kt - kt_other              # -> timedelta (difference between opens)
```

### Comparisons

```python
kt == kt_other             # equality by (open, tick_ms)
kt < kt_other              # ordering by (open, tick_ms)
```

Timezone is ignored for equality, hashing, and ordering.

---

## Examples

### Fixed interval

```python
from kline_timestamp import KlineTimestamp
from datetime import timedelta

kt = KlineTimestamp(1633036800000, "1h", "Europe/Madrid")

print("Open:", kt.open)
print("Close:", kt.close)
print("Datetime:", kt.to_datetime())
print("Pandas:", kt.to_pandas_timestamp())

kt_utc = kt.with_timezone("UTC")
print("UTC:", kt_utc.to_datetime())

kt_plus = kt + timedelta(hours=1)
print("After +1h:", kt_plus.to_datetime())

print("Next:", kt.next().to_datetime())
print("Prev:", kt.prev().to_datetime())

kt_other = KlineTimestamp(1633033200000, "1h", "UTC")
print("Comparison:", kt > kt_other)
print("Time delta:", kt - kt_other)
```

### Monthly interval (1M)

```python
from kline_timestamp import KlineTimestamp

# March 2024
kt = KlineTimestamp(1709251200000, "1M", "UTC")
print("Open:", kt.to_datetime())    # 2024-03-01 00:00:00+00:00
print("Close ms:", kt.close)        # last ms of March 31

# Navigate months
kt_apr = kt.next()                  # April 2024
kt_feb = kt.prev()                  # February 2024 (leap year, 29 days)
print("Feb days:", kt_feb.tick_ms // 86400000)  # 29

# Any timestamp within a month snaps to that month’s open
kt_mid = KlineTimestamp(1710000000000, "1M", "UTC")  # ~Mar 9
print(kt_mid.open == kt.open)       # True
```

---

## License

MIT License.
See the [LICENSE](LICENSE) file for details.

---

## Contributing

Pull requests are welcome.
Open an issue or send a PR at:

[https://github.com/nand0san/KlineTimestamp](https://github.com/nand0san/KlineTimestamp)

---

## Acknowledgments

* Inspired by practical needs in quantitative financial analysis.
* Uses the excellent `pytz` and `pandas` libraries for timezone and datetime handling.
