refactor(paper_trading): move multi_swarm_core/paper_trading → strategy_crypto/backend

- git mv executor.py, portfolio.py, persistence.py al backend strategy_crypto
- Cancellato src/multi_swarm_core/multi_swarm_core/paper_trading/
- Patch import: from ..backtest/protocol → from multi_swarm_core.backtest/protocol
- persistence.py:
  * usa schema locale strategy_crypto.backend.schema (no piu' core)
  * docstring aggiornata: DB dedicato state/strategy_crypto.db isolato dal core
  * PaperRepository.init_schema() crea le tabelle paper_trading_*
- backend/__init__.py: re-export pubblico (PaperExecutor, Portfolio, PaperRepository, ...)
- config.py:
  * NEW: ga_db_path (alias DB_PATH legacy + GA_DB_PATH preferito)
  * NEW: strategy_crypto_db_path (STRATEGY_CRYPTO_DB_PATH)
  * db_path conserva come property proxy di ga_db_path per backcompat
- Test: import in venv workspace OK; load_settings() resolve entrambi i path

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Adriano Dal Pastro
2026-05-15 17:54:31 +00:00
parent 08f1585ab2
commit b02be64831
6 changed files with 58 additions and 8 deletions
@@ -6,7 +6,7 @@ in the project root. Required secrets are validated at instantiation time.
from pathlib import Path
from pydantic import Field, SecretStr
from pydantic import AliasChoices, Field, SecretStr
from pydantic_settings import BaseSettings, SettingsConfigDict
@@ -35,7 +35,24 @@ class Settings(BaseSettings):
run_name: str = "phase1-spike-001"
data_dir: Path = Field(default=Path("./data"))
series_dir: Path = Field(default=Path("./series"))
db_path: Path = Field(default=Path("./runs.db"))
# GA core DB (tabelle universali: runs, generations, genomes, evaluations, ...)
# Alias DB_PATH legacy mantenuto per backcompat (deprecato, rimuovere nei prossimi cicli).
ga_db_path: Path = Field(
default=Path("./state/runs.db"),
validation_alias=AliasChoices("GA_DB_PATH", "DB_PATH"),
)
# DB per la strategia crypto (tabelle paper_trading_*, isolato dal core)
strategy_crypto_db_path: Path = Field(
default=Path("./state/strategy_crypto.db"),
validation_alias="STRATEGY_CRYPTO_DB_PATH",
)
@property
def db_path(self) -> Path:
"""Backcompat alias: legge ga_db_path. Deprecato — usare ga_db_path."""
return self.ga_db_path
def load_settings() -> Settings:
@@ -0,0 +1,23 @@
"""Backend paper-trading per la strategia crypto.
Espone le classi principali per import ergonomici in scripts/runner:
from strategy_crypto.backend import PaperExecutor, Portfolio, PaperRepository
Per i tipi interni (TickResult, OpenPosition, Trade) importare dal sotto-modulo.
"""
from .executor import PaperExecutor, TickResult
from .persistence import PaperRepository
from .portfolio import OpenPosition, Portfolio
from .schema import PAPER_SCHEMA_SQL, init_schema
__all__ = [
"PAPER_SCHEMA_SQL",
"OpenPosition",
"PaperExecutor",
"PaperRepository",
"Portfolio",
"TickResult",
"init_schema",
]
@@ -20,9 +20,10 @@ from pathlib import Path
import pandas as pd # type: ignore[import-untyped]
from ..backtest.orders import Side, Trade
from ..protocol.compiler import compile_strategy
from ..protocol.parser import parse_strategy
from multi_swarm_core.backtest.orders import Side, Trade
from multi_swarm_core.protocol.compiler import compile_strategy
from multi_swarm_core.protocol.parser import parse_strategy
from .portfolio import OpenPosition, Portfolio
@@ -1,5 +1,9 @@
"""Persistenza paper-trading: usa lo stesso ``runs.db`` con tabelle dedicate
``paper_trading_*`` (vedi :mod:`multi_swarm_core.persistence.schema`).
"""Persistenza paper-trading: scrive su un DB dedicato (state/strategy_crypto.db)
con le tabelle ``paper_trading_*`` definite localmente in :mod:`.schema`.
Il DB e' isolato dal ``runs.db`` del core GA: nessun naming conflict con
future strategie (state/strategy_<asset>.db), nessuna contention di lock
fra writer GA e writer paper.
"""
from __future__ import annotations
@@ -13,12 +17,17 @@ from typing import Any
from .executor import TickResult
from .portfolio import Portfolio
from .schema import init_schema as _init_paper_schema
class PaperRepository:
def __init__(self, db_path: Path | str):
self.db_path = Path(db_path)
def init_schema(self) -> None:
"""Crea (se mancanti) le tabelle paper_trading_* su ``self.db_path``."""
_init_paper_schema(self.db_path)
def _conn(self) -> sqlite3.Connection:
conn = sqlite3.connect(self.db_path, isolation_level=None)
conn.row_factory = sqlite3.Row
@@ -17,7 +17,7 @@ from __future__ import annotations
from dataclasses import dataclass, field
from datetime import datetime
from ..backtest.orders import Side, Trade
from multi_swarm_core.backtest.orders import Side, Trade
@dataclass(frozen=True)