01b82a03bc
This commit introduces a new test file, `tests/test_data_loader.py`, to verify the functionality of `get_data_mt5`. It uses `unittest.mock.MagicMock` to mock the `MetaTrader5` module, allowing tests to run on Linux where the module cannot be imported. The tests cover: - Live trading data retrieval (`start_pos=None`). - Backtesting data retrieval with a specific `start_pos`. - Error handling when `copy_rates_from_pos` returns `None`. - The proper conversion of rates into a pandas DataFrame with a parsed datetime index. Co-authored-by: maghdam <63883156+maghdam@users.noreply.github.com>
75 lines
2.3 KiB
Python
75 lines
2.3 KiB
Python
import sys
|
|
from unittest.mock import MagicMock
|
|
|
|
# Mock MetaTrader5 before importing data_loader
|
|
mt5_mock = MagicMock()
|
|
sys.modules['MetaTrader5'] = mt5_mock
|
|
|
|
import pandas as pd
|
|
import pytest
|
|
from data.data_loader import get_data_mt5
|
|
|
|
def test_get_data_mt5_live_trading():
|
|
"""Test get_data_mt5 when start_pos is None (live trading)."""
|
|
# Arrange
|
|
symbol = "BTCUSD"
|
|
n_bars = 100
|
|
timeframe = mt5_mock.TIMEFRAME_H1
|
|
|
|
# Mock return value of copy_rates_from_pos
|
|
mock_rates = [
|
|
{"time": 1600000000, "open": 1.0, "high": 2.0, "low": 0.5, "close": 1.5},
|
|
{"time": 1600003600, "open": 1.5, "high": 2.5, "low": 1.0, "close": 2.0},
|
|
]
|
|
mt5_mock.copy_rates_from_pos.return_value = mock_rates
|
|
|
|
# Act
|
|
df = get_data_mt5(symbol, n_bars, timeframe)
|
|
|
|
# Assert
|
|
mt5_mock.copy_rates_from_pos.assert_called_once_with(symbol, timeframe, 0, n_bars)
|
|
assert isinstance(df, pd.DataFrame)
|
|
assert df.index.name == 'time'
|
|
assert len(df) == 2
|
|
assert "open" in df.columns
|
|
assert df.index[0] == pd.to_datetime(1600000000, unit='s')
|
|
|
|
def test_get_data_mt5_backtesting():
|
|
"""Test get_data_mt5 when start_pos is provided (backtesting)."""
|
|
# Arrange
|
|
mt5_mock.copy_rates_from_pos.reset_mock()
|
|
symbol = "EURUSD"
|
|
n_bars = 50
|
|
timeframe = mt5_mock.TIMEFRAME_M15
|
|
start_pos = 10
|
|
|
|
mock_rates = [
|
|
{"time": 1600000000, "open": 1.1, "high": 1.2, "low": 1.0, "close": 1.15},
|
|
]
|
|
mt5_mock.copy_rates_from_pos.return_value = mock_rates
|
|
|
|
# Act
|
|
df = get_data_mt5(symbol, n_bars, timeframe, start_pos=start_pos)
|
|
|
|
# Assert
|
|
mt5_mock.copy_rates_from_pos.assert_called_once_with(symbol, timeframe, start_pos, n_bars)
|
|
assert isinstance(df, pd.DataFrame)
|
|
assert df.index.name == 'time'
|
|
assert len(df) == 1
|
|
|
|
def test_get_data_mt5_no_data():
|
|
"""Test get_data_mt5 when copy_rates_from_pos returns None."""
|
|
# Arrange
|
|
mt5_mock.copy_rates_from_pos.reset_mock()
|
|
symbol = "INVALID"
|
|
n_bars = 10
|
|
timeframe = mt5_mock.TIMEFRAME_H1
|
|
|
|
mt5_mock.copy_rates_from_pos.return_value = None
|
|
|
|
# Act & Assert
|
|
with pytest.raises(ValueError, match=f"Could not retrieve data for {symbol}"):
|
|
get_data_mt5(symbol, n_bars, timeframe)
|
|
|
|
mt5_mock.copy_rates_from_pos.assert_called_once_with(symbol, timeframe, 0, n_bars)
|