refactor(layout): rename multi_swarm → multi_swarm_core con doppia nidificazione uv workspace

- mv src/multi_swarm → src/multi_swarm_core/multi_swarm_core (member layout)
- sed-replace globale degli import: from/import multi_swarm.* → multi_swarm_core.*
- 115 occorrenze aggiornate in src/ scripts/ tests/
- multi_swarm_coevolutive (nome repo) preservato dal word boundary

Pre-condizione per il setup uv workspace della Fase 3.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Adriano Dal Pastro
2026-05-15 17:43:48 +00:00
parent 7d766173a4
commit b6539802e0
103 changed files with 746 additions and 110 deletions
+4 -4
View File
@@ -5,10 +5,10 @@ import numpy as np
import pandas as pd
import pytest
from multi_swarm.genome.hypothesis import ModelTier
from multi_swarm.llm.client import CompletionResult
from multi_swarm.orchestrator.run import RunConfig, run_phase1
from multi_swarm.persistence.repository import Repository
from multi_swarm_core.genome.hypothesis import ModelTier
from multi_swarm_core.llm.client import CompletionResult
from multi_swarm_core.orchestrator.run import RunConfig, run_phase1
from multi_swarm_core.persistence.repository import Repository
@pytest.fixture
@@ -9,8 +9,8 @@ from __future__ import annotations
import random
from dataclasses import dataclass
from multi_swarm.ga.loop import GAConfig, next_generation
from multi_swarm.genome.hypothesis import HypothesisAgentGenome, ModelTier
from multi_swarm_core.ga.loop import GAConfig, next_generation
from multi_swarm_core.genome.hypothesis import HypothesisAgentGenome, ModelTier
_PROMPT_TEMPLATES = (
"Strategia mean-reversion 1h. Entry long RSI(14) < 30 e close > SMA(50). Stop 2%.",
+18 -18
View File
@@ -4,14 +4,14 @@ import numpy as np
import pandas as pd
import pytest
from multi_swarm.agents.adversarial import (
from multi_swarm_core.agents.adversarial import (
AdversarialAgent,
AdversarialReport,
Severity,
)
from multi_swarm.backtest.engine import BacktestResult
from multi_swarm.backtest.orders import Side, Trade
from multi_swarm.protocol.parser import parse_strategy
from multi_swarm_core.backtest.engine import BacktestResult
from multi_swarm_core.backtest.orders import Side, Trade
from multi_swarm_core.protocol.parser import parse_strategy
@pytest.fixture
@@ -178,10 +178,10 @@ def test_undertrading_under_10_is_high(monkeypatch: pytest.MonkeyPatch,
return lambda df: fake_signals
monkeypatch.setattr(
"multi_swarm.agents.adversarial.BacktestEngine.run", fake_run
"multi_swarm_core.agents.adversarial.BacktestEngine.run", fake_run
)
monkeypatch.setattr(
"multi_swarm.agents.adversarial.compile_strategy", fake_compile
"multi_swarm_core.agents.adversarial.compile_strategy", fake_compile
)
src = _MINIMAL_STRATEGY_SRC
@@ -220,8 +220,8 @@ def test_undertrading_threshold_parametric(monkeypatch: pytest.MonkeyPatch,
def fake_compile(strategy): # type: ignore[no-untyped-def]
return lambda df: fake_signals
monkeypatch.setattr("multi_swarm.agents.adversarial.BacktestEngine.run", fake_run)
monkeypatch.setattr("multi_swarm.agents.adversarial.compile_strategy", fake_compile)
monkeypatch.setattr("multi_swarm_core.agents.adversarial.BacktestEngine.run", fake_run)
monkeypatch.setattr("multi_swarm_core.agents.adversarial.compile_strategy", fake_compile)
ast = parse_strategy(_MINIMAL_STRATEGY_SRC)
# Default threshold 10: 15 trade NON killato
@@ -269,10 +269,10 @@ def test_overtrading_with_tighter_threshold(monkeypatch: pytest.MonkeyPatch,
return lambda df: fake_signals
monkeypatch.setattr(
"multi_swarm.agents.adversarial.BacktestEngine.run", fake_run
"multi_swarm_core.agents.adversarial.BacktestEngine.run", fake_run
)
monkeypatch.setattr(
"multi_swarm.agents.adversarial.compile_strategy", fake_compile
"multi_swarm_core.agents.adversarial.compile_strategy", fake_compile
)
src = _MINIMAL_STRATEGY_SRC
@@ -315,10 +315,10 @@ def test_flat_too_long_flagged(monkeypatch: pytest.MonkeyPatch,
return lambda df: fake_signals
monkeypatch.setattr(
"multi_swarm.agents.adversarial.BacktestEngine.run", fake_run
"multi_swarm_core.agents.adversarial.BacktestEngine.run", fake_run
)
monkeypatch.setattr(
"multi_swarm.agents.adversarial.compile_strategy", fake_compile
"multi_swarm_core.agents.adversarial.compile_strategy", fake_compile
)
src = _MINIMAL_STRATEGY_SRC
@@ -367,10 +367,10 @@ def test_fees_eat_alpha_flagged(monkeypatch: pytest.MonkeyPatch,
return lambda df: fake_signals
monkeypatch.setattr(
"multi_swarm.agents.adversarial.BacktestEngine.run", fake_run
"multi_swarm_core.agents.adversarial.BacktestEngine.run", fake_run
)
monkeypatch.setattr(
"multi_swarm.agents.adversarial.compile_strategy", fake_compile
"multi_swarm_core.agents.adversarial.compile_strategy", fake_compile
)
src = _MINIMAL_STRATEGY_SRC
@@ -413,10 +413,10 @@ def test_time_in_market_too_high_flagged(monkeypatch: pytest.MonkeyPatch,
return lambda df: fake_signals
monkeypatch.setattr(
"multi_swarm.agents.adversarial.BacktestEngine.run", fake_run
"multi_swarm_core.agents.adversarial.BacktestEngine.run", fake_run
)
monkeypatch.setattr(
"multi_swarm.agents.adversarial.compile_strategy", fake_compile
"multi_swarm_core.agents.adversarial.compile_strategy", fake_compile
)
src = _MINIMAL_STRATEGY_SRC
@@ -461,10 +461,10 @@ def test_reasonable_balanced_strategy_not_flagged(monkeypatch: pytest.MonkeyPatc
return lambda df: fake_signals
monkeypatch.setattr(
"multi_swarm.agents.adversarial.BacktestEngine.run", fake_run
"multi_swarm_core.agents.adversarial.BacktestEngine.run", fake_run
)
monkeypatch.setattr(
"multi_swarm.agents.adversarial.compile_strategy", fake_compile
"multi_swarm_core.agents.adversarial.compile_strategy", fake_compile
)
src = _MINIMAL_STRATEGY_SRC
+2 -2
View File
@@ -2,8 +2,8 @@ import numpy as np
import pandas as pd
import pytest
from multi_swarm.backtest.engine import BacktestEngine
from multi_swarm.backtest.orders import Side
from multi_swarm_core.backtest.engine import BacktestEngine
from multi_swarm_core.backtest.orders import Side
@pytest.fixture
+1 -1
View File
@@ -2,7 +2,7 @@ from datetime import UTC, datetime
import pytest
from multi_swarm.backtest.orders import Order, Position, Side, Trade
from multi_swarm_core.backtest.orders import Order, Position, Side, Trade
def test_order_validates_side() -> None:
+1 -1
View File
@@ -1,7 +1,7 @@
import pytest
import responses
from multi_swarm.cerbero.client import CerberoClient
from multi_swarm_core.cerbero.client import CerberoClient
@responses.activate
+1 -1
View File
@@ -6,7 +6,7 @@ from pathlib import Path
import pandas as pd
import pytest
from multi_swarm.data.cerbero_ohlcv import CerberoOHLCVLoader, OHLCVRequest
from multi_swarm_core.data.cerbero_ohlcv import CerberoOHLCVLoader, OHLCVRequest
@pytest.fixture
+1 -1
View File
@@ -1,6 +1,6 @@
import pytest
from multi_swarm.cerbero.tools import CerberoTools
from multi_swarm_core.cerbero.tools import CerberoTools
def test_tools_dispatch_sma(mocker):
+2 -2
View File
@@ -1,4 +1,4 @@
"""Tests for multi_swarm.config.Settings.
"""Tests for multi_swarm_core.config.Settings.
Note on .env isolation:
The happy-path test relies on monkeypatch.setenv to provide values.
@@ -10,7 +10,7 @@ absence of required env vars. This keeps the test deterministic both in CI
import pytest
from multi_swarm.config import Settings
from multi_swarm_core.config import Settings
def test_settings_loads_from_env(monkeypatch: pytest.MonkeyPatch) -> None:
+2 -2
View File
@@ -1,5 +1,5 @@
from multi_swarm.genome.hypothesis import ModelTier
from multi_swarm.llm.cost_tracker import CostTracker, estimate_cost
from multi_swarm_core.genome.hypothesis import ModelTier
from multi_swarm_core.llm.cost_tracker import CostTracker, estimate_cost
def test_estimate_cost_tier_c():
+1 -1
View File
@@ -1,6 +1,6 @@
from __future__ import annotations
from multi_swarm.metrics.diversity import population_prompt_diversity
from multi_swarm_core.metrics.diversity import population_prompt_diversity
def test_empty_or_single_prompt_zero_diversity() -> None:
+2 -2
View File
@@ -4,8 +4,8 @@ import numpy as np
import pandas as pd
import pytest
from multi_swarm.agents.falsification import FalsificationAgent, FalsificationReport
from multi_swarm.protocol.parser import parse_strategy
from multi_swarm_core.agents.falsification import FalsificationAgent, FalsificationReport
from multi_swarm_core.protocol.parser import parse_strategy
@pytest.fixture
+3 -3
View File
@@ -1,8 +1,8 @@
from itertools import pairwise
from multi_swarm.agents.adversarial import AdversarialReport, Finding, Severity
from multi_swarm.agents.falsification import FalsificationReport
from multi_swarm.ga.fitness import compute_fitness
from multi_swarm_core.agents.adversarial import AdversarialReport, Finding, Severity
from multi_swarm_core.agents.falsification import FalsificationReport
from multi_swarm_core.ga.fitness import compute_fitness
def make_falsification(
+2 -2
View File
@@ -1,7 +1,7 @@
import random
from multi_swarm.ga.initial import build_initial_population
from multi_swarm.genome.hypothesis import ModelTier
from multi_swarm_core.ga.initial import build_initial_population
from multi_swarm_core.genome.hypothesis import ModelTier
def test_initial_population_size():
+2 -2
View File
@@ -1,7 +1,7 @@
import random
from multi_swarm.ga.loop import GAConfig, next_generation
from multi_swarm.genome.hypothesis import HypothesisAgentGenome, ModelTier
from multi_swarm_core.ga.loop import GAConfig, next_generation
from multi_swarm_core.genome.hypothesis import HypothesisAgentGenome, ModelTier
def make(idx: int) -> HypothesisAgentGenome:
+1 -1
View File
@@ -2,7 +2,7 @@ import math
import pytest
from multi_swarm.ga.summary import generation_summary
from multi_swarm_core.ga.summary import generation_summary
def test_summary_basic_stats():
+2 -2
View File
@@ -1,7 +1,7 @@
import random
from multi_swarm.genome.crossover import uniform_crossover
from multi_swarm.genome.hypothesis import HypothesisAgentGenome, ModelTier
from multi_swarm_core.genome.crossover import uniform_crossover
from multi_swarm_core.genome.hypothesis import HypothesisAgentGenome, ModelTier
def make(name: str) -> HypothesisAgentGenome:
+1 -1
View File
@@ -1,4 +1,4 @@
from multi_swarm.genome.hypothesis import HypothesisAgentGenome, ModelTier
from multi_swarm_core.genome.hypothesis import HypothesisAgentGenome, ModelTier
def test_genome_creation_defaults():
+2 -2
View File
@@ -2,8 +2,8 @@ import random
import pytest
from multi_swarm.genome.hypothesis import HypothesisAgentGenome, ModelTier
from multi_swarm.genome.mutation import (
from multi_swarm_core.genome.hypothesis import HypothesisAgentGenome, ModelTier
from multi_swarm_core.genome.mutation import (
COGNITIVE_STYLES,
FEATURE_POOL,
mutate_cognitive_style,
+3 -3
View File
@@ -1,8 +1,8 @@
import json
from multi_swarm.agents.hypothesis import HypothesisAgent, MarketSummary
from multi_swarm.genome.hypothesis import HypothesisAgentGenome, ModelTier
from multi_swarm.llm.client import CompletionResult, EmptyCompletionError
from multi_swarm_core.agents.hypothesis import HypothesisAgent, MarketSummary
from multi_swarm_core.genome.hypothesis import HypothesisAgentGenome, ModelTier
from multi_swarm_core.llm.client import CompletionResult, EmptyCompletionError
def make_summary() -> MarketSummary:
+12 -12
View File
@@ -1,7 +1,7 @@
import pytest
from multi_swarm.genome.hypothesis import HypothesisAgentGenome, ModelTier
from multi_swarm.llm.client import CompletionResult, LLMClient
from multi_swarm_core.genome.hypothesis import HypothesisAgentGenome, ModelTier
from multi_swarm_core.llm.client import CompletionResult, LLMClient
def make_genome(tier: ModelTier) -> HypothesisAgentGenome:
@@ -23,7 +23,7 @@ def test_completion_tier_c_uses_openrouter(mocker):
fake_response.usage = mocker.MagicMock(prompt_tokens=100, completion_tokens=200)
fake_openai.chat.completions.create.return_value = fake_response
mocker.patch("multi_swarm.llm.client.OpenAI", return_value=fake_openai)
mocker.patch("multi_swarm_core.llm.client.OpenAI", return_value=fake_openai)
client = LLMClient(openrouter_api_key="or-x")
g = make_genome(ModelTier.C)
@@ -43,7 +43,7 @@ def test_completion_tier_b_uses_openrouter_with_anthropic_model(mocker):
fake_response.choices = [mocker.MagicMock(message=mocker.MagicMock(content="(strategy ...)"))]
fake_response.usage = mocker.MagicMock(prompt_tokens=80, completion_tokens=150)
fake_openai.chat.completions.create.return_value = fake_response
mocker.patch("multi_swarm.llm.client.OpenAI", return_value=fake_openai)
mocker.patch("multi_swarm_core.llm.client.OpenAI", return_value=fake_openai)
client = LLMClient(openrouter_api_key="or-x")
g = make_genome(ModelTier.B)
@@ -67,7 +67,7 @@ def test_completion_retries_on_connection_error(mocker):
fake_openai.chat.completions.create.side_effect = openai.APIConnectionError(
request=mocker.MagicMock()
)
mocker.patch("multi_swarm.llm.client.OpenAI", return_value=fake_openai)
mocker.patch("multi_swarm_core.llm.client.OpenAI", return_value=fake_openai)
client = LLMClient(openrouter_api_key="or-x")
g = make_genome(ModelTier.C)
@@ -86,7 +86,7 @@ def test_completion_uses_custom_model_tier_c(mocker):
]
fake_response.usage = mocker.MagicMock(prompt_tokens=10, completion_tokens=20)
fake_openai.chat.completions.create.return_value = fake_response
mocker.patch("multi_swarm.llm.client.OpenAI", return_value=fake_openai)
mocker.patch("multi_swarm_core.llm.client.OpenAI", return_value=fake_openai)
client = LLMClient(
openrouter_api_key="or-x",
@@ -109,7 +109,7 @@ def test_completion_uses_custom_model_tier_b(mocker):
]
fake_response.usage = mocker.MagicMock(prompt_tokens=10, completion_tokens=20)
fake_openai.chat.completions.create.return_value = fake_response
mocker.patch("multi_swarm.llm.client.OpenAI", return_value=fake_openai)
mocker.patch("multi_swarm_core.llm.client.OpenAI", return_value=fake_openai)
client = LLMClient(
openrouter_api_key="or-x",
@@ -130,7 +130,7 @@ def test_completion_tier_s_uses_openrouter_with_anthropic_model(mocker):
fake_response.choices = [mocker.MagicMock(message=mocker.MagicMock(content="(strategy s)"))]
fake_response.usage = mocker.MagicMock(prompt_tokens=50, completion_tokens=100)
fake_openai.chat.completions.create.return_value = fake_response
mocker.patch("multi_swarm.llm.client.OpenAI", return_value=fake_openai)
mocker.patch("multi_swarm_core.llm.client.OpenAI", return_value=fake_openai)
client = LLMClient(openrouter_api_key="or-x")
g = make_genome(ModelTier.S)
@@ -149,7 +149,7 @@ def test_completion_tier_a_uses_openrouter_with_anthropic_model(mocker):
fake_response.choices = [mocker.MagicMock(message=mocker.MagicMock(content="(strategy a)"))]
fake_response.usage = mocker.MagicMock(prompt_tokens=40, completion_tokens=80)
fake_openai.chat.completions.create.return_value = fake_response
mocker.patch("multi_swarm.llm.client.OpenAI", return_value=fake_openai)
mocker.patch("multi_swarm_core.llm.client.OpenAI", return_value=fake_openai)
client = LLMClient(openrouter_api_key="or-x")
g = make_genome(ModelTier.A)
@@ -170,7 +170,7 @@ def test_completion_tier_d_uses_openrouter_with_llama(mocker):
]
fake_response.usage = mocker.MagicMock(prompt_tokens=30, completion_tokens=70)
fake_openai.chat.completions.create.return_value = fake_response
mocker.patch("multi_swarm.llm.client.OpenAI", return_value=fake_openai)
mocker.patch("multi_swarm_core.llm.client.OpenAI", return_value=fake_openai)
client = LLMClient(openrouter_api_key="or-x")
g = make_genome(ModelTier.D)
@@ -191,7 +191,7 @@ def test_completion_uses_custom_model_tier_s(mocker):
]
fake_response.usage = mocker.MagicMock(prompt_tokens=10, completion_tokens=20)
fake_openai.chat.completions.create.return_value = fake_response
mocker.patch("multi_swarm.llm.client.OpenAI", return_value=fake_openai)
mocker.patch("multi_swarm_core.llm.client.OpenAI", return_value=fake_openai)
client = LLMClient(
openrouter_api_key="or-x",
@@ -221,7 +221,7 @@ def test_completion_succeeds_after_one_retry(mocker):
openai.APITimeoutError(request=mocker.MagicMock()),
fake_response,
]
mocker.patch("multi_swarm.llm.client.OpenAI", return_value=fake_openai)
mocker.patch("multi_swarm_core.llm.client.OpenAI", return_value=fake_openai)
client = LLMClient(openrouter_api_key="or-x")
g = make_genome(ModelTier.C)
+1 -1
View File
@@ -1,7 +1,7 @@
import numpy as np
import pandas as pd
from multi_swarm.agents.market_summary import build_market_summary
from multi_swarm_core.agents.market_summary import build_market_summary
def test_build_summary_basic() -> None:
+1 -1
View File
@@ -2,7 +2,7 @@ import numpy as np
import pandas as pd
import pytest
from multi_swarm.metrics.basic import max_drawdown, sharpe_ratio, total_return
from multi_swarm_core.metrics.basic import max_drawdown, sharpe_ratio, total_return
def test_sharpe_zero_returns():
+1 -1
View File
@@ -1,7 +1,7 @@
import numpy as np
import pandas as pd
from multi_swarm.metrics.dsr import deflated_sharpe_ratio, expected_max_sharpe
from multi_swarm_core.metrics.dsr import deflated_sharpe_ratio, expected_max_sharpe
def test_expected_max_sharpe_grows_with_n_trials():
+2 -2
View File
@@ -4,8 +4,8 @@ import random
from collections import Counter
from dataclasses import dataclass
from multi_swarm.genome.hypothesis import HypothesisAgentGenome, ModelTier
from multi_swarm.genome.mutation import weighted_random_mutate
from multi_swarm_core.genome.hypothesis import HypothesisAgentGenome, ModelTier
from multi_swarm_core.genome.mutation import weighted_random_mutate
_PROMPT = (
"Strategia mean-reversion 1h BTC. Entry long quando RSI(14) < 30 e "
+2 -2
View File
@@ -3,8 +3,8 @@ from __future__ import annotations
import random
from dataclasses import dataclass
from multi_swarm.genome.hypothesis import HypothesisAgentGenome, ModelTier
from multi_swarm.genome.mutation_prompt_llm import (
from multi_swarm_core.genome.hypothesis import HypothesisAgentGenome, ModelTier
from multi_swarm_core.genome.mutation_prompt_llm import (
MUTATION_INSTRUCTIONS,
_extract_prompt,
is_valid_prompt,
+3 -3
View File
@@ -6,9 +6,9 @@ import numpy as np
import pandas as pd
import pytest
from multi_swarm.backtest.orders import Side
from multi_swarm.protocol.compiler import compile_strategy
from multi_swarm.protocol.parser import parse_strategy
from multi_swarm_core.backtest.orders import Side
from multi_swarm_core.protocol.compiler import compile_strategy
from multi_swarm_core.protocol.parser import parse_strategy
@pytest.fixture
+2 -2
View File
@@ -2,7 +2,7 @@ import json
import pytest
from multi_swarm.protocol.grammar import (
from multi_swarm_core.protocol.grammar import (
ACTION_VALUES,
ALL_OPS,
COMPARATOR_OPS,
@@ -10,7 +10,7 @@ from multi_swarm.protocol.grammar import (
KIND_VALUES,
LOGICAL_OPS,
)
from multi_swarm.protocol.parser import (
from multi_swarm_core.protocol.parser import (
FeatureNode,
IndicatorNode,
LiteralNode,
+2 -2
View File
@@ -2,8 +2,8 @@ import json
import pytest
from multi_swarm.protocol.parser import parse_strategy
from multi_swarm.protocol.validator import ValidationError, validate_strategy
from multi_swarm_core.protocol.parser import parse_strategy
from multi_swarm_core.protocol.validator import ValidationError, validate_strategy
def _wrap(condition: dict, action: str = "entry-long") -> str:
+2 -2
View File
@@ -1,8 +1,8 @@
import json
from pathlib import Path
from multi_swarm.genome.hypothesis import HypothesisAgentGenome, ModelTier
from multi_swarm.persistence.repository import Repository
from multi_swarm_core.genome.hypothesis import HypothesisAgentGenome, ModelTier
from multi_swarm_core.persistence.repository import Repository
def make_genome(idx: int) -> HypothesisAgentGenome:
+2 -2
View File
@@ -1,7 +1,7 @@
import random
from multi_swarm.ga.selection import elite_select, tournament_select
from multi_swarm.genome.hypothesis import HypothesisAgentGenome, ModelTier
from multi_swarm_core.ga.selection import elite_select, tournament_select
from multi_swarm_core.genome.hypothesis import HypothesisAgentGenome, ModelTier
def make(idx: int) -> HypothesisAgentGenome:
+1 -1
View File
@@ -1,7 +1,7 @@
import pandas as pd
import pytest
from multi_swarm.data.splits import expanding_walk_forward
from multi_swarm_core.data.splits import expanding_walk_forward
@pytest.fixture