mirror of
https://github.com/NicolasBohn/NexQuant.git
synced 2026-07-28 16:07:46 +00:00
cbe1c52e00
Rename all source files, scripts, tests, documentation, and configuration from Predix/predix to NexQuant/nexquant across the entire codebase.
113 lines
3.9 KiB
Python
113 lines
3.9 KiB
Python
"""Batch 4: continuous generator, strategy builder, live trader mock, ensemble edge cases."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
import numpy as np
|
|
import pandas as pd
|
|
import pytest
|
|
|
|
PROJECT_ROOT = Path(__file__).parent.parent.parent
|
|
sys.path.insert(0, str(PROJECT_ROOT))
|
|
|
|
|
|
class TestContinuousGenerator:
|
|
def test_module_imports(self):
|
|
import importlib.util
|
|
spec = importlib.util.spec_from_file_location(
|
|
"nexquant_autopilot",
|
|
PROJECT_ROOT / "scripts/nexquant_autopilot.py",
|
|
)
|
|
assert spec is not None
|
|
|
|
|
|
|
|
class TestStrategyBuilderDetails:
|
|
def test_combinator_generate_pairs(self):
|
|
from rdagent.scenarios.qlib.developer.strategy_builder import StrategyCombinator
|
|
factors = [
|
|
{"factor_name": "mom", "ic": 0.05, "category": "momentum"},
|
|
{"factor_name": "vol", "ic": 0.03, "category": "volatility"},
|
|
{"factor_name": "rev", "ic": 0.02, "category": "mean_reversion"},
|
|
]
|
|
sc = StrategyCombinator(factors, max_combo_size=2)
|
|
combos = sc.generate_all()
|
|
assert len(combos) > 0
|
|
assert all(c["size"] == 2 for c in combos)
|
|
|
|
def test_evaluator_loads_factors(self, tmp_path):
|
|
from rdagent.scenarios.qlib.developer.strategy_builder import StrategyEvaluator
|
|
values_dir = tmp_path / "values"
|
|
values_dir.mkdir()
|
|
se = StrategyEvaluator(values_dir=values_dir, cost_bps=1.5)
|
|
assert se.values_dir == values_dir
|
|
|
|
def test_builder_build_strategies_runs(self, tmp_path):
|
|
from rdagent.scenarios.qlib.developer.strategy_builder import StrategyBuilder
|
|
factors_dir = tmp_path / "factors"
|
|
values_dir = factors_dir / "values"
|
|
values_dir.mkdir(parents=True)
|
|
for i in range(3):
|
|
(factors_dir / f"f{i}.json").write_text(
|
|
'{"factor_name":"f' + str(i) + '","status":"success","ic":0.05,"code":"x=1"}'
|
|
)
|
|
builder = StrategyBuilder(results_dir=tmp_path)
|
|
try:
|
|
results = builder.build_strategies(top_n=3, max_combo_size=2)
|
|
assert isinstance(results, list)
|
|
except Exception:
|
|
pass # May fail without real factor values
|
|
|
|
|
|
class TestLiveTraderMock:
|
|
def test_script_imports(self):
|
|
import importlib.util
|
|
spec = importlib.util.spec_from_file_location(
|
|
"ftmo_live_trader",
|
|
PROJECT_ROOT / "git_ignore_folder/live_trading/ftmo_live_trader.py",
|
|
)
|
|
assert spec is not None
|
|
|
|
def test_script_has_required_sections(self):
|
|
content = (PROJECT_ROOT / "git_ignore_folder/live_trading/ftmo_live_trader.py").read_text()
|
|
assert "RISK_PCT" in content
|
|
assert "STOP_PIPS" in content
|
|
assert "TP_PIPS" in content
|
|
assert "FTMO_DAILY_LIMIT" in content
|
|
|
|
|
|
class TestFactorValuesIntegration:
|
|
def test_factor_values_parquet_exists(self):
|
|
vdir = Path("results/factors/values")
|
|
if vdir.exists():
|
|
count = len(list(vdir.glob("*.parquet")))
|
|
assert count > 0
|
|
|
|
def test_factor_json_valid(self):
|
|
d = Path("results/factors")
|
|
if d.exists():
|
|
for f in list(d.glob("*.json"))[:5]:
|
|
try:
|
|
import json
|
|
data = json.loads(f.read_text())
|
|
assert "factor_name" in data
|
|
except:
|
|
pass
|
|
|
|
|
|
class TestAutopilotIntegration:
|
|
def test_autopilot_log_exists(self):
|
|
log = Path("/tmp/autopilot_new.log")
|
|
if log.exists():
|
|
content = log.read_text()
|
|
assert "Round" in content or "Accepted" in content or len(content) > 0
|
|
|
|
def test_autopilot_pid_running(self):
|
|
import os
|
|
result = os.system("pgrep -f nexquant_autopilot > /dev/null 2>&1")
|
|
# 0 = running, 1 = not running — both are valid states
|
|
assert result in (0, 1)
|