dccd 3.3.0__tar.gz → 3.3.1__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.
- {dccd-3.3.0 → dccd-3.3.1}/CHANGELOG.md +9 -0
- {dccd-3.3.0 → dccd-3.3.1}/PKG-INFO +1 -1
- {dccd-3.3.0 → dccd-3.3.1}/dccd/sources/kraken.py +10 -4
- {dccd-3.3.0 → dccd-3.3.1}/dccd/tests/v3/test_sources.py +4 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd.egg-info/PKG-INFO +1 -1
- {dccd-3.3.0 → dccd-3.3.1}/pyproject.toml +1 -1
- {dccd-3.3.0 → dccd-3.3.1}/CLAUDE.md +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/CONTRIBUTING.md +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/LICENSE.txt +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/MANIFEST.in +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/README.md +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/__init__.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/application/__init__.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/application/config.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/application/events.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/application/jobs.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/application/monitor.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/application/operations.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/application/registry.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/application/scheduler.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/application/service_factory.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/domain/__init__.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/domain/capability.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/domain/dataset.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/domain/errors.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/domain/records.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/domain/symbol.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/domain/timeutils.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/domain/transforms.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/domain/types.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/interfaces/__init__.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/interfaces/api/__init__.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/interfaces/api/app.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/interfaces/cli/__init__.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/interfaces/cli/main.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/interfaces/ui/__init__.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/interfaces/ui/static/favicon.svg +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/interfaces/ui/static/logo.svg +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/interfaces/ui/templates/base.html +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/interfaces/ui/templates/config.html +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/interfaces/ui/templates/dashboard.html +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/interfaces/ui/templates/data.html +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/interfaces/ui/templates/historical.html +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/interfaces/ui/templates/live.html +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/interfaces/ui/templates/login.html +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/interfaces/ui/templates/logs.html +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/interfaces/ui/templates/storage.html +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/sources/__init__.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/sources/base.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/sources/binance.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/sources/bitfinex.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/sources/bitmex.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/sources/bybit.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/sources/coinbase.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/sources/okx.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/sources/registry.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/storage/__init__.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/storage/coverage_sqlite.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/storage/parquet.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/storage/purge.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/storage/remote.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/storage/runs_sqlite.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/tests/__init__.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/tests/v3/__init__.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/tests/v3/test_api.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/tests/v3/test_application.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/tests/v3/test_backfill_lookback.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/tests/v3/test_client.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/tests/v3/test_coverage.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/tests/v3/test_domain.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/tests/v3/test_domain_extended.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/tests/v3/test_network.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/tests/v3/test_purge.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/tests/v3/test_remote_sync.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/tests/v3/test_restart.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/tests/v3/test_restore.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/tests/v3/test_storage.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/tests/v3/test_storage_extended.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/tests/v3/test_transport.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/transport/__init__.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/transport/http.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/transport/paginate.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/transport/ratelimit.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd/transport/ws.py +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd.egg-info/SOURCES.txt +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd.egg-info/dependency_links.txt +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd.egg-info/entry_points.txt +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd.egg-info/requires.txt +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/dccd.egg-info/top_level.txt +0 -0
- {dccd-3.3.0 → dccd-3.3.1}/setup.cfg +0 -0
|
@@ -16,6 +16,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
16
16
|
|
|
17
17
|
### Removed
|
|
18
18
|
|
|
19
|
+
## [3.3.1] - 2026-06-10
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- Kraken crypto/crypto OHLC pairs (e.g. `ETH/BTC`): `_kraken_pair` only mapped the
|
|
24
|
+
*base* `BTC→XBT`, producing `XETHXBTC` which Kraken rejects with "Unknown asset
|
|
25
|
+
pair"; it now maps the *quote* too (`XETHXXBT`). Verified against the live Kraken
|
|
26
|
+
API (721 bars). (#113)
|
|
27
|
+
|
|
19
28
|
## [3.3.0] - 2026-06-10
|
|
20
29
|
|
|
21
30
|
### Added
|
|
@@ -45,13 +45,19 @@ def _kraken_pair(symbol: Symbol) -> str:
|
|
|
45
45
|
>>> from dccd.domain.symbol import Symbol
|
|
46
46
|
>>> _kraken_pair(Symbol(base='BTC', quote='USD'))
|
|
47
47
|
'XXBTZUSD'
|
|
48
|
+
>>> _kraken_pair(Symbol(base='ETH', quote='BTC'))
|
|
49
|
+
'XETHXXBT'
|
|
48
50
|
"""
|
|
51
|
+
# Kraken names BTC as XBT — for the quote too, not just the base, so a
|
|
52
|
+
# crypto/crypto pair like ETH/BTC must become XETHXXBT (not XETHXBTC,
|
|
53
|
+
# which Kraken rejects with "Unknown asset pair").
|
|
49
54
|
base = "XBT" if symbol.base == "BTC" else symbol.base
|
|
55
|
+
quote = "XBT" if symbol.quote == "BTC" else symbol.quote
|
|
50
56
|
if base in ("BCH", "DASH"):
|
|
51
|
-
return f"{base}{
|
|
52
|
-
if
|
|
53
|
-
return f"X{base}Z{
|
|
54
|
-
return f"X{base}X{
|
|
57
|
+
return f"{base}{quote}"
|
|
58
|
+
if quote in ("EUR", "USD", "CAD", "JPY", "GBP"):
|
|
59
|
+
return f"X{base}Z{quote}"
|
|
60
|
+
return f"X{base}X{quote}"
|
|
55
61
|
|
|
56
62
|
|
|
57
63
|
def _ws_pair(symbol: Symbol) -> str:
|
|
@@ -115,6 +115,10 @@ class TestKrakenCapabilities:
|
|
|
115
115
|
def test_render_symbol(self):
|
|
116
116
|
assert self.src.render_symbol(BTC_USD) == "XXBTZUSD"
|
|
117
117
|
|
|
118
|
+
def test_render_symbol_crypto_quote_btc(self):
|
|
119
|
+
# ETH/BTC: BTC→XBT for the *quote* too, else Kraken rejects "XETHXBTC".
|
|
120
|
+
assert self.src.render_symbol(Symbol(base="ETH", quote="BTC")) == "XETHXXBT"
|
|
121
|
+
|
|
118
122
|
def test_ohlc_cap_history_recent(self):
|
|
119
123
|
cap = self.src.capability_for(DataType.OHLC, "rest", "historical")
|
|
120
124
|
assert cap is not None
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|