brk-client 0.1.1__tar.gz → 0.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {brk_client-0.1.1 → brk_client-0.1.2}/PKG-INFO +1 -1
- {brk_client-0.1.1 → brk_client-0.1.2}/brk_client/__init__.py +233 -123
- {brk_client-0.1.1 → brk_client-0.1.2}/pyproject.toml +3 -1
- brk_client-0.1.2/tests/test_metric_data.py +340 -0
- {brk_client-0.1.1 → brk_client-0.1.2}/uv.lock +508 -7
- {brk_client-0.1.1 → brk_client-0.1.2}/.gitignore +0 -0
- {brk_client-0.1.1 → brk_client-0.1.2}/.python-version +0 -0
- {brk_client-0.1.1 → brk_client-0.1.2}/README.md +0 -0
- {brk_client-0.1.1 → brk_client-0.1.2}/pydoc-markdown.yml +0 -0
- {brk_client-0.1.1 → brk_client-0.1.2}/tests/test_basic.py +0 -0
- {brk_client-0.1.1 → brk_client-0.1.2}/tests/test_tree.py +0 -0
|
@@ -3,11 +3,16 @@
|
|
|
3
3
|
|
|
4
4
|
from __future__ import annotations
|
|
5
5
|
from dataclasses import dataclass
|
|
6
|
-
from typing import TypeVar, Generic, Any, Optional, List, Literal, TypedDict, Union, Protocol, overload
|
|
6
|
+
from typing import TypeVar, Generic, Any, Optional, List, Literal, TypedDict, Union, Protocol, overload, Iterator, Tuple, TYPE_CHECKING
|
|
7
7
|
from http.client import HTTPSConnection, HTTPConnection
|
|
8
8
|
from urllib.parse import urlparse
|
|
9
|
+
from datetime import date, timedelta
|
|
9
10
|
import json
|
|
10
11
|
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
import pandas as pd # type: ignore[import-not-found]
|
|
14
|
+
import polars as pl # type: ignore[import-not-found]
|
|
15
|
+
|
|
11
16
|
T = TypeVar('T')
|
|
12
17
|
|
|
13
18
|
# Type definitions
|
|
@@ -1043,16 +1048,114 @@ def _p(prefix: str, acc: str) -> str:
|
|
|
1043
1048
|
return f"{prefix}_{acc}" if acc else prefix
|
|
1044
1049
|
|
|
1045
1050
|
|
|
1051
|
+
# Date conversion constants
|
|
1052
|
+
_GENESIS = date(2009, 1, 3) # dateindex 0, weekindex 0
|
|
1053
|
+
_DAY_ONE = date(2009, 1, 9) # dateindex 1 (6 day gap after genesis)
|
|
1054
|
+
_DATE_INDEXES = frozenset(['dateindex', 'weekindex', 'monthindex', 'yearindex', 'quarterindex', 'semesterindex', 'decadeindex'])
|
|
1055
|
+
|
|
1056
|
+
def is_date_index(index: str) -> bool:
|
|
1057
|
+
"""Check if an index type is date-based."""
|
|
1058
|
+
return index in _DATE_INDEXES
|
|
1059
|
+
|
|
1060
|
+
def index_to_date(index: str, i: int) -> date:
|
|
1061
|
+
"""Convert an index value to a date for date-based indexes."""
|
|
1062
|
+
if index == 'dateindex':
|
|
1063
|
+
return _GENESIS if i == 0 else _DAY_ONE + timedelta(days=i - 1)
|
|
1064
|
+
elif index == 'weekindex':
|
|
1065
|
+
return _GENESIS + timedelta(weeks=i)
|
|
1066
|
+
elif index == 'monthindex':
|
|
1067
|
+
return date(2009 + i // 12, i % 12 + 1, 1)
|
|
1068
|
+
elif index == 'yearindex':
|
|
1069
|
+
return date(2009 + i, 1, 1)
|
|
1070
|
+
elif index == 'quarterindex':
|
|
1071
|
+
m = i * 3
|
|
1072
|
+
return date(2009 + m // 12, m % 12 + 1, 1)
|
|
1073
|
+
elif index == 'semesterindex':
|
|
1074
|
+
m = i * 6
|
|
1075
|
+
return date(2009 + m // 12, m % 12 + 1, 1)
|
|
1076
|
+
elif index == 'decadeindex':
|
|
1077
|
+
return date(2009 + i * 10, 1, 1)
|
|
1078
|
+
else:
|
|
1079
|
+
raise ValueError(f"{index} is not a date-based index")
|
|
1080
|
+
|
|
1081
|
+
|
|
1046
1082
|
@dataclass
|
|
1047
1083
|
class MetricData(Generic[T]):
|
|
1048
1084
|
"""Metric data with range information."""
|
|
1049
1085
|
version: int
|
|
1086
|
+
index: Index
|
|
1050
1087
|
total: int
|
|
1051
1088
|
start: int
|
|
1052
1089
|
end: int
|
|
1053
1090
|
stamp: str
|
|
1054
1091
|
data: List[T]
|
|
1055
1092
|
|
|
1093
|
+
def dates(self) -> List[date]:
|
|
1094
|
+
"""Convert index range to dates. Only works for date-based indexes."""
|
|
1095
|
+
return [index_to_date(self.index, i) for i in range(self.start, self.end)]
|
|
1096
|
+
|
|
1097
|
+
def indexes(self) -> List[int]:
|
|
1098
|
+
"""Get index range as list."""
|
|
1099
|
+
return list(range(self.start, self.end))
|
|
1100
|
+
|
|
1101
|
+
def to_date_dict(self) -> dict[date, T]:
|
|
1102
|
+
"""Return data as {date: value} dict. Only works for date-based indexes."""
|
|
1103
|
+
return dict(zip(self.dates(), self.data))
|
|
1104
|
+
|
|
1105
|
+
def to_index_dict(self) -> dict[int, T]:
|
|
1106
|
+
"""Return data as {index: value} dict."""
|
|
1107
|
+
return dict(zip(range(self.start, self.end), self.data))
|
|
1108
|
+
|
|
1109
|
+
def date_items(self) -> List[Tuple[date, T]]:
|
|
1110
|
+
"""Return data as [(date, value), ...] pairs. Only works for date-based indexes."""
|
|
1111
|
+
return list(zip(self.dates(), self.data))
|
|
1112
|
+
|
|
1113
|
+
def index_items(self) -> List[Tuple[int, T]]:
|
|
1114
|
+
"""Return data as [(index, value), ...] pairs."""
|
|
1115
|
+
return list(zip(range(self.start, self.end), self.data))
|
|
1116
|
+
|
|
1117
|
+
def iter(self) -> Iterator[Tuple[int, T]]:
|
|
1118
|
+
"""Iterate over (index, value) pairs."""
|
|
1119
|
+
return iter(zip(range(self.start, self.end), self.data))
|
|
1120
|
+
|
|
1121
|
+
def iter_dates(self) -> Iterator[Tuple[date, T]]:
|
|
1122
|
+
"""Iterate over (date, value) pairs. Date-based indexes only."""
|
|
1123
|
+
return iter(zip(self.dates(), self.data))
|
|
1124
|
+
|
|
1125
|
+
def __iter__(self) -> Iterator[Tuple[int, T]]:
|
|
1126
|
+
"""Default iteration over (index, value) pairs."""
|
|
1127
|
+
return self.iter()
|
|
1128
|
+
|
|
1129
|
+
def to_polars(self, with_dates: bool = True) -> pl.DataFrame:
|
|
1130
|
+
"""Convert to Polars DataFrame. Requires polars to be installed.
|
|
1131
|
+
|
|
1132
|
+
Returns a DataFrame with columns:
|
|
1133
|
+
- 'date' (date) and 'value' (T) if with_dates=True and index is date-based
|
|
1134
|
+
- 'index' (int) and 'value' (T) otherwise
|
|
1135
|
+
"""
|
|
1136
|
+
try:
|
|
1137
|
+
import polars as pl # type: ignore[import-not-found]
|
|
1138
|
+
except ImportError:
|
|
1139
|
+
raise ImportError("polars is required: pip install polars")
|
|
1140
|
+
if with_dates and self.index in _DATE_INDEXES:
|
|
1141
|
+
return pl.DataFrame({"date": self.dates(), "value": self.data})
|
|
1142
|
+
return pl.DataFrame({"index": list(range(self.start, self.end)), "value": self.data})
|
|
1143
|
+
|
|
1144
|
+
def to_pandas(self, with_dates: bool = True) -> pd.DataFrame:
|
|
1145
|
+
"""Convert to Pandas DataFrame. Requires pandas to be installed.
|
|
1146
|
+
|
|
1147
|
+
Returns a DataFrame with columns:
|
|
1148
|
+
- 'date' (date) and 'value' (T) if with_dates=True and index is date-based
|
|
1149
|
+
- 'index' (int) and 'value' (T) otherwise
|
|
1150
|
+
"""
|
|
1151
|
+
try:
|
|
1152
|
+
import pandas as pd # type: ignore[import-not-found]
|
|
1153
|
+
except ImportError:
|
|
1154
|
+
raise ImportError("pandas is required: pip install pandas")
|
|
1155
|
+
if with_dates and self.index in _DATE_INDEXES:
|
|
1156
|
+
return pd.DataFrame({"date": self.dates(), "value": self.data})
|
|
1157
|
+
return pd.DataFrame({"index": list(range(self.start, self.end)), "value": self.data})
|
|
1158
|
+
|
|
1056
1159
|
|
|
1057
1160
|
# Type alias for non-generic usage
|
|
1058
1161
|
AnyMetricData = MetricData[Any]
|
|
@@ -1089,9 +1192,8 @@ class _EndpointConfig:
|
|
|
1089
1192
|
p = self.path()
|
|
1090
1193
|
return f"{p}?{query}" if query else p
|
|
1091
1194
|
|
|
1092
|
-
def
|
|
1093
|
-
|
|
1094
|
-
return MetricData(**data)
|
|
1195
|
+
def get_metric(self) -> MetricData:
|
|
1196
|
+
return MetricData(**self.client.get_json(self._build_path()))
|
|
1095
1197
|
|
|
1096
1198
|
def get_csv(self) -> str:
|
|
1097
1199
|
return self.client.get_text(self._build_path(format='csv'))
|
|
@@ -1105,7 +1207,7 @@ class RangeBuilder(Generic[T]):
|
|
|
1105
1207
|
|
|
1106
1208
|
def fetch(self) -> MetricData[T]:
|
|
1107
1209
|
"""Fetch the range as parsed JSON."""
|
|
1108
|
-
return self._config.
|
|
1210
|
+
return self._config.get_metric()
|
|
1109
1211
|
|
|
1110
1212
|
def fetch_csv(self) -> str:
|
|
1111
1213
|
"""Fetch the range as CSV string."""
|
|
@@ -1120,7 +1222,7 @@ class SingleItemBuilder(Generic[T]):
|
|
|
1120
1222
|
|
|
1121
1223
|
def fetch(self) -> MetricData[T]:
|
|
1122
1224
|
"""Fetch the single item."""
|
|
1123
|
-
return self._config.
|
|
1225
|
+
return self._config.get_metric()
|
|
1124
1226
|
|
|
1125
1227
|
def fetch_csv(self) -> str:
|
|
1126
1228
|
"""Fetch as CSV."""
|
|
@@ -1143,7 +1245,7 @@ class SkippedBuilder(Generic[T]):
|
|
|
1143
1245
|
|
|
1144
1246
|
def fetch(self) -> MetricData[T]:
|
|
1145
1247
|
"""Fetch from skipped position to end."""
|
|
1146
|
-
return self._config.
|
|
1248
|
+
return self._config.get_metric()
|
|
1147
1249
|
|
|
1148
1250
|
def fetch_csv(self) -> str:
|
|
1149
1251
|
"""Fetch as CSV."""
|
|
@@ -1227,7 +1329,7 @@ class MetricEndpointBuilder(Generic[T]):
|
|
|
1227
1329
|
|
|
1228
1330
|
def fetch(self) -> MetricData[T]:
|
|
1229
1331
|
"""Fetch all data as parsed JSON."""
|
|
1230
|
-
return self._config.
|
|
1332
|
+
return self._config.get_metric()
|
|
1231
1333
|
|
|
1232
1334
|
def fetch_csv(self) -> str:
|
|
1233
1335
|
"""Fetch all data as CSV string."""
|
|
@@ -2047,18 +2149,18 @@ class ClassDaysInLossPattern(Generic[T]):
|
|
|
2047
2149
|
|
|
2048
2150
|
def __init__(self, client: BrkClientBase, acc: str):
|
|
2049
2151
|
"""Create pattern node with accumulated metric name."""
|
|
2050
|
-
self._2015: MetricPattern4[T] = MetricPattern4(client, _m(acc, '
|
|
2051
|
-
self._2016: MetricPattern4[T] = MetricPattern4(client, _m(acc, '
|
|
2052
|
-
self._2017: MetricPattern4[T] = MetricPattern4(client, _m(acc, '
|
|
2053
|
-
self._2018: MetricPattern4[T] = MetricPattern4(client, _m(acc, '
|
|
2054
|
-
self._2019: MetricPattern4[T] = MetricPattern4(client, _m(acc, '
|
|
2055
|
-
self._2020: MetricPattern4[T] = MetricPattern4(client, _m(acc, '
|
|
2056
|
-
self._2021: MetricPattern4[T] = MetricPattern4(client, _m(acc, '
|
|
2057
|
-
self._2022: MetricPattern4[T] = MetricPattern4(client, _m(acc, '
|
|
2058
|
-
self._2023: MetricPattern4[T] = MetricPattern4(client, _m(acc, '
|
|
2059
|
-
self._2024: MetricPattern4[T] = MetricPattern4(client, _m(acc, '
|
|
2060
|
-
self._2025: MetricPattern4[T] = MetricPattern4(client, _m(acc, '
|
|
2061
|
-
self._2026: MetricPattern4[T] = MetricPattern4(client, _m(acc, '
|
|
2152
|
+
self._2015: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2015_returns'))
|
|
2153
|
+
self._2016: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2016_returns'))
|
|
2154
|
+
self._2017: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2017_returns'))
|
|
2155
|
+
self._2018: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2018_returns'))
|
|
2156
|
+
self._2019: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2019_returns'))
|
|
2157
|
+
self._2020: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2020_returns'))
|
|
2158
|
+
self._2021: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2021_returns'))
|
|
2159
|
+
self._2022: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2022_returns'))
|
|
2160
|
+
self._2023: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2023_returns'))
|
|
2161
|
+
self._2024: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2024_returns'))
|
|
2162
|
+
self._2025: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2025_returns'))
|
|
2163
|
+
self._2026: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2026_returns'))
|
|
2062
2164
|
|
|
2063
2165
|
class BitcoinPattern:
|
|
2064
2166
|
"""Pattern struct for repeated tree structure."""
|
|
@@ -2094,22 +2196,6 @@ class DollarsPattern(Generic[T]):
|
|
|
2094
2196
|
self.pct90: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct90'))
|
|
2095
2197
|
self.sum: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'sum'))
|
|
2096
2198
|
|
|
2097
|
-
class RelativePattern2:
|
|
2098
|
-
"""Pattern struct for repeated tree structure."""
|
|
2099
|
-
|
|
2100
|
-
def __init__(self, client: BrkClientBase, acc: str):
|
|
2101
|
-
"""Create pattern node with accumulated metric name."""
|
|
2102
|
-
self.neg_unrealized_loss_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_market_cap'))
|
|
2103
|
-
self.neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_total_unrealized_pnl'))
|
|
2104
|
-
self.net_unrealized_pnl_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_market_cap'))
|
|
2105
|
-
self.net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_total_unrealized_pnl'))
|
|
2106
|
-
self.supply_in_loss_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'supply_in_loss_rel_to_own_supply'))
|
|
2107
|
-
self.supply_in_profit_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'supply_in_profit_rel_to_own_supply'))
|
|
2108
|
-
self.unrealized_loss_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_market_cap'))
|
|
2109
|
-
self.unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_total_unrealized_pnl'))
|
|
2110
|
-
self.unrealized_profit_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_market_cap'))
|
|
2111
|
-
self.unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_total_unrealized_pnl'))
|
|
2112
|
-
|
|
2113
2199
|
class RelativePattern:
|
|
2114
2200
|
"""Pattern struct for repeated tree structure."""
|
|
2115
2201
|
|
|
@@ -2126,6 +2212,22 @@ class RelativePattern:
|
|
|
2126
2212
|
self.unrealized_loss_rel_to_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_market_cap'))
|
|
2127
2213
|
self.unrealized_profit_rel_to_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_market_cap'))
|
|
2128
2214
|
|
|
2215
|
+
class RelativePattern2:
|
|
2216
|
+
"""Pattern struct for repeated tree structure."""
|
|
2217
|
+
|
|
2218
|
+
def __init__(self, client: BrkClientBase, acc: str):
|
|
2219
|
+
"""Create pattern node with accumulated metric name."""
|
|
2220
|
+
self.neg_unrealized_loss_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_market_cap'))
|
|
2221
|
+
self.neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_total_unrealized_pnl'))
|
|
2222
|
+
self.net_unrealized_pnl_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_market_cap'))
|
|
2223
|
+
self.net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_total_unrealized_pnl'))
|
|
2224
|
+
self.supply_in_loss_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'supply_in_loss_rel_to_own_supply'))
|
|
2225
|
+
self.supply_in_profit_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'supply_in_profit_rel_to_own_supply'))
|
|
2226
|
+
self.unrealized_loss_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_market_cap'))
|
|
2227
|
+
self.unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_total_unrealized_pnl'))
|
|
2228
|
+
self.unrealized_profit_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_market_cap'))
|
|
2229
|
+
self.unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_total_unrealized_pnl'))
|
|
2230
|
+
|
|
2129
2231
|
class CountPattern2(Generic[T]):
|
|
2130
2232
|
"""Pattern struct for repeated tree structure."""
|
|
2131
2233
|
|
|
@@ -2201,6 +2303,19 @@ class _0satsPattern:
|
|
|
2201
2303
|
self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply'))
|
|
2202
2304
|
self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc)
|
|
2203
2305
|
|
|
2306
|
+
class PeriodCagrPattern:
|
|
2307
|
+
"""Pattern struct for repeated tree structure."""
|
|
2308
|
+
|
|
2309
|
+
def __init__(self, client: BrkClientBase, acc: str):
|
|
2310
|
+
"""Create pattern node with accumulated metric name."""
|
|
2311
|
+
self._10y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('10y', acc))
|
|
2312
|
+
self._2y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('2y', acc))
|
|
2313
|
+
self._3y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('3y', acc))
|
|
2314
|
+
self._4y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('4y', acc))
|
|
2315
|
+
self._5y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('5y', acc))
|
|
2316
|
+
self._6y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('6y', acc))
|
|
2317
|
+
self._8y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('8y', acc))
|
|
2318
|
+
|
|
2204
2319
|
class _100btcPattern:
|
|
2205
2320
|
"""Pattern struct for repeated tree structure."""
|
|
2206
2321
|
|
|
@@ -2240,32 +2355,6 @@ class _10yPattern:
|
|
|
2240
2355
|
self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply'))
|
|
2241
2356
|
self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc)
|
|
2242
2357
|
|
|
2243
|
-
class UnrealizedPattern:
|
|
2244
|
-
"""Pattern struct for repeated tree structure."""
|
|
2245
|
-
|
|
2246
|
-
def __init__(self, client: BrkClientBase, acc: str):
|
|
2247
|
-
"""Create pattern node with accumulated metric name."""
|
|
2248
|
-
self.neg_unrealized_loss: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'neg_unrealized_loss'))
|
|
2249
|
-
self.net_unrealized_pnl: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'net_unrealized_pnl'))
|
|
2250
|
-
self.supply_in_loss: ActiveSupplyPattern = ActiveSupplyPattern(client, _m(acc, 'supply_in_loss'))
|
|
2251
|
-
self.supply_in_profit: ActiveSupplyPattern = ActiveSupplyPattern(client, _m(acc, 'supply_in_profit'))
|
|
2252
|
-
self.total_unrealized_pnl: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'total_unrealized_pnl'))
|
|
2253
|
-
self.unrealized_loss: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'unrealized_loss'))
|
|
2254
|
-
self.unrealized_profit: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'unrealized_profit'))
|
|
2255
|
-
|
|
2256
|
-
class PeriodCagrPattern:
|
|
2257
|
-
"""Pattern struct for repeated tree structure."""
|
|
2258
|
-
|
|
2259
|
-
def __init__(self, client: BrkClientBase, acc: str):
|
|
2260
|
-
"""Create pattern node with accumulated metric name."""
|
|
2261
|
-
self._10y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('10y', acc))
|
|
2262
|
-
self._2y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('2y', acc))
|
|
2263
|
-
self._3y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('3y', acc))
|
|
2264
|
-
self._4y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('4y', acc))
|
|
2265
|
-
self._5y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('5y', acc))
|
|
2266
|
-
self._6y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('6y', acc))
|
|
2267
|
-
self._8y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('8y', acc))
|
|
2268
|
-
|
|
2269
2358
|
class _10yTo12yPattern:
|
|
2270
2359
|
"""Pattern struct for repeated tree structure."""
|
|
2271
2360
|
|
|
@@ -2279,6 +2368,19 @@ class _10yTo12yPattern:
|
|
|
2279
2368
|
self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply'))
|
|
2280
2369
|
self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc)
|
|
2281
2370
|
|
|
2371
|
+
class UnrealizedPattern:
|
|
2372
|
+
"""Pattern struct for repeated tree structure."""
|
|
2373
|
+
|
|
2374
|
+
def __init__(self, client: BrkClientBase, acc: str):
|
|
2375
|
+
"""Create pattern node with accumulated metric name."""
|
|
2376
|
+
self.neg_unrealized_loss: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'neg_unrealized_loss'))
|
|
2377
|
+
self.net_unrealized_pnl: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'net_unrealized_pnl'))
|
|
2378
|
+
self.supply_in_loss: ActiveSupplyPattern = ActiveSupplyPattern(client, _m(acc, 'supply_in_loss'))
|
|
2379
|
+
self.supply_in_profit: ActiveSupplyPattern = ActiveSupplyPattern(client, _m(acc, 'supply_in_profit'))
|
|
2380
|
+
self.total_unrealized_pnl: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'total_unrealized_pnl'))
|
|
2381
|
+
self.unrealized_loss: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'unrealized_loss'))
|
|
2382
|
+
self.unrealized_profit: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'unrealized_profit'))
|
|
2383
|
+
|
|
2282
2384
|
class AllPattern:
|
|
2283
2385
|
"""Pattern struct for repeated tree structure."""
|
|
2284
2386
|
|
|
@@ -2312,23 +2414,14 @@ class SplitPattern2(Generic[T]):
|
|
|
2312
2414
|
self.low: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'low'))
|
|
2313
2415
|
self.open: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'open'))
|
|
2314
2416
|
|
|
2315
|
-
class
|
|
2316
|
-
"""Pattern struct for repeated tree structure."""
|
|
2317
|
-
|
|
2318
|
-
def __init__(self, client: BrkClientBase, acc: str):
|
|
2319
|
-
"""Create pattern node with accumulated metric name."""
|
|
2320
|
-
self.bitcoin: BitcoinPattern2[Bitcoin] = BitcoinPattern2(client, _m(acc, 'btc'))
|
|
2321
|
-
self.dollars: BlockCountPattern[Dollars] = BlockCountPattern(client, _m(acc, 'usd'))
|
|
2322
|
-
self.sats: BlockCountPattern[Sats] = BlockCountPattern(client, acc)
|
|
2323
|
-
|
|
2324
|
-
class _2015Pattern:
|
|
2417
|
+
class SegwitAdoptionPattern:
|
|
2325
2418
|
"""Pattern struct for repeated tree structure."""
|
|
2326
2419
|
|
|
2327
2420
|
def __init__(self, client: BrkClientBase, acc: str):
|
|
2328
2421
|
"""Create pattern node with accumulated metric name."""
|
|
2329
|
-
self.
|
|
2330
|
-
self.
|
|
2331
|
-
self.
|
|
2422
|
+
self.base: MetricPattern11[StoredF32] = MetricPattern11(client, acc)
|
|
2423
|
+
self.cumulative: MetricPattern2[StoredF32] = MetricPattern2(client, _m(acc, 'cumulative'))
|
|
2424
|
+
self.sum: MetricPattern2[StoredF32] = MetricPattern2(client, _m(acc, 'sum'))
|
|
2332
2425
|
|
|
2333
2426
|
class ActiveSupplyPattern:
|
|
2334
2427
|
"""Pattern struct for repeated tree structure."""
|
|
@@ -2339,32 +2432,32 @@ class ActiveSupplyPattern:
|
|
|
2339
2432
|
self.dollars: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'usd'))
|
|
2340
2433
|
self.sats: MetricPattern1[Sats] = MetricPattern1(client, acc)
|
|
2341
2434
|
|
|
2342
|
-
class
|
|
2435
|
+
class _2015Pattern:
|
|
2343
2436
|
"""Pattern struct for repeated tree structure."""
|
|
2344
2437
|
|
|
2345
2438
|
def __init__(self, client: BrkClientBase, acc: str):
|
|
2346
2439
|
"""Create pattern node with accumulated metric name."""
|
|
2347
|
-
self.bitcoin:
|
|
2348
|
-
self.dollars:
|
|
2349
|
-
self.sats:
|
|
2440
|
+
self.bitcoin: MetricPattern4[Bitcoin] = MetricPattern4(client, _m(acc, 'btc'))
|
|
2441
|
+
self.dollars: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'usd'))
|
|
2442
|
+
self.sats: MetricPattern4[Sats] = MetricPattern4(client, acc)
|
|
2350
2443
|
|
|
2351
|
-
class
|
|
2444
|
+
class CoinbasePattern:
|
|
2352
2445
|
"""Pattern struct for repeated tree structure."""
|
|
2353
2446
|
|
|
2354
2447
|
def __init__(self, client: BrkClientBase, acc: str):
|
|
2355
2448
|
"""Create pattern node with accumulated metric name."""
|
|
2356
|
-
self.
|
|
2357
|
-
self.
|
|
2358
|
-
self.
|
|
2449
|
+
self.bitcoin: BitcoinPattern = BitcoinPattern(client, _m(acc, 'btc'))
|
|
2450
|
+
self.dollars: DollarsPattern[Dollars] = DollarsPattern(client, _m(acc, 'usd'))
|
|
2451
|
+
self.sats: DollarsPattern[Sats] = DollarsPattern(client, acc)
|
|
2359
2452
|
|
|
2360
|
-
class
|
|
2453
|
+
class UnclaimedRewardsPattern:
|
|
2361
2454
|
"""Pattern struct for repeated tree structure."""
|
|
2362
2455
|
|
|
2363
2456
|
def __init__(self, client: BrkClientBase, acc: str):
|
|
2364
2457
|
"""Create pattern node with accumulated metric name."""
|
|
2365
|
-
self.
|
|
2366
|
-
self.
|
|
2367
|
-
self.
|
|
2458
|
+
self.bitcoin: BitcoinPattern2[Bitcoin] = BitcoinPattern2(client, _m(acc, 'btc'))
|
|
2459
|
+
self.dollars: BlockCountPattern[Dollars] = BlockCountPattern(client, _m(acc, 'usd'))
|
|
2460
|
+
self.sats: BlockCountPattern[Sats] = BlockCountPattern(client, acc)
|
|
2368
2461
|
|
|
2369
2462
|
class CoinbasePattern2:
|
|
2370
2463
|
"""Pattern struct for repeated tree structure."""
|
|
@@ -2375,13 +2468,14 @@ class CoinbasePattern2:
|
|
|
2375
2468
|
self.dollars: BlockCountPattern[Dollars] = BlockCountPattern(client, _m(acc, 'usd'))
|
|
2376
2469
|
self.sats: BlockCountPattern[Sats] = BlockCountPattern(client, acc)
|
|
2377
2470
|
|
|
2378
|
-
class
|
|
2471
|
+
class CostBasisPattern2:
|
|
2379
2472
|
"""Pattern struct for repeated tree structure."""
|
|
2380
2473
|
|
|
2381
2474
|
def __init__(self, client: BrkClientBase, acc: str):
|
|
2382
2475
|
"""Create pattern node with accumulated metric name."""
|
|
2383
|
-
self.
|
|
2384
|
-
self.
|
|
2476
|
+
self.max: ActivePricePattern = ActivePricePattern(client, _m(acc, 'max_cost_basis'))
|
|
2477
|
+
self.min: ActivePricePattern = ActivePricePattern(client, _m(acc, 'min_cost_basis'))
|
|
2478
|
+
self.percentiles: PercentilesPattern = PercentilesPattern(client, _m(acc, 'cost_basis'))
|
|
2385
2479
|
|
|
2386
2480
|
class ActivePricePattern:
|
|
2387
2481
|
"""Pattern struct for repeated tree structure."""
|
|
@@ -2391,13 +2485,13 @@ class ActivePricePattern:
|
|
|
2391
2485
|
self.dollars: MetricPattern1[Dollars] = MetricPattern1(client, acc)
|
|
2392
2486
|
self.sats: MetricPattern1[SatsFract] = MetricPattern1(client, _m(acc, 'sats'))
|
|
2393
2487
|
|
|
2394
|
-
class
|
|
2488
|
+
class _0sdUsdPattern:
|
|
2395
2489
|
"""Pattern struct for repeated tree structure."""
|
|
2396
2490
|
|
|
2397
2491
|
def __init__(self, client: BrkClientBase, acc: str):
|
|
2398
2492
|
"""Create pattern node with accumulated metric name."""
|
|
2399
|
-
self.
|
|
2400
|
-
self.
|
|
2493
|
+
self.dollars: MetricPattern4[Dollars] = MetricPattern4(client, acc)
|
|
2494
|
+
self.sats: MetricPattern4[SatsFract] = MetricPattern4(client, _m(acc, 'sats'))
|
|
2401
2495
|
|
|
2402
2496
|
class SupplyPattern2:
|
|
2403
2497
|
"""Pattern struct for repeated tree structure."""
|
|
@@ -2407,21 +2501,29 @@ class SupplyPattern2:
|
|
|
2407
2501
|
self.halved: ActiveSupplyPattern = ActiveSupplyPattern(client, _m(acc, 'halved'))
|
|
2408
2502
|
self.total: ActiveSupplyPattern = ActiveSupplyPattern(client, acc)
|
|
2409
2503
|
|
|
2410
|
-
class
|
|
2504
|
+
class CostBasisPattern:
|
|
2411
2505
|
"""Pattern struct for repeated tree structure."""
|
|
2412
2506
|
|
|
2413
2507
|
def __init__(self, client: BrkClientBase, acc: str):
|
|
2414
2508
|
"""Create pattern node with accumulated metric name."""
|
|
2415
|
-
self.
|
|
2416
|
-
self.
|
|
2509
|
+
self.max: ActivePricePattern = ActivePricePattern(client, _m(acc, 'max_cost_basis'))
|
|
2510
|
+
self.min: ActivePricePattern = ActivePricePattern(client, _m(acc, 'min_cost_basis'))
|
|
2417
2511
|
|
|
2418
|
-
class
|
|
2512
|
+
class _1dReturns1mSdPattern:
|
|
2419
2513
|
"""Pattern struct for repeated tree structure."""
|
|
2420
2514
|
|
|
2421
2515
|
def __init__(self, client: BrkClientBase, acc: str):
|
|
2422
2516
|
"""Create pattern node with accumulated metric name."""
|
|
2423
|
-
self.
|
|
2424
|
-
self.
|
|
2517
|
+
self.sd: MetricPattern4[StoredF32] = MetricPattern4(client, _m(acc, 'sd'))
|
|
2518
|
+
self.sma: MetricPattern4[StoredF32] = MetricPattern4(client, _m(acc, 'sma'))
|
|
2519
|
+
|
|
2520
|
+
class RelativePattern4:
|
|
2521
|
+
"""Pattern struct for repeated tree structure."""
|
|
2522
|
+
|
|
2523
|
+
def __init__(self, client: BrkClientBase, acc: str):
|
|
2524
|
+
"""Create pattern node with accumulated metric name."""
|
|
2525
|
+
self.supply_in_loss_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'loss_rel_to_own_supply'))
|
|
2526
|
+
self.supply_in_profit_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'profit_rel_to_own_supply'))
|
|
2425
2527
|
|
|
2426
2528
|
class BlockCountPattern(Generic[T]):
|
|
2427
2529
|
"""Pattern struct for repeated tree structure."""
|
|
@@ -2447,19 +2549,19 @@ class SatsPattern(Generic[T]):
|
|
|
2447
2549
|
self.ohlc: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'ohlc_sats'))
|
|
2448
2550
|
self.split: SplitPattern2[T] = SplitPattern2(client, _m(acc, 'sats'))
|
|
2449
2551
|
|
|
2450
|
-
class
|
|
2552
|
+
class RealizedPriceExtraPattern:
|
|
2451
2553
|
"""Pattern struct for repeated tree structure."""
|
|
2452
2554
|
|
|
2453
2555
|
def __init__(self, client: BrkClientBase, acc: str):
|
|
2454
2556
|
"""Create pattern node with accumulated metric name."""
|
|
2455
|
-
self.
|
|
2557
|
+
self.ratio: MetricPattern4[StoredF32] = MetricPattern4(client, acc)
|
|
2456
2558
|
|
|
2457
|
-
class
|
|
2559
|
+
class OutputsPattern:
|
|
2458
2560
|
"""Pattern struct for repeated tree structure."""
|
|
2459
2561
|
|
|
2460
2562
|
def __init__(self, client: BrkClientBase, acc: str):
|
|
2461
2563
|
"""Create pattern node with accumulated metric name."""
|
|
2462
|
-
self.
|
|
2564
|
+
self.utxo_count: MetricPattern1[StoredU64] = MetricPattern1(client, acc)
|
|
2463
2565
|
|
|
2464
2566
|
# Metrics tree classes
|
|
2465
2567
|
|
|
@@ -3384,6 +3486,23 @@ class MetricsTree_Market_Dca_ClassDaysInLoss:
|
|
|
3384
3486
|
self._2025: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2025_days_in_loss')
|
|
3385
3487
|
self._2026: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2026_days_in_loss')
|
|
3386
3488
|
|
|
3489
|
+
class MetricsTree_Market_Dca_ClassDaysInProfit:
|
|
3490
|
+
"""Metrics tree node."""
|
|
3491
|
+
|
|
3492
|
+
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
|
3493
|
+
self._2015: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2015_days_in_profit')
|
|
3494
|
+
self._2016: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2016_days_in_profit')
|
|
3495
|
+
self._2017: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2017_days_in_profit')
|
|
3496
|
+
self._2018: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2018_days_in_profit')
|
|
3497
|
+
self._2019: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2019_days_in_profit')
|
|
3498
|
+
self._2020: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2020_days_in_profit')
|
|
3499
|
+
self._2021: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2021_days_in_profit')
|
|
3500
|
+
self._2022: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2022_days_in_profit')
|
|
3501
|
+
self._2023: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2023_days_in_profit')
|
|
3502
|
+
self._2024: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2024_days_in_profit')
|
|
3503
|
+
self._2025: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2025_days_in_profit')
|
|
3504
|
+
self._2026: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2026_days_in_profit')
|
|
3505
|
+
|
|
3387
3506
|
class MetricsTree_Market_Dca_ClassMaxDrawdown:
|
|
3388
3507
|
"""Metrics tree node."""
|
|
3389
3508
|
|
|
@@ -3418,23 +3537,6 @@ class MetricsTree_Market_Dca_ClassMaxReturn:
|
|
|
3418
3537
|
self._2025: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2025_max_return')
|
|
3419
3538
|
self._2026: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2026_max_return')
|
|
3420
3539
|
|
|
3421
|
-
class MetricsTree_Market_Dca_ClassReturns:
|
|
3422
|
-
"""Metrics tree node."""
|
|
3423
|
-
|
|
3424
|
-
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
|
3425
|
-
self._2015: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2015_returns')
|
|
3426
|
-
self._2016: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2016_returns')
|
|
3427
|
-
self._2017: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2017_returns')
|
|
3428
|
-
self._2018: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2018_returns')
|
|
3429
|
-
self._2019: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2019_returns')
|
|
3430
|
-
self._2020: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2020_returns')
|
|
3431
|
-
self._2021: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2021_returns')
|
|
3432
|
-
self._2022: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2022_returns')
|
|
3433
|
-
self._2023: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2023_returns')
|
|
3434
|
-
self._2024: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2024_returns')
|
|
3435
|
-
self._2025: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2025_returns')
|
|
3436
|
-
self._2026: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2026_returns')
|
|
3437
|
-
|
|
3438
3540
|
class MetricsTree_Market_Dca_ClassStack:
|
|
3439
3541
|
"""Metrics tree node."""
|
|
3440
3542
|
|
|
@@ -3475,10 +3577,10 @@ class MetricsTree_Market_Dca:
|
|
|
3475
3577
|
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
|
3476
3578
|
self.class_average_price: MetricsTree_Market_Dca_ClassAveragePrice = MetricsTree_Market_Dca_ClassAveragePrice(client)
|
|
3477
3579
|
self.class_days_in_loss: MetricsTree_Market_Dca_ClassDaysInLoss = MetricsTree_Market_Dca_ClassDaysInLoss(client)
|
|
3478
|
-
self.class_days_in_profit:
|
|
3580
|
+
self.class_days_in_profit: MetricsTree_Market_Dca_ClassDaysInProfit = MetricsTree_Market_Dca_ClassDaysInProfit(client)
|
|
3479
3581
|
self.class_max_drawdown: MetricsTree_Market_Dca_ClassMaxDrawdown = MetricsTree_Market_Dca_ClassMaxDrawdown(client)
|
|
3480
3582
|
self.class_max_return: MetricsTree_Market_Dca_ClassMaxReturn = MetricsTree_Market_Dca_ClassMaxReturn(client)
|
|
3481
|
-
self.class_returns:
|
|
3583
|
+
self.class_returns: ClassDaysInLossPattern[StoredF32] = ClassDaysInLossPattern(client, 'dca_class')
|
|
3482
3584
|
self.class_stack: MetricsTree_Market_Dca_ClassStack = MetricsTree_Market_Dca_ClassStack(client)
|
|
3483
3585
|
self.period_average_price: MetricsTree_Market_Dca_PeriodAveragePrice = MetricsTree_Market_Dca_PeriodAveragePrice(client)
|
|
3484
3586
|
self.period_cagr: PeriodCagrPattern = PeriodCagrPattern(client, 'dca_cagr')
|
|
@@ -4052,7 +4154,7 @@ class MetricsTree:
|
|
|
4052
4154
|
class BrkClient(BrkClientBase):
|
|
4053
4155
|
"""Main BRK client with metrics tree and API methods."""
|
|
4054
4156
|
|
|
4055
|
-
VERSION = "v0.1.
|
|
4157
|
+
VERSION = "v0.1.1"
|
|
4056
4158
|
|
|
4057
4159
|
INDEXES = [
|
|
4058
4160
|
"dateindex",
|
|
@@ -4958,6 +5060,14 @@ class BrkClient(BrkClientBase):
|
|
|
4958
5060
|
"""
|
|
4959
5061
|
return MetricEndpointBuilder(self, metric, index)
|
|
4960
5062
|
|
|
5063
|
+
def index_to_date(self, index: Index, i: int) -> date:
|
|
5064
|
+
"""Convert an index value to a date for date-based indexes."""
|
|
5065
|
+
return index_to_date(index, i)
|
|
5066
|
+
|
|
5067
|
+
def is_date_index(self, index: Index) -> bool:
|
|
5068
|
+
"""Check if an index type is date-based."""
|
|
5069
|
+
return is_date_index(index)
|
|
5070
|
+
|
|
4961
5071
|
def get_api(self) -> Any:
|
|
4962
5072
|
"""Compact OpenAPI specification.
|
|
4963
5073
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "brk-client"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.2"
|
|
4
4
|
description = "Python client for the Bitcoin Research Kit"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.9"
|
|
@@ -25,6 +25,8 @@ Repository = "https://github.com/bitcoinresearchkit/brk"
|
|
|
25
25
|
|
|
26
26
|
[dependency-groups]
|
|
27
27
|
dev = [
|
|
28
|
+
"pandas>=2.3.3",
|
|
29
|
+
"polars>=1.36.1",
|
|
28
30
|
"pydoc-markdown>=4.8.2",
|
|
29
31
|
"pytest",
|
|
30
32
|
]
|