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
+234
View File
@@ -0,0 +1,234 @@
{
"version": "1.0.0",
"lastScanned": 1778863584729,
"projectRoot": "/opt/docker/multi_swarm_coevolutive",
"techStack": {
"languages": [
{
"name": "Python",
"version": null,
"confidence": "high",
"markers": [
"pyproject.toml"
]
}
],
"frameworks": [
{
"name": "pytest",
"version": null,
"category": "testing"
}
],
"packageManager": null,
"runtime": null
},
"build": {
"buildCommand": null,
"testCommand": "pytest",
"lintCommand": "ruff check",
"devCommand": null,
"scripts": {}
},
"conventions": {
"namingStyle": null,
"importStyle": null,
"testPattern": null,
"fileOrganization": null
},
"structure": {
"isMonorepo": false,
"workspaces": [],
"mainDirectories": [
"docs",
"scripts",
"src",
"tests"
],
"gitBranches": {
"defaultBranch": "main",
"branchingStrategy": null
}
},
"customNotes": [],
"directoryMap": {
"data": {
"path": "data",
"purpose": "Data files",
"fileCount": 0,
"lastAccessed": 1778863584681,
"keyFiles": []
},
"docs": {
"path": "docs",
"purpose": "Documentation",
"fileCount": 0,
"lastAccessed": 1778863584688,
"keyFiles": []
},
"scripts": {
"path": "scripts",
"purpose": "Build/utility scripts",
"fileCount": 6,
"lastAccessed": 1778863584699,
"keyFiles": [
"__init__.py",
"backtest_strategy.py",
"replay_strategies_window.py",
"run_paper_trading.py",
"run_phase1.py"
]
},
"series": {
"path": "series",
"purpose": null,
"fileCount": 1,
"lastAccessed": 1778863584703,
"keyFiles": [
"f4a6ed332c35c4a2.parquet"
]
},
"src": {
"path": "src",
"purpose": "Source code",
"fileCount": 0,
"lastAccessed": 1778863584706,
"keyFiles": []
},
"state": {
"path": "state",
"purpose": null,
"fileCount": 3,
"lastAccessed": 1778863584707,
"keyFiles": [
"runs.db",
"runs.db-shm",
"runs.db-wal"
]
},
"strategies": {
"path": "strategies",
"purpose": null,
"fileCount": 2,
"lastAccessed": 1778863584707,
"keyFiles": [
"btc_fb63e851.json",
"eth_facd6af85d5d.json"
]
},
"tests": {
"path": "tests",
"purpose": "Test files",
"fileCount": 1,
"lastAccessed": 1778863584710,
"keyFiles": [
"__init__.py"
]
}
},
"hotPaths": [
{
"path": "src/multi_swarm/paper_trading/persistence.py",
"accessCount": 2,
"lastAccessed": 1778864950928,
"type": "file"
},
{
"path": "src/multi_swarm/paper_trading/executor.py",
"accessCount": 2,
"lastAccessed": 1778864951455,
"type": "file"
},
{
"path": "src/multi_swarm/paper_trading/portfolio.py",
"accessCount": 2,
"lastAccessed": 1778864956467,
"type": "file"
},
{
"path": "src/multi_swarm/paper_trading/__init__.py",
"accessCount": 2,
"lastAccessed": 1778864957276,
"type": "file"
},
{
"path": "src/multi_swarm/dashboard/data.py",
"accessCount": 2,
"lastAccessed": 1778864958856,
"type": "file"
},
{
"path": "src/multi_swarm/dashboard/__init__.py",
"accessCount": 2,
"lastAccessed": 1778864959235,
"type": "file"
},
{
"path": "pyproject.toml",
"accessCount": 2,
"lastAccessed": 1778864960093,
"type": "file"
},
{
"path": "docker-compose.yml",
"accessCount": 2,
"lastAccessed": 1778864960851,
"type": "file"
},
{
"path": ".env.example",
"accessCount": 2,
"lastAccessed": 1778864961733,
"type": "file"
},
{
"path": "Dockerfile",
"accessCount": 1,
"lastAccessed": 1778864536214,
"type": "file"
},
{
"path": "src/multi_swarm/__init__.py",
"accessCount": 1,
"lastAccessed": 1778864537411,
"type": "file"
},
{
"path": "README.md",
"accessCount": 1,
"lastAccessed": 1778864537500,
"type": "file"
},
{
"path": "src/multi_swarm/dashboard/nicegui_app.py",
"accessCount": 1,
"lastAccessed": 1778864557898,
"type": "file"
},
{
"path": "src/multi_swarm/persistence/schema.py",
"accessCount": 1,
"lastAccessed": 1778864949548,
"type": "file"
},
{
"path": "src/multi_swarm/persistence/repository.py",
"accessCount": 1,
"lastAccessed": 1778864949987,
"type": "file"
},
{
"path": "src/multi_swarm/config.py",
"accessCount": 1,
"lastAccessed": 1778864959813,
"type": "file"
},
{
"path": "scripts/run_paper_trading.py",
"accessCount": 1,
"lastAccessed": 1778864961224,
"type": "file"
}
],
"userDirectives": []
}
@@ -0,0 +1,8 @@
{
"session_id": "798fb16b-8751-4e21-a558-26b5cea16bd8",
"ended_at": "2026-05-15T00:33:45.627Z",
"reason": "other",
"agents_spawned": 0,
"agents_completed": 0,
"modes_used": []
}
@@ -0,0 +1,8 @@
{
"session_id": "d997b670-db00-45b4-a478-cdad4d7fd603",
"ended_at": "2026-05-15T14:30:53.277Z",
"reason": "other",
"agents_spawned": 1,
"agents_completed": 1,
"modes_used": []
}
@@ -0,0 +1,8 @@
{
"session_id": "ed0d4e09-401a-47e4-b354-336908ba30c2",
"ended_at": "2026-05-14T09:47:10.928Z",
"reason": "other",
"agents_spawned": 0,
"agents_completed": 0,
"modes_used": []
}
@@ -0,0 +1,31 @@
{"t":0,"agent":"a682971","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a3e1e57","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"ac6e465","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"ae622fc","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a70edb8","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a0298bb","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a0a1dac","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a233182","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a36dbf7","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"ad92a42","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a3d10f4","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a3a6023","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a0031d5","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a49c162","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a593b10","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a3936fc","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a547232","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a5b6003","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a70d843","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"aec9396","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a339545","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"acb249c","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"acd29d1","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a8e0c37","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a8e001b","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"ac6bdc5","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a69506c","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"aacfb9e","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"ac010a8","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a7f5511","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a5e7734","agent_type":"unknown","event":"agent_stop","success":true}
@@ -0,0 +1,6 @@
{"t":0,"agent":"aa06dbe","agent_type":"Explore","event":"agent_start","parent_mode":"none"}
{"t":0,"agent":"a62f5be","agent_type":"Explore","event":"agent_start","parent_mode":"none"}
{"t":0,"agent":"a62f5be","agent_type":"Explore","event":"agent_stop","success":true,"duration_ms":21379}
{"t":0,"agent":"aa06dbe","agent_type":"Explore","event":"agent_stop","success":true,"duration_ms":94545}
{"t":0,"agent":"a086f61","agent_type":"Plan","event":"agent_start","parent_mode":"none"}
{"t":0,"agent":"a086f61","agent_type":"Plan","event":"agent_stop","success":true,"duration_ms":202552}
@@ -0,0 +1,16 @@
{"t":0,"agent":"a0d4467","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a160b0e","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"af3bbac","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a1ee6c9","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a4ad30d","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a90eb8d","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"ae064b2","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a0c8984","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"ad27588","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a523e02","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a2f3f5e","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"ad7358f","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a70e03c","agent_type":"unknown","event":"agent_stop","success":true}
{"t":0,"agent":"a5535e6","agent_type":"Explore","event":"agent_start","parent_mode":"none"}
{"t":0,"agent":"a5535e6","agent_type":"Explore","event":"agent_stop","success":true,"duration_ms":316451}
{"t":0,"agent":"adffe1e","agent_type":"unknown","event":"agent_stop","success":true}
@@ -0,0 +1 @@
{"t":0,"agent":"a25cb13","agent_type":"unknown","event":"agent_stop","success":true}
+6
View File
@@ -0,0 +1,6 @@
{
"timestamp": "2026-05-15T16:46:57.759Z",
"backgroundTasks": [],
"sessionStartTimestamp": "2026-05-15T16:46:24.599Z",
"sessionId": "c410f859-5a67-475c-a941-8e2c50ed3a11"
}
+1
View File
@@ -0,0 +1 @@
{"session_id":"c410f859-5a67-475c-a941-8e2c50ed3a11","transcript_path":"/root/.claude/projects/-opt-docker-multi-swarm-coevolutive/c410f859-5a67-475c-a941-8e2c50ed3a11.jsonl","cwd":"/opt/docker/multi_swarm_coevolutive","effort":{"level":"xhigh"},"session_name":"monorepo-reorganization-split-revert","model":{"id":"claude-opus-4-7[1m]","display_name":"Opus 4.7 (1M context)"},"workspace":{"current_dir":"/opt/docker/multi_swarm_coevolutive","project_dir":"/opt/docker/multi_swarm_coevolutive","added_dirs":[]},"version":"2.1.142","output_style":{"name":"default"},"cost":{"total_cost_usd":12.174355699999994,"total_duration_ms":3442407,"total_api_duration_ms":1675477,"total_lines_added":750,"total_lines_removed":345},"context_window":{"total_input_tokens":212953,"total_output_tokens":8,"context_window_size":1000000,"current_usage":{"input_tokens":6,"output_tokens":8,"cache_creation_input_tokens":599,"cache_read_input_tokens":212348},"used_percentage":21,"remaining_percentage":79},"exceeds_200k_tokens":true,"fast_mode":false,"thinking":{"enabled":true},"rate_limits":{"five_hour":{"used_percentage":11,"resets_at":1778881200},"seven_day":{"used_percentage":21,"resets_at":1779138000}}}
+3
View File
@@ -0,0 +1,3 @@
{
"lastSentAt": "2026-05-15T17:22:55.330Z"
}
+7
View File
@@ -0,0 +1,7 @@
{
"tool_name": "Bash",
"tool_input_preview": "{\"command\":\"find /opt/docker/multi_swarm_coevolutive -name \\\"config.py\\\" | xargs grep -l \\\"DATA_DIR\\\\|STRATEGIES\\\\|STATE\\\" 2>/dev/null\"}",
"error": "Exit code 123",
"timestamp": "2026-05-15T17:03:17.335Z",
"retry_count": 1
}
+145
View File
@@ -0,0 +1,145 @@
{
"updatedAt": "2026-05-15T17:12:22.595Z",
"missions": [
{
"id": "session:d997b670-db00-45b4-a478-cdad4d7fd603:none",
"source": "session",
"name": "none",
"objective": "Session mission",
"createdAt": "2026-05-15T10:07:56.561Z",
"updatedAt": "2026-05-15T11:04:10.376Z",
"status": "done",
"workerCount": 1,
"taskCounts": {
"total": 1,
"pending": 0,
"blocked": 0,
"inProgress": 0,
"completed": 1,
"failed": 0
},
"agents": [
{
"name": "Explore:a5535e6",
"role": "Explore",
"ownership": "a5535e676159dcf1c",
"status": "done",
"currentStep": null,
"latestUpdate": "completed",
"completedSummary": null,
"updatedAt": "2026-05-15T11:04:10.376Z"
}
],
"timeline": [
{
"id": "session-start:a5535e676159dcf1c:2026-05-15T10:07:56.561Z",
"at": "2026-05-15T10:07:56.561Z",
"kind": "update",
"agent": "Explore:a5535e6",
"detail": "started Explore:a5535e6",
"sourceKey": "session-start:a5535e676159dcf1c"
},
{
"id": "session-stop:a5535e676159dcf1c:2026-05-15T10:13:13.012Z",
"at": "2026-05-15T10:13:13.012Z",
"kind": "completion",
"agent": "Explore:a5535e6",
"detail": "completed",
"sourceKey": "session-stop:a5535e676159dcf1c"
},
{
"id": "session-stop:adffe1eae69f95602:2026-05-15T11:04:10.376Z",
"at": "2026-05-15T11:04:10.376Z",
"kind": "completion",
"agent": "Explore:a5535e6",
"detail": "completed",
"sourceKey": "session-stop:adffe1eae69f95602"
}
]
},
{
"id": "session:c410f859-5a67-475c-a941-8e2c50ed3a11:none",
"source": "session",
"name": "none",
"objective": "Session mission",
"createdAt": "2026-05-15T17:02:02.737Z",
"updatedAt": "2026-05-15T17:12:22.595Z",
"status": "done",
"workerCount": 3,
"taskCounts": {
"total": 3,
"pending": 0,
"blocked": 0,
"inProgress": 0,
"completed": 3,
"failed": 0
},
"agents": [
{
"name": "Explore:aa06dbe",
"role": "Explore",
"ownership": "aa06dbecb11544c5e",
"status": "done",
"currentStep": null,
"latestUpdate": "completed",
"completedSummary": null,
"updatedAt": "2026-05-15T17:03:37.282Z"
},
{
"name": "Explore:a62f5be",
"role": "Explore",
"ownership": "a62f5bee30bd7a6c1",
"status": "done",
"currentStep": null,
"latestUpdate": "completed",
"completedSummary": null,
"updatedAt": "2026-05-15T17:02:35.066Z"
},
{
"name": "Plan:a086f61",
"role": "Plan",
"ownership": "a086f61a1fbb580be",
"status": "done",
"currentStep": null,
"latestUpdate": "completed",
"completedSummary": null,
"updatedAt": "2026-05-15T17:12:22.595Z"
}
],
"timeline": [
{
"id": "session-stop:a62f5bee30bd7a6c1:2026-05-15T17:02:35.066Z",
"at": "2026-05-15T17:02:35.066Z",
"kind": "completion",
"agent": "Explore:a62f5be",
"detail": "completed",
"sourceKey": "session-stop:a62f5bee30bd7a6c1"
},
{
"id": "session-stop:aa06dbecb11544c5e:2026-05-15T17:03:37.282Z",
"at": "2026-05-15T17:03:37.282Z",
"kind": "completion",
"agent": "Explore:aa06dbe",
"detail": "completed",
"sourceKey": "session-stop:aa06dbecb11544c5e"
},
{
"id": "session-start:a086f61a1fbb580be:2026-05-15T17:09:00.043Z",
"at": "2026-05-15T17:09:00.043Z",
"kind": "update",
"agent": "Plan:a086f61",
"detail": "started Plan:a086f61",
"sourceKey": "session-start:a086f61a1fbb580be"
},
{
"id": "session-stop:a086f61a1fbb580be:2026-05-15T17:12:22.595Z",
"at": "2026-05-15T17:12:22.595Z",
"kind": "completion",
"agent": "Plan:a086f61",
"detail": "completed",
"sourceKey": "session-stop:a086f61a1fbb580be"
}
]
}
]
}
+35
View File
@@ -0,0 +1,35 @@
{
"agents": [
{
"agent_id": "aa06dbecb11544c5e",
"agent_type": "Explore",
"started_at": "2026-05-15T17:02:02.737Z",
"parent_mode": "none",
"status": "completed",
"completed_at": "2026-05-15T17:03:37.282Z",
"duration_ms": 94545
},
{
"agent_id": "a62f5bee30bd7a6c1",
"agent_type": "Explore",
"started_at": "2026-05-15T17:02:13.687Z",
"parent_mode": "none",
"status": "completed",
"completed_at": "2026-05-15T17:02:35.066Z",
"duration_ms": 21379
},
{
"agent_id": "a086f61a1fbb580be",
"agent_type": "Plan",
"started_at": "2026-05-15T17:09:00.043Z",
"parent_mode": "none",
"status": "completed",
"completed_at": "2026-05-15T17:12:22.595Z",
"duration_ms": 202552
}
],
"total_spawned": 3,
"total_completed": 3,
"total_failed": 0,
"last_updated": "2026-05-15T17:12:22.696Z"
}
+7 -7
View File
@@ -17,13 +17,13 @@ import math
from datetime import datetime from datetime import datetime
from pathlib import Path from pathlib import Path
from multi_swarm.agents.adversarial import AdversarialAgent from multi_swarm_core.agents.adversarial import AdversarialAgent
from multi_swarm.agents.falsification import FalsificationAgent from multi_swarm_core.agents.falsification import FalsificationAgent
from multi_swarm.cerbero.client import CerberoClient from multi_swarm_core.cerbero.client import CerberoClient
from multi_swarm.config import load_settings from multi_swarm_core.config import load_settings
from multi_swarm.data.cerbero_ohlcv import CerberoOHLCVLoader, OHLCVRequest from multi_swarm_core.data.cerbero_ohlcv import CerberoOHLCVLoader, OHLCVRequest
from multi_swarm.protocol.parser import parse_strategy from multi_swarm_core.protocol.parser import parse_strategy
from multi_swarm.protocol.validator import validate_strategy from multi_swarm_core.protocol.validator import validate_strategy
def main() -> None: def main() -> None:
+127
View File
@@ -0,0 +1,127 @@
"""Replay diagnostico: per ciascuna strategia conta quanti bar avrebbero
soddisfatto le condizioni di ciascuna regola sull'ultimo `--days` di storico.
Ouput tabellare per branch: total_bars, fires, fire_rate, primo/ultimo fire.
Esegue anche un backtest grezzo (entry-on-signal, exit-on-flat) per stimare
n_trades e total_return realistici nel periodo.
Esempio:
docker compose exec multi-swarm-paper \
python /app/scripts/replay_strategies_window.py --days 30
"""
from __future__ import annotations
import argparse
import json
from datetime import UTC, datetime, timedelta
from pathlib import Path
import pandas as pd
from multi_swarm_core.cerbero.client import CerberoClient
from multi_swarm_core.config import load_settings
from multi_swarm_core.data.cerbero_ohlcv import CerberoOHLCVLoader, OHLCVRequest
from multi_swarm_core.protocol.compiler import _eval_node, compile_strategy
from multi_swarm_core.protocol.parser import parse_strategy
PROJECT_ROOT = Path(__file__).resolve().parent.parent
def parse_args() -> argparse.Namespace:
p = argparse.ArgumentParser()
p.add_argument("--days", type=int, default=30)
p.add_argument("--strategies-dir", default=str(PROJECT_ROOT / "strategies"))
return p.parse_args()
def fetch_window(loader: CerberoOHLCVLoader, symbol: str, days: int) -> pd.DataFrame:
end = datetime.now(UTC).replace(minute=0, second=0, microsecond=0)
start = end - timedelta(days=days)
req = OHLCVRequest(
symbol=symbol, timeframe="1h", start=start, end=end, exchange="deribit"
)
return loader._fetch(req) # noqa: SLF001 — bypass cache
def per_branch_fires(strategy_path: Path, ohlcv: pd.DataFrame) -> list[dict]:
raw = strategy_path.read_text()
parsed = parse_strategy(raw)
out = []
for idx, rule in enumerate(parsed.rules):
cond_series = _eval_node(rule.condition, ohlcv).fillna(False).astype(bool)
n = int(cond_series.sum())
first = ohlcv.index[cond_series.argmax()] if n > 0 else None
# last fire: argmax on reversed
last = ohlcv.index[len(cond_series) - 1 - cond_series[::-1].argmax()] if n > 0 else None
out.append({
"branch_idx": idx,
"action": rule.action,
"fires": n,
"fire_rate_pct": round(100.0 * n / len(ohlcv), 2),
"first_fire": first,
"last_fire": last,
})
return out
def quick_pnl(strategy_path: Path, ohlcv: pd.DataFrame, fees_bp: float = 5.0) -> dict:
"""Approx: at each bar evaluate compiled signal series (long/short/flat),
apply position to next-bar return, charge fees on changes. No leverage."""
raw = strategy_path.read_text()
parsed = parse_strategy(raw)
sig_fn = compile_strategy(parsed)
signals = sig_fn(ohlcv) # series of "long"/"short"/"flat"
# map to position: long=+1, short=-1, flat=0
pos = signals.map({"long": 1, "short": -1, "flat": 0}).fillna(0).astype(int)
rets = ohlcv["close"].pct_change().fillna(0.0)
# next-bar execution: position decided at bar t applies to return t+1 -> shift
pnl = pos.shift(1).fillna(0) * rets
# fees on position changes
changes = pos.diff().abs().fillna(0).astype(int)
fee_per_change = fees_bp / 10_000.0
pnl_after_fees = pnl - changes * fee_per_change
cum = (1 + pnl_after_fees).prod() - 1
n_trades = int((changes > 0).sum())
time_in_market = float((pos != 0).mean())
return {
"n_trades": n_trades,
"total_return_pct": round(100.0 * float(cum), 3),
"time_in_market_pct": round(100.0 * time_in_market, 2),
}
def main() -> None:
args = parse_args()
settings = load_settings()
token = (
settings.cerbero_mainnet_token.get_secret_value()
if settings.cerbero_mainnet_token
else settings.cerbero_testnet_token.get_secret_value()
)
cerbero = CerberoClient(
base_url=settings.cerbero_base_url,
token=token,
bot_tag=settings.cerbero_bot_tag,
)
loader = CerberoOHLCVLoader(client=cerbero, cache_dir=settings.series_dir)
strategies_dir = Path(args.strategies_dir)
pairs = [
("BTC-PERPETUAL", sorted(strategies_dir.glob("btc_*.json"))[0]),
("ETH-PERPETUAL", sorted(strategies_dir.glob("eth_*.json"))[0]),
]
for symbol, strat_path in pairs:
print(f"\n=== {symbol} strategy={strat_path.name} window={args.days}d ===")
ohlcv = fetch_window(loader, symbol, args.days)
print(f"bars: {len(ohlcv)} range: {ohlcv.index[0]} -> {ohlcv.index[-1]}")
print("\n-- per branch --")
for row in per_branch_fires(strat_path, ohlcv):
print(json.dumps(row, default=str))
print("\n-- quick pnl (next-bar exec, fees=5bp) --")
print(json.dumps(quick_pnl(strat_path, ohlcv), default=str))
if __name__ == "__main__":
main()
+7 -7
View File
@@ -25,13 +25,13 @@ from dataclasses import dataclass
from datetime import UTC, datetime, timedelta from datetime import UTC, datetime, timedelta
from pathlib import Path from pathlib import Path
from multi_swarm.cerbero.client import CerberoClient from multi_swarm_core.cerbero.client import CerberoClient
from multi_swarm.config import load_settings from multi_swarm_core.config import load_settings
from multi_swarm.data.cerbero_ohlcv import CerberoOHLCVLoader, OHLCVRequest from multi_swarm_core.data.cerbero_ohlcv import CerberoOHLCVLoader, OHLCVRequest
from multi_swarm.paper_trading.executor import PaperExecutor from multi_swarm_core.paper_trading.executor import PaperExecutor
from multi_swarm.paper_trading.persistence import PaperRepository from multi_swarm_core.paper_trading.persistence import PaperRepository
from multi_swarm.paper_trading.portfolio import Portfolio from multi_swarm_core.paper_trading.portfolio import Portfolio
from multi_swarm.persistence.repository import Repository from multi_swarm_core.persistence.repository import Repository
PROJECT_ROOT = Path(__file__).resolve().parent.parent PROJECT_ROOT = Path(__file__).resolve().parent.parent
+6 -6
View File
@@ -3,12 +3,12 @@ from __future__ import annotations
import argparse import argparse
from datetime import datetime from datetime import datetime
from multi_swarm.cerbero.client import CerberoClient from multi_swarm_core.cerbero.client import CerberoClient
from multi_swarm.config import load_settings from multi_swarm_core.config import load_settings
from multi_swarm.data.cerbero_ohlcv import CerberoOHLCVLoader, OHLCVRequest from multi_swarm_core.data.cerbero_ohlcv import CerberoOHLCVLoader, OHLCVRequest
from multi_swarm.genome.hypothesis import ModelTier from multi_swarm_core.genome.hypothesis import ModelTier
from multi_swarm.llm.client import LLMClient from multi_swarm_core.llm.client import LLMClient
from multi_swarm.orchestrator.run import RunConfig, run_phase1 from multi_swarm_core.orchestrator.run import RunConfig, run_phase1
def parse_args() -> argparse.Namespace: def parse_args() -> argparse.Namespace:
+3 -3
View File
@@ -6,9 +6,9 @@ from pathlib import Path
import numpy as np import numpy as np
import pandas as pd # type: ignore[import-untyped] import pandas as pd # type: ignore[import-untyped]
from multi_swarm.genome.hypothesis import HypothesisAgentGenome, ModelTier from multi_swarm_core.genome.hypothesis import HypothesisAgentGenome, ModelTier
from multi_swarm.llm.client import CompletionResult from multi_swarm_core.llm.client import CompletionResult
from multi_swarm.orchestrator.run import RunConfig, run_phase1 from multi_swarm_core.orchestrator.run import RunConfig, run_phase1
_MOCK_STRATEGY = json.dumps( _MOCK_STRATEGY = json.dumps(
{ {
@@ -1,6 +1,6 @@
"""NiceGUI dashboard — port progressivo da Streamlit. """NiceGUI dashboard — port progressivo da Streamlit.
Avvio: ``uv run python -m multi_swarm.dashboard.nicegui_app`` Avvio: ``uv run python -m multi_swarm_core.dashboard.nicegui_app``
Default port 8080. Streamlit resta su 8501 durante la migrazione. Default port 8080. Streamlit resta su 8501 durante la migrazione.
Riusa ``dashboard.data`` (Repository helpers) senza modifiche al backend. Riusa ``dashboard.data`` (Repository helpers) senza modifiche al backend.
@@ -28,7 +28,7 @@ import pandas as pd # type: ignore[import-untyped]
import plotly.graph_objects as go # type: ignore[import-untyped] import plotly.graph_objects as go # type: ignore[import-untyped]
from nicegui import app, ui from nicegui import app, ui
from multi_swarm.dashboard.data import ( from multi_swarm_core.dashboard.data import (
evaluations_df, evaluations_df,
generations_df, generations_df,
genomes_df, genomes_df,
@@ -1,5 +1,5 @@
"""Persistenza paper-trading: usa lo stesso ``runs.db`` con tabelle dedicate """Persistenza paper-trading: usa lo stesso ``runs.db`` con tabelle dedicate
``paper_trading_*`` (vedi :mod:`multi_swarm.persistence.schema`). ``paper_trading_*`` (vedi :mod:`multi_swarm_core.persistence.schema`).
""" """
from __future__ import annotations from __future__ import annotations
+4 -4
View File
@@ -5,10 +5,10 @@ import numpy as np
import pandas as pd import pandas as pd
import pytest import pytest
from multi_swarm.genome.hypothesis import ModelTier from multi_swarm_core.genome.hypothesis import ModelTier
from multi_swarm.llm.client import CompletionResult from multi_swarm_core.llm.client import CompletionResult
from multi_swarm.orchestrator.run import RunConfig, run_phase1 from multi_swarm_core.orchestrator.run import RunConfig, run_phase1
from multi_swarm.persistence.repository import Repository from multi_swarm_core.persistence.repository import Repository
@pytest.fixture @pytest.fixture
@@ -9,8 +9,8 @@ from __future__ import annotations
import random import random
from dataclasses import dataclass from dataclasses import dataclass
from multi_swarm.ga.loop import GAConfig, next_generation from multi_swarm_core.ga.loop import GAConfig, next_generation
from multi_swarm.genome.hypothesis import HypothesisAgentGenome, ModelTier from multi_swarm_core.genome.hypothesis import HypothesisAgentGenome, ModelTier
_PROMPT_TEMPLATES = ( _PROMPT_TEMPLATES = (
"Strategia mean-reversion 1h. Entry long RSI(14) < 30 e close > SMA(50). Stop 2%.", "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 pandas as pd
import pytest import pytest
from multi_swarm.agents.adversarial import ( from multi_swarm_core.agents.adversarial import (
AdversarialAgent, AdversarialAgent,
AdversarialReport, AdversarialReport,
Severity, Severity,
) )
from multi_swarm.backtest.engine import BacktestResult from multi_swarm_core.backtest.engine import BacktestResult
from multi_swarm.backtest.orders import Side, Trade from multi_swarm_core.backtest.orders import Side, Trade
from multi_swarm.protocol.parser import parse_strategy from multi_swarm_core.protocol.parser import parse_strategy
@pytest.fixture @pytest.fixture
@@ -178,10 +178,10 @@ def test_undertrading_under_10_is_high(monkeypatch: pytest.MonkeyPatch,
return lambda df: fake_signals return lambda df: fake_signals
monkeypatch.setattr( monkeypatch.setattr(
"multi_swarm.agents.adversarial.BacktestEngine.run", fake_run "multi_swarm_core.agents.adversarial.BacktestEngine.run", fake_run
) )
monkeypatch.setattr( monkeypatch.setattr(
"multi_swarm.agents.adversarial.compile_strategy", fake_compile "multi_swarm_core.agents.adversarial.compile_strategy", fake_compile
) )
src = _MINIMAL_STRATEGY_SRC 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] def fake_compile(strategy): # type: ignore[no-untyped-def]
return lambda df: fake_signals return lambda df: fake_signals
monkeypatch.setattr("multi_swarm.agents.adversarial.BacktestEngine.run", fake_run) monkeypatch.setattr("multi_swarm_core.agents.adversarial.BacktestEngine.run", fake_run)
monkeypatch.setattr("multi_swarm.agents.adversarial.compile_strategy", fake_compile) monkeypatch.setattr("multi_swarm_core.agents.adversarial.compile_strategy", fake_compile)
ast = parse_strategy(_MINIMAL_STRATEGY_SRC) ast = parse_strategy(_MINIMAL_STRATEGY_SRC)
# Default threshold 10: 15 trade NON killato # 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 return lambda df: fake_signals
monkeypatch.setattr( monkeypatch.setattr(
"multi_swarm.agents.adversarial.BacktestEngine.run", fake_run "multi_swarm_core.agents.adversarial.BacktestEngine.run", fake_run
) )
monkeypatch.setattr( monkeypatch.setattr(
"multi_swarm.agents.adversarial.compile_strategy", fake_compile "multi_swarm_core.agents.adversarial.compile_strategy", fake_compile
) )
src = _MINIMAL_STRATEGY_SRC src = _MINIMAL_STRATEGY_SRC
@@ -315,10 +315,10 @@ def test_flat_too_long_flagged(monkeypatch: pytest.MonkeyPatch,
return lambda df: fake_signals return lambda df: fake_signals
monkeypatch.setattr( monkeypatch.setattr(
"multi_swarm.agents.adversarial.BacktestEngine.run", fake_run "multi_swarm_core.agents.adversarial.BacktestEngine.run", fake_run
) )
monkeypatch.setattr( monkeypatch.setattr(
"multi_swarm.agents.adversarial.compile_strategy", fake_compile "multi_swarm_core.agents.adversarial.compile_strategy", fake_compile
) )
src = _MINIMAL_STRATEGY_SRC src = _MINIMAL_STRATEGY_SRC
@@ -367,10 +367,10 @@ def test_fees_eat_alpha_flagged(monkeypatch: pytest.MonkeyPatch,
return lambda df: fake_signals return lambda df: fake_signals
monkeypatch.setattr( monkeypatch.setattr(
"multi_swarm.agents.adversarial.BacktestEngine.run", fake_run "multi_swarm_core.agents.adversarial.BacktestEngine.run", fake_run
) )
monkeypatch.setattr( monkeypatch.setattr(
"multi_swarm.agents.adversarial.compile_strategy", fake_compile "multi_swarm_core.agents.adversarial.compile_strategy", fake_compile
) )
src = _MINIMAL_STRATEGY_SRC src = _MINIMAL_STRATEGY_SRC
@@ -413,10 +413,10 @@ def test_time_in_market_too_high_flagged(monkeypatch: pytest.MonkeyPatch,
return lambda df: fake_signals return lambda df: fake_signals
monkeypatch.setattr( monkeypatch.setattr(
"multi_swarm.agents.adversarial.BacktestEngine.run", fake_run "multi_swarm_core.agents.adversarial.BacktestEngine.run", fake_run
) )
monkeypatch.setattr( monkeypatch.setattr(
"multi_swarm.agents.adversarial.compile_strategy", fake_compile "multi_swarm_core.agents.adversarial.compile_strategy", fake_compile
) )
src = _MINIMAL_STRATEGY_SRC src = _MINIMAL_STRATEGY_SRC
@@ -461,10 +461,10 @@ def test_reasonable_balanced_strategy_not_flagged(monkeypatch: pytest.MonkeyPatc
return lambda df: fake_signals return lambda df: fake_signals
monkeypatch.setattr( monkeypatch.setattr(
"multi_swarm.agents.adversarial.BacktestEngine.run", fake_run "multi_swarm_core.agents.adversarial.BacktestEngine.run", fake_run
) )
monkeypatch.setattr( monkeypatch.setattr(
"multi_swarm.agents.adversarial.compile_strategy", fake_compile "multi_swarm_core.agents.adversarial.compile_strategy", fake_compile
) )
src = _MINIMAL_STRATEGY_SRC src = _MINIMAL_STRATEGY_SRC
+2 -2
View File
@@ -2,8 +2,8 @@ import numpy as np
import pandas as pd import pandas as pd
import pytest import pytest
from multi_swarm.backtest.engine import BacktestEngine from multi_swarm_core.backtest.engine import BacktestEngine
from multi_swarm.backtest.orders import Side from multi_swarm_core.backtest.orders import Side
@pytest.fixture @pytest.fixture
+1 -1
View File
@@ -2,7 +2,7 @@ from datetime import UTC, datetime
import pytest 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: def test_order_validates_side() -> None:
+1 -1
View File
@@ -1,7 +1,7 @@
import pytest import pytest
import responses import responses
from multi_swarm.cerbero.client import CerberoClient from multi_swarm_core.cerbero.client import CerberoClient
@responses.activate @responses.activate
+1 -1
View File
@@ -6,7 +6,7 @@ from pathlib import Path
import pandas as pd import pandas as pd
import pytest import pytest
from multi_swarm.data.cerbero_ohlcv import CerberoOHLCVLoader, OHLCVRequest from multi_swarm_core.data.cerbero_ohlcv import CerberoOHLCVLoader, OHLCVRequest
@pytest.fixture @pytest.fixture
+1 -1
View File
@@ -1,6 +1,6 @@
import pytest import pytest
from multi_swarm.cerbero.tools import CerberoTools from multi_swarm_core.cerbero.tools import CerberoTools
def test_tools_dispatch_sma(mocker): 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: Note on .env isolation:
The happy-path test relies on monkeypatch.setenv to provide values. 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 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: 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_core.genome.hypothesis import ModelTier
from multi_swarm.llm.cost_tracker import CostTracker, estimate_cost from multi_swarm_core.llm.cost_tracker import CostTracker, estimate_cost
def test_estimate_cost_tier_c(): def test_estimate_cost_tier_c():
+1 -1
View File
@@ -1,6 +1,6 @@
from __future__ import annotations 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: 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 pandas as pd
import pytest import pytest
from multi_swarm.agents.falsification import FalsificationAgent, FalsificationReport from multi_swarm_core.agents.falsification import FalsificationAgent, FalsificationReport
from multi_swarm.protocol.parser import parse_strategy from multi_swarm_core.protocol.parser import parse_strategy
@pytest.fixture @pytest.fixture
+3 -3
View File
@@ -1,8 +1,8 @@
from itertools import pairwise from itertools import pairwise
from multi_swarm.agents.adversarial import AdversarialReport, Finding, Severity from multi_swarm_core.agents.adversarial import AdversarialReport, Finding, Severity
from multi_swarm.agents.falsification import FalsificationReport from multi_swarm_core.agents.falsification import FalsificationReport
from multi_swarm.ga.fitness import compute_fitness from multi_swarm_core.ga.fitness import compute_fitness
def make_falsification( def make_falsification(
+2 -2
View File
@@ -1,7 +1,7 @@
import random import random
from multi_swarm.ga.initial import build_initial_population from multi_swarm_core.ga.initial import build_initial_population
from multi_swarm.genome.hypothesis import ModelTier from multi_swarm_core.genome.hypothesis import ModelTier
def test_initial_population_size(): def test_initial_population_size():
+2 -2
View File
@@ -1,7 +1,7 @@
import random import random
from multi_swarm.ga.loop import GAConfig, next_generation from multi_swarm_core.ga.loop import GAConfig, next_generation
from multi_swarm.genome.hypothesis import HypothesisAgentGenome, ModelTier from multi_swarm_core.genome.hypothesis import HypothesisAgentGenome, ModelTier
def make(idx: int) -> HypothesisAgentGenome: def make(idx: int) -> HypothesisAgentGenome:
+1 -1
View File
@@ -2,7 +2,7 @@ import math
import pytest import pytest
from multi_swarm.ga.summary import generation_summary from multi_swarm_core.ga.summary import generation_summary
def test_summary_basic_stats(): def test_summary_basic_stats():
+2 -2
View File
@@ -1,7 +1,7 @@
import random import random
from multi_swarm.genome.crossover import uniform_crossover from multi_swarm_core.genome.crossover import uniform_crossover
from multi_swarm.genome.hypothesis import HypothesisAgentGenome, ModelTier from multi_swarm_core.genome.hypothesis import HypothesisAgentGenome, ModelTier
def make(name: str) -> HypothesisAgentGenome: 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(): def test_genome_creation_defaults():
+2 -2
View File
@@ -2,8 +2,8 @@ import random
import pytest import pytest
from multi_swarm.genome.hypothesis import HypothesisAgentGenome, ModelTier from multi_swarm_core.genome.hypothesis import HypothesisAgentGenome, ModelTier
from multi_swarm.genome.mutation import ( from multi_swarm_core.genome.mutation import (
COGNITIVE_STYLES, COGNITIVE_STYLES,
FEATURE_POOL, FEATURE_POOL,
mutate_cognitive_style, mutate_cognitive_style,
+3 -3
View File
@@ -1,8 +1,8 @@
import json import json
from multi_swarm.agents.hypothesis import HypothesisAgent, MarketSummary from multi_swarm_core.agents.hypothesis import HypothesisAgent, MarketSummary
from multi_swarm.genome.hypothesis import HypothesisAgentGenome, ModelTier from multi_swarm_core.genome.hypothesis import HypothesisAgentGenome, ModelTier
from multi_swarm.llm.client import CompletionResult, EmptyCompletionError from multi_swarm_core.llm.client import CompletionResult, EmptyCompletionError
def make_summary() -> MarketSummary: def make_summary() -> MarketSummary:
+12 -12
View File
@@ -1,7 +1,7 @@
import pytest import pytest
from multi_swarm.genome.hypothesis import HypothesisAgentGenome, ModelTier from multi_swarm_core.genome.hypothesis import HypothesisAgentGenome, ModelTier
from multi_swarm.llm.client import CompletionResult, LLMClient from multi_swarm_core.llm.client import CompletionResult, LLMClient
def make_genome(tier: ModelTier) -> HypothesisAgentGenome: 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_response.usage = mocker.MagicMock(prompt_tokens=100, completion_tokens=200)
fake_openai.chat.completions.create.return_value = fake_response 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") client = LLMClient(openrouter_api_key="or-x")
g = make_genome(ModelTier.C) 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.choices = [mocker.MagicMock(message=mocker.MagicMock(content="(strategy ...)"))]
fake_response.usage = mocker.MagicMock(prompt_tokens=80, completion_tokens=150) fake_response.usage = mocker.MagicMock(prompt_tokens=80, completion_tokens=150)
fake_openai.chat.completions.create.return_value = fake_response 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") client = LLMClient(openrouter_api_key="or-x")
g = make_genome(ModelTier.B) 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( fake_openai.chat.completions.create.side_effect = openai.APIConnectionError(
request=mocker.MagicMock() 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") client = LLMClient(openrouter_api_key="or-x")
g = make_genome(ModelTier.C) 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_response.usage = mocker.MagicMock(prompt_tokens=10, completion_tokens=20)
fake_openai.chat.completions.create.return_value = fake_response 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( client = LLMClient(
openrouter_api_key="or-x", 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_response.usage = mocker.MagicMock(prompt_tokens=10, completion_tokens=20)
fake_openai.chat.completions.create.return_value = fake_response 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( client = LLMClient(
openrouter_api_key="or-x", 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.choices = [mocker.MagicMock(message=mocker.MagicMock(content="(strategy s)"))]
fake_response.usage = mocker.MagicMock(prompt_tokens=50, completion_tokens=100) fake_response.usage = mocker.MagicMock(prompt_tokens=50, completion_tokens=100)
fake_openai.chat.completions.create.return_value = fake_response 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") client = LLMClient(openrouter_api_key="or-x")
g = make_genome(ModelTier.S) 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.choices = [mocker.MagicMock(message=mocker.MagicMock(content="(strategy a)"))]
fake_response.usage = mocker.MagicMock(prompt_tokens=40, completion_tokens=80) fake_response.usage = mocker.MagicMock(prompt_tokens=40, completion_tokens=80)
fake_openai.chat.completions.create.return_value = fake_response 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") client = LLMClient(openrouter_api_key="or-x")
g = make_genome(ModelTier.A) 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_response.usage = mocker.MagicMock(prompt_tokens=30, completion_tokens=70)
fake_openai.chat.completions.create.return_value = fake_response 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") client = LLMClient(openrouter_api_key="or-x")
g = make_genome(ModelTier.D) 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_response.usage = mocker.MagicMock(prompt_tokens=10, completion_tokens=20)
fake_openai.chat.completions.create.return_value = fake_response 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( client = LLMClient(
openrouter_api_key="or-x", openrouter_api_key="or-x",
@@ -221,7 +221,7 @@ def test_completion_succeeds_after_one_retry(mocker):
openai.APITimeoutError(request=mocker.MagicMock()), openai.APITimeoutError(request=mocker.MagicMock()),
fake_response, 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") client = LLMClient(openrouter_api_key="or-x")
g = make_genome(ModelTier.C) g = make_genome(ModelTier.C)
+1 -1
View File
@@ -1,7 +1,7 @@
import numpy as np import numpy as np
import pandas as pd 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: def test_build_summary_basic() -> None:
+1 -1
View File
@@ -2,7 +2,7 @@ import numpy as np
import pandas as pd import pandas as pd
import pytest 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(): def test_sharpe_zero_returns():
+1 -1
View File
@@ -1,7 +1,7 @@
import numpy as np import numpy as np
import pandas as pd 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(): def test_expected_max_sharpe_grows_with_n_trials():
+2 -2
View File
@@ -4,8 +4,8 @@ import random
from collections import Counter from collections import Counter
from dataclasses import dataclass from dataclasses import dataclass
from multi_swarm.genome.hypothesis import HypothesisAgentGenome, ModelTier from multi_swarm_core.genome.hypothesis import HypothesisAgentGenome, ModelTier
from multi_swarm.genome.mutation import weighted_random_mutate from multi_swarm_core.genome.mutation import weighted_random_mutate
_PROMPT = ( _PROMPT = (
"Strategia mean-reversion 1h BTC. Entry long quando RSI(14) < 30 e " "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 import random
from dataclasses import dataclass from dataclasses import dataclass
from multi_swarm.genome.hypothesis import HypothesisAgentGenome, ModelTier from multi_swarm_core.genome.hypothesis import HypothesisAgentGenome, ModelTier
from multi_swarm.genome.mutation_prompt_llm import ( from multi_swarm_core.genome.mutation_prompt_llm import (
MUTATION_INSTRUCTIONS, MUTATION_INSTRUCTIONS,
_extract_prompt, _extract_prompt,
is_valid_prompt, is_valid_prompt,
+3 -3
View File
@@ -6,9 +6,9 @@ import numpy as np
import pandas as pd import pandas as pd
import pytest import pytest
from multi_swarm.backtest.orders import Side from multi_swarm_core.backtest.orders import Side
from multi_swarm.protocol.compiler import compile_strategy from multi_swarm_core.protocol.compiler import compile_strategy
from multi_swarm.protocol.parser import parse_strategy from multi_swarm_core.protocol.parser import parse_strategy
@pytest.fixture @pytest.fixture
+2 -2
View File
@@ -2,7 +2,7 @@ import json
import pytest import pytest
from multi_swarm.protocol.grammar import ( from multi_swarm_core.protocol.grammar import (
ACTION_VALUES, ACTION_VALUES,
ALL_OPS, ALL_OPS,
COMPARATOR_OPS, COMPARATOR_OPS,
@@ -10,7 +10,7 @@ from multi_swarm.protocol.grammar import (
KIND_VALUES, KIND_VALUES,
LOGICAL_OPS, LOGICAL_OPS,
) )
from multi_swarm.protocol.parser import ( from multi_swarm_core.protocol.parser import (
FeatureNode, FeatureNode,
IndicatorNode, IndicatorNode,
LiteralNode, LiteralNode,
+2 -2
View File
@@ -2,8 +2,8 @@ import json
import pytest import pytest
from multi_swarm.protocol.parser import parse_strategy from multi_swarm_core.protocol.parser import parse_strategy
from multi_swarm.protocol.validator import ValidationError, validate_strategy from multi_swarm_core.protocol.validator import ValidationError, validate_strategy
def _wrap(condition: dict, action: str = "entry-long") -> str: def _wrap(condition: dict, action: str = "entry-long") -> str:

Some files were not shown because too many files have changed in this diff Show More