Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ These profiles depend on artifacts produced by `CryptoLivePoolPipelines` before

| Profile | Name | Notes |
| --- | --- | --- |
| `crypto_live_pool_rotation` | Crypto Live Pool Rotation | runtime-enabled trend-following rotation that consumes the ordered live pool published by CryptoLivePoolPipelines. Runtime code may gate and size trades inside that pool, but monthly selection and order remain upstream. |
| `crypto_live_pool_rotation` | Crypto Live Pool Rotation | runtime-enabled trend-following rotation that consumes the ordered live pool published by CryptoLivePoolPipelines. The legacy `crypto_leader_rotation` profile remains an alias for compatibility. Runtime code may gate and size trades inside that pool, but monthly selection and order remain upstream. |

### Research-only candidates

Expand Down
2 changes: 1 addition & 1 deletion README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ CryptoStrategies 是 QuantStrategyLab 的加密货币策略包。为 Binance 执

| Profile | 名称 | 说明 |
| --- | --- | --- |
| `crypto_live_pool_rotation` | Crypto Live Pool Rotation | 消费 CryptoLivePoolPipelines 发布的有序 live pool 的趋势轮动策略。运行时代码可以在该池内做交易门控和仓位 sizing,但月度选池和排序属于上游。 |
| `crypto_live_pool_rotation` | 加密领涨轮动 | 消费 CryptoLivePoolPipelines 发布的有序 live pool 的趋势轮动策略。兼容旧 profile `crypto_leader_rotation`;运行时代码可以在该池内做交易门控和仓位 sizing,但月度选池和排序属于上游。 |

### 研究侧候选

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "crypto-strategies"
version = "0.4.7"
version = "0.4.8"
description = "Shared crypto strategy catalog and implementations"
readme = "README.md"
requires-python = ">=3.11"
Expand Down
4 changes: 4 additions & 0 deletions src/crypto_strategies/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from .catalog import (
STRATEGY_CATALOG,
STRATEGY_DEFINITIONS,
CRYPTO_LEADER_ROTATION_PROFILE,
CRYPTO_LIVE_POOL_ROTATION_PROFILE,
get_strategy_catalog,
get_strategy_definition,
get_strategy_definitions,
Expand All @@ -16,6 +18,8 @@
__all__ = [
"STRATEGY_CATALOG",
"STRATEGY_DEFINITIONS",
"CRYPTO_LEADER_ROTATION_PROFILE",
"CRYPTO_LIVE_POOL_ROTATION_PROFILE",
"PLATFORM_RUNTIME_ADAPTERS",
"get_strategy_catalog",
"get_strategy_definition",
Expand Down
4 changes: 3 additions & 1 deletion src/crypto_strategies/catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
)

CRYPTO_LIVE_POOL_ROTATION_PROFILE = "crypto_live_pool_rotation"
CRYPTO_LEADER_ROTATION_PROFILE = "crypto_leader_rotation"
CRYPTO_LIVE_POOL_ROTATION_ALIASES = (CRYPTO_LEADER_ROTATION_PROFILE,)

CRYPTO_CANONICAL_REQUIRED_INPUTS = frozenset(
{
Expand Down Expand Up @@ -74,7 +76,7 @@
canonical_profile=CRYPTO_LIVE_POOL_ROTATION_PROFILE,
display_name="Crypto Live Pool Rotation",
description="Trend-following crypto rotation with staged entries, degradation controls, and cash parking.",
aliases=(),
aliases=CRYPTO_LIVE_POOL_ROTATION_ALIASES,
cadence="daily",
asset_scope="liquid_crypto_assets",
benchmark="BTC",
Expand Down
1 change: 1 addition & 0 deletions src/crypto_strategies/manifests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
domain="crypto",
display_name="Crypto Live Pool Rotation",
description="Trend-following crypto rotation with staged entries, degradation controls, and cash parking.",
aliases=("crypto_leader_rotation",),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Resolve manifest aliases before lookup

Declaring crypto_leader_rotation as a manifest alias advertises it as usable metadata, but get_strategy_manifest() still indexes MANIFESTS only by canonical profile, so callers that keep the legacy profile in config and ask for its manifest get a KeyError even though catalog and runtime-adapter lookups now resolve the alias. Please either add alias entries to MANIFESTS or route this lookup through the same catalog alias resolver so manifest compatibility matches the rest of the package.

Useful? React with 👍 / 👎.

required_inputs=frozenset(
{
"market_prices",
Expand Down
10 changes: 10 additions & 0 deletions tests/test_catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
from crypto_strategies import get_strategy_definitions
from crypto_strategies.catalog import (
CRYPTO_CANONICAL_REQUIRED_INPUTS,
CRYPTO_LEADER_ROTATION_PROFILE,
CRYPTO_LIVE_POOL_ROTATION_PROFILE,
get_strategy_definition,
get_strategy_metadata,
)
from crypto_strategies.runtime_adapters import BINANCE_PLATFORM, get_platform_runtime_adapter

Expand Down Expand Up @@ -34,6 +36,14 @@ def test_known_profile_resolves(self):
"crypto_strategies.strategies.crypto_live_pool_rotation.rotation",
)

def test_legacy_leader_rotation_profile_resolves_to_live_pool_rotation(self):
definition = get_strategy_definition(CRYPTO_LEADER_ROTATION_PROFILE)
metadata = get_strategy_metadata(CRYPTO_LEADER_ROTATION_PROFILE)

self.assertEqual(definition.profile, CRYPTO_LIVE_POOL_ROTATION_PROFILE)
self.assertEqual(metadata.canonical_profile, CRYPTO_LIVE_POOL_ROTATION_PROFILE)
self.assertIn(CRYPTO_LEADER_ROTATION_PROFILE, metadata.aliases)

def test_runtime_adapter_covers_canonical_inputs(self):
definition = get_strategy_definition(CRYPTO_LIVE_POOL_ROTATION_PROFILE)
adapter = get_platform_runtime_adapter(CRYPTO_LIVE_POOL_ROTATION_PROFILE, platform_id=BINANCE_PLATFORM)
Expand Down
2 changes: 2 additions & 0 deletions tests/test_contract_governance.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ def test_manifest_matches_catalog_definition_and_metadata(self) -> None:
self.assertEqual(manifest.profile, definition.profile)
self.assertEqual(manifest.domain, definition.domain)
self.assertEqual(manifest.display_name, metadata.display_name)
self.assertEqual(manifest.aliases, metadata.aliases)
self.assertEqual(manifest.required_inputs, definition.required_inputs)
self.assertEqual(dict(manifest.default_config), dict(definition.default_config))

Expand All @@ -106,6 +107,7 @@ def test_entrypoint_manifest_matches_catalog_when_importable(self) -> None:
self.assertEqual(entrypoint.manifest.profile, definition.profile)
self.assertEqual(entrypoint.manifest.domain, definition.domain)
self.assertEqual(entrypoint.manifest.display_name, metadata.display_name)
self.assertEqual(entrypoint.manifest.aliases, metadata.aliases)
self.assertEqual(entrypoint.manifest.required_inputs, definition.required_inputs)

def test_strategy_index_rows_expose_expected_contract_fields(self) -> None:
Expand Down