Docs / Validate documentation (push) Canceled after 0s
Docs / Deploy GitHub Pages (push) Canceled after 0s
CI Final Summary (AI) / AI Final Summary (push) Canceled after 0s
CI Final Summary (AI) / Push/PR event feed (push) Canceled after 0s
CI / CI Integrity and Change Classification (push) Canceled after 0s
CI / Code Quality & Tests (push) Canceled after 0s
Dependency Lock & Migration Safety / Dependency drift (lock vs pyproject) (push) Canceled after 0s
Dependency Lock & Migration Safety / Migration safety (fail-loud + version postconditions) (push) Canceled after 0s
JS Tests / Frontend JS Unit Tests (push) Canceled after 0s
Security / CodeQL Analysis (push) Canceled after 0s
Security / Trivy Vulnerability Scan (push) Canceled after 0s
Tests (OS Matrix) / Py Tests (macos-latest) (push) Canceled after 0s
Tests (OS Matrix) / Py Tests (windows-latest) (push) Canceled after 0s
CI / Extended Validation (Tier 2) (push) Canceled after 0s
CI / Heavy CI (database-provider) (push) Canceled after 0s
CI / Heavy CI (e2e) (push) Canceled after 0s
CI / Heavy CI (integration) (push) Canceled after 0s
CI / Heavy CI (model-validation) (push) Canceled after 0s
CI / Heavy CI (research-backtest) (push) Canceled after 0s
CI / Aggregate CI Results (push) Canceled after 0s
Full project import for the self-hosted code hosting (https://code.aifunny.ltd/gavindiaz/my-NexusTradingForexBot.git). Includes the live-freshness + scaler-hash fixes for the permanent STALE dashboard (tick_pipeline now_utc stamps; infer_probabilities computes model_input_hash on the actual scaled 70D tensor), the data-fetch default-path fix, the g29 web-auth test fixes, and a Chinese user manual (使用手册.md) for the web dashboard. Scratch diagnostic scripts (check*.py, contain a live web-auth token) and the .kilo/ agent-worktree directory are gitignored, not committed. Co-Authored-By: Claude Code <noreply@anthropic.com>
86 lines
2.6 KiB
Python
86 lines
2.6 KiB
Python
"""Shared helpers: load the REAL MT5 capture fixtures.
|
|
|
|
The fixtures under tests/fixtures/mt5/ were captured READ-ONLY from the live
|
|
MetaQuotes-Demo terminal on 2026-08-17 (see capture_mt5_contract.py, deleted
|
|
after capture). Every value is a real broker response — no synthetic data.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
_FIXTURE_DIR = Path(__file__).resolve().parent.parent / "fixtures" / "mt5"
|
|
|
|
#: Object keys that are namedtuple plumbing, never broker data.
|
|
_SKIP_KEYS = frozenset(
|
|
{
|
|
"count",
|
|
"index",
|
|
"n_fields",
|
|
"n_sequence_fields",
|
|
"n_unnamed_fields",
|
|
"_none",
|
|
}
|
|
)
|
|
|
|
|
|
def fixture_path(name: str) -> Path:
|
|
path = _FIXTURE_DIR / f"{name}.json"
|
|
assert path.exists(), f"fixture missing: {path} (run the capture script first)"
|
|
return path
|
|
|
|
|
|
def load_fixture(name: str) -> dict[str, Any]:
|
|
return json.loads(fixture_path(name).read_text(encoding="utf-8"))
|
|
|
|
|
|
def fixture_objects(name: str) -> list[dict[str, Any]]:
|
|
"""Returns the cleaned per-object field dicts (value-only)."""
|
|
payload = load_fixture(name)
|
|
out: list[dict[str, Any]] = []
|
|
for obj in payload.get("objects", []):
|
|
cleaned = {
|
|
k: v["value"] if isinstance(v, dict) else v
|
|
for k, v in obj.items()
|
|
if k not in _SKIP_KEYS
|
|
}
|
|
out.append(cleaned)
|
|
return out
|
|
|
|
|
|
def fixture_object(name: str) -> dict[str, Any]:
|
|
"""Returns the cleaned field dict for single-object fixtures."""
|
|
payload = load_fixture(name)
|
|
obj = payload.get("object", {})
|
|
return {k: v["value"] for k, v in obj.items() if k not in _SKIP_KEYS}
|
|
|
|
|
|
def count_objects(name: str) -> int:
|
|
return int(load_fixture(name).get("count", 0))
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Canonical expected values computed from the REAL captures (deterministic).
|
|
# ---------------------------------------------------------------------------
|
|
EXPECTED = {
|
|
"account_login": 10011755849,
|
|
"deals_count": 88,
|
|
"orders_count": 136,
|
|
# 44 positions in the deal stream; 2 have only ENTRY deals (still open at
|
|
# capture time, no realized result) -> only their entry deals persist.
|
|
"positions_count": 44,
|
|
"open_positions_in_window": 2,
|
|
"closed_trades": 42,
|
|
"trades_net_total": 741.05,
|
|
"wins": 37,
|
|
"losses": 5,
|
|
"breakeven": 0, # the two zero-net positions are still OPEN (no OUT deal)
|
|
"best_trade": 178.11,
|
|
"worst_trade": -11.60,
|
|
"partial_close_position": 152487940044,
|
|
"partial_close_gross": 178.11,
|
|
"net_pnl_winning_close": 87.62, # single partial-close deal profit
|
|
}
|