Files
Trademind_OpenCode/tests/test_trademind.py
T

104 lines
3.3 KiB
Python

"""Smoke-Tests für TradeMind (ohne Netzwerk & ohne echte Keys)."""
import numpy as np
import pandas as pd
import pytest
from trademind.config import Config, StrategyConfig, TradingConfig, TrainingConfig
from trademind.strategy import Strategy
from trademind.engine import Engine
from trademind.trader import Trader
from trademind.exchange import MockBroker, CcxtBroker
from trademind.trainer import Trainer, eval_params, random_params
@pytest.fixture
def cfg() -> Config:
return Config(
trading=TradingConfig(),
strategy=StrategyConfig(),
training=TrainingConfig(generations=3, population=6),
exchanges={},
)
@pytest.fixture
def candles() -> pd.DataFrame:
rng = np.random.default_rng(0)
n = 300
close = 50_000 + np.cumsum(rng.standard_normal(n) * 500)
open_ = np.roll(close, 1)
open_[0] = 50_000
spread = np.abs(rng.standard_normal(n)) * 100 + 5
high = np.maximum(open_, close) + spread
low = np.minimum(open_, close) - spread
idx = pd.date_range(end=pd.Timestamp.utcnow().floor("h"), periods=n, freq="h")
return pd.DataFrame(
{"time": idx, "open": open_, "high": high, "low": low, "close": close,
"volume": rng.uniform(10, 100, n)}
)
def test_strategy_prepare_and_decide(cfg, candles):
st = Strategy(cfg.strategy)
prep = st.prepare(candles)
assert all(k in prep for k in ("ema_fast", "ema_slow", "rsi", "atr"))
sigs = st.decide(prep)
assert len(sigs) == len(candles)
assert sigs[-1].price > 0
def test_engine_run_produces_result(cfg, candles):
st = Strategy(cfg.strategy)
eng = Engine(cfg.trading, st)
res = eng.run(candles)
assert res.final_equity > 0
assert isinstance(res.summary().get("num_trades"), int)
assert res.equity_curve[0] > 0
def test_paper_trader_roundtrip(cfg, candles):
broker = MockBroker(seed=1)
st = Strategy(cfg.strategy)
tr = Trader(cfg, broker, st)
res = tr.simulate()
assert res.final_equity >= 0
assert res.num_trades >= 0
def test_trainer_improves_and_sets_weights(cfg, candles):
base = Strategy(cfg.strategy)
trainer = Trainer(cfg.training, base)
p0 = random_params(__import__("random").Random(1))
before = eval_params(p0, candles, cfg.trading, base, cfg.training)
best = trainer.train(candles, cfg.trading, base)
# after: best should be >= before (elitism guarantees)
after = eval_params(best, candles, cfg.trading, base, cfg.training)
assert after >= before - 1e-6
def test_data_broker_falls_back_to_mock(cfg):
"""Ohne Netzwerk/Exchange muss der Fallback auf Mock-Daten greifen."""
from trademind.cli import _data_broker
broker = _data_broker(cfg, data="auto", exchange="binance", seed=3)
df = broker.fetch_ohlcv("BTC/USDT", "1h", 50)
assert len(df) == 50
for col in ("open", "high", "low", "close"):
assert (df[col] > 0).all()
def test_mock_broker_deterministic():
b1 = MockBroker(seed=3).fetch_ohlcv("BTC/USDT", "1h", 100)
b2 = MockBroker(seed=3).fetch_ohlcv("BTC/USDT", "1h", 100)
assert b1.equals(b2)
def test_strategy_set_parameter(cfg):
st = Strategy(cfg.strategy)
p = st.parameters()
assert "fast_period" in p and "w_ema_cross" in p
st.set_parameter("fast_period", 20)
assert st.cfg.fast_period == 20
st.set_parameter("w_ema_cross", 1.5)
assert st.weights["ema_cross"] == pytest.approx(1.5)