- simulation.py: price-series loader (Yahoo snapshot) + allocate_capital 50/20/30 with min-100 shares, bucket3 excludes bucket1, cash fallback - /api/v1/simulation POST: combines theme 60/40 score + Siamchart dividend + Yahoo price; labels output paper/backtest non-PIT (never validated) - mt5_bridge.py: MT5 order interface, dry-run default; live dispatch needs MT5_SEND_ORDERS=1 AND approval (Windows-only MetaTrader5) - 12 new tests (simulation/mt5/api); full suite 184 OK; live verified (1M -> buckets)
49 lines
1.6 KiB
Python
49 lines
1.6 KiB
Python
"""Tests for the MT5 bridge (dry-run default + live gating)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import unittest
|
|
|
|
from app import mt5_bridge
|
|
from app.mt5_bridge import MT5OrderRequest, place_order
|
|
|
|
|
|
class MT5BridgeTest(unittest.TestCase):
|
|
def setUp(self):
|
|
# ensure live dispatch is OFF during these tests
|
|
self._prev = os.environ.get("MT5_SEND_ORDERS")
|
|
os.environ.pop("MT5_SEND_ORDERS", None)
|
|
|
|
def tearDown(self):
|
|
if self._prev is None:
|
|
os.environ.pop("MT5_SEND_ORDERS", None)
|
|
else:
|
|
os.environ["MT5_SEND_ORDERS"] = self._prev
|
|
|
|
def test_place_order_dry_runs_without_flag(self):
|
|
res = place_order(MT5OrderRequest("AOT", "BUY", 1.0), approve=True)
|
|
# Even with approval, without the env flag it stays dry-run.
|
|
self.assertFalse(res.executed)
|
|
self.assertTrue(res.dry_run)
|
|
|
|
def test_disabled_without_approval(self):
|
|
res = place_order(MT5OrderRequest("AOT", "BUY", 1.0), approve=False)
|
|
self.assertFalse(res.executed)
|
|
self.assertTrue(res.dry_run)
|
|
self.assertIn("gated", res.message)
|
|
|
|
def test_enabled_requires_both(self):
|
|
os.environ["MT5_SEND_ORDERS"] = "1"
|
|
# approval required even when flag set; but module likely unavailable ->
|
|
# still dry-run with 'not available' (never sends real order in tests)
|
|
res = place_order(MT5OrderRequest("AOT", "BUY", 1.0), approve=False)
|
|
self.assertFalse(res.executed)
|
|
|
|
def test_is_available_is_bool(self):
|
|
self.assertIsInstance(mt5_bridge.is_available(), bool)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|