Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
93718212fa |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -204,11 +204,8 @@ def market_regime_dc(df: pd.DataFrame, threshold: float = 0.01) -> pd.DataFrame:
|
||||
dc_up, dc_down = calculate_dc(dfc, threshold=threshold)
|
||||
t_down, t_up = calculate_trend(dc_up, dc_down, dfc)
|
||||
dfc["market_regime"] = np.nan
|
||||
# Map index locations to actual index labels since calculate_dc returns integer indices
|
||||
t_up_labels = dfc.index[t_up] if len(t_up) > 0 else []
|
||||
t_down_labels = dfc.index[t_down] if len(t_down) > 0 else []
|
||||
dfc.loc[t_up_labels, "market_regime"] = 1
|
||||
dfc.loc[t_down_labels, "market_regime"] = 0
|
||||
dfc.loc[t_up, "market_regime"] = 1
|
||||
dfc.loc[t_down, "market_regime"] = 0
|
||||
dfc["market_regime"] = dfc["market_regime"].ffill().bfill()
|
||||
return dfc
|
||||
|
||||
@@ -269,7 +266,7 @@ def displacement_detection(
|
||||
dfc["displacement"] = 0
|
||||
mask = dfc["candle_range"] > strenght * dfc["STD"]
|
||||
dfc.loc[mask, "displacement"] = 1
|
||||
dfc["red_displacement"] = (dfc["displacement"].astype(int) & dfc["displacement"].shift(1).fillna(0).astype(int)).astype(int)
|
||||
dfc["red_displacement"] = (dfc["displacement"] & dfc["displacement"].shift(1).fillna(0)).astype(int)
|
||||
return dfc
|
||||
|
||||
|
||||
|
||||
@@ -101,9 +101,13 @@ class TradingApp:
|
||||
Loads a pre-trained classification pipeline (e.g., 'best_rf_pipeline.pkl').
|
||||
This pipeline is expected to produce SHIFTED labels [0,1,2].
|
||||
"""
|
||||
self.pipeline = joblib.load(pipeline_path)
|
||||
logging.info(f"Loaded pipeline from {pipeline_path}")
|
||||
log_and_print(f"Loaded pipeline from {pipeline_path}")
|
||||
import joblib
|
||||
try:
|
||||
self.pipeline = joblib.load(pipeline_path)
|
||||
log_and_print(f"Pipeline loaded from {pipeline_path}")
|
||||
except Exception as e:
|
||||
log_and_print(f"Failed to load pipeline: {e}", is_error=True)
|
||||
self.pipeline = None
|
||||
|
||||
def ml_signal_generation(self, symbol, n_bars, timeframe):
|
||||
"""
|
||||
|
||||
@@ -1,171 +0,0 @@
|
||||
import pytest
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
from features.feature_engineering import (
|
||||
spread,
|
||||
candle_information,
|
||||
log_transform,
|
||||
mathematical_derivatives,
|
||||
parkinson_estimator,
|
||||
yang_zhang_estimator,
|
||||
market_regime_dc,
|
||||
gap_detection,
|
||||
displacement_detection,
|
||||
set_double_barrier_label
|
||||
)
|
||||
|
||||
@pytest.fixture
|
||||
def sample_df():
|
||||
"""Create a sample dataframe with OHLCV data for testing."""
|
||||
dates = pd.date_range("2023-01-01", periods=10)
|
||||
data = {
|
||||
"open": [100.0, 102.0, 101.0, 105.0, 104.0, 106.0, 108.0, 107.0, 109.0, 110.0],
|
||||
"high": [105.0, 106.0, 104.0, 108.0, 107.0, 109.0, 110.0, 111.0, 112.0, 115.0],
|
||||
"low": [95.0, 100.0, 99.0, 102.0, 101.0, 104.0, 105.0, 106.0, 107.0, 108.0],
|
||||
"close": [102.0, 101.0, 105.0, 104.0, 106.0, 108.0, 107.0, 109.0, 110.0, 112.0],
|
||||
"tick_volume": [1000, 1200, 1100, 1500, 1300, 1400, 1600, 1700, 1800, 2000]
|
||||
}
|
||||
return pd.DataFrame(data, index=dates)
|
||||
|
||||
def test_spread(sample_df):
|
||||
"""Test spread calculation."""
|
||||
df_result = spread(sample_df)
|
||||
|
||||
# Check if 'spread' column exists
|
||||
assert "spread" in df_result.columns
|
||||
|
||||
# Check calculation
|
||||
expected_spread = sample_df["high"] - sample_df["low"]
|
||||
pd.testing.assert_series_equal(df_result["spread"], expected_spread, check_names=False)
|
||||
|
||||
# Check that original df is not modified
|
||||
assert "spread" not in sample_df.columns
|
||||
|
||||
def test_candle_information(sample_df):
|
||||
"""Test candle_information features."""
|
||||
df_result = candle_information(sample_df)
|
||||
|
||||
# Check if columns are added
|
||||
expected_cols = ["candle_way", "fill", "amplitude"]
|
||||
for col in expected_cols:
|
||||
assert col in df_result.columns
|
||||
|
||||
# Check logic of candle_way
|
||||
expected_candle_way = (sample_df["close"] > sample_df["open"]).astype(int)
|
||||
pd.testing.assert_series_equal(df_result["candle_way"], expected_candle_way, check_names=False)
|
||||
|
||||
# Check fill calculation
|
||||
rng = (sample_df["high"] - sample_df["low"]).replace(0, np.nan)
|
||||
expected_fill = (sample_df["close"] - sample_df["open"]).abs() / (rng + 1e-5)
|
||||
pd.testing.assert_series_equal(df_result["fill"], expected_fill, check_names=False)
|
||||
|
||||
def test_log_transform(sample_df):
|
||||
"""Test log_transform logic."""
|
||||
col_to_transform = "close"
|
||||
n_period = 2
|
||||
df_result = log_transform(sample_df, col_to_transform, n_period)
|
||||
|
||||
# Check columns
|
||||
assert f"log_{col_to_transform}" in df_result.columns
|
||||
assert f"log_ret_{n_period}" in df_result.columns
|
||||
|
||||
# Check log calculation
|
||||
expected_log = np.log(sample_df[col_to_transform].clip(lower=1e-12))
|
||||
pd.testing.assert_series_equal(df_result[f"log_{col_to_transform}"], expected_log, check_names=False)
|
||||
|
||||
# Check diff calculation
|
||||
expected_diff = expected_log.diff(n_period)
|
||||
pd.testing.assert_series_equal(df_result[f"log_ret_{n_period}"], expected_diff, check_names=False)
|
||||
|
||||
def test_mathematical_derivatives(sample_df):
|
||||
"""Test velocity and acceleration logic."""
|
||||
col_to_derive = "close"
|
||||
df_result = mathematical_derivatives(sample_df, col_to_derive)
|
||||
|
||||
# Check columns
|
||||
assert "velocity" in df_result.columns
|
||||
assert "acceleration" in df_result.columns
|
||||
|
||||
# Check calculation
|
||||
expected_velocity = sample_df[col_to_derive].diff()
|
||||
expected_acceleration = expected_velocity.diff()
|
||||
|
||||
pd.testing.assert_series_equal(df_result["velocity"], expected_velocity, check_names=False)
|
||||
pd.testing.assert_series_equal(df_result["acceleration"], expected_acceleration, check_names=False)
|
||||
|
||||
def test_parkinson_estimator(sample_df):
|
||||
"""Test Parkinson estimator."""
|
||||
# Test with valid window
|
||||
vol = parkinson_estimator(sample_df)
|
||||
assert not np.isnan(vol)
|
||||
assert vol > 0
|
||||
|
||||
# Test with empty window
|
||||
empty_df = pd.DataFrame()
|
||||
empty_vol = parkinson_estimator(empty_df)
|
||||
assert np.isnan(empty_vol)
|
||||
|
||||
def test_yang_zhang_estimator(sample_df):
|
||||
"""Test Yang Zhang estimator."""
|
||||
# Test with valid window
|
||||
vol = yang_zhang_estimator(sample_df)
|
||||
assert not np.isnan(vol)
|
||||
assert vol > 0
|
||||
|
||||
# Test with empty window
|
||||
empty_df = pd.DataFrame()
|
||||
empty_vol = yang_zhang_estimator(empty_df)
|
||||
assert np.isnan(empty_vol)
|
||||
|
||||
def test_market_regime_dc(sample_df):
|
||||
"""Test market regime calculation."""
|
||||
df_result = market_regime_dc(sample_df, threshold=0.01)
|
||||
|
||||
# Check column
|
||||
assert "market_regime" in df_result.columns
|
||||
|
||||
# Check values
|
||||
assert df_result["market_regime"].isin([0, 1, np.nan]).all()
|
||||
|
||||
def test_gap_detection(sample_df):
|
||||
"""Test gap detection calculation."""
|
||||
df_result = gap_detection(sample_df)
|
||||
|
||||
# Check expected columns
|
||||
expected_cols = [
|
||||
"Bullish_gap_inf",
|
||||
"Bullish_gap_sup",
|
||||
"Bullish_gap_size",
|
||||
"Bearish_gap_inf",
|
||||
"Bearish_gap_sup",
|
||||
"Bearish_gap_size",
|
||||
]
|
||||
for col in expected_cols:
|
||||
assert col in df_result.columns
|
||||
|
||||
def test_displacement_detection(sample_df):
|
||||
"""Test displacement detection."""
|
||||
df_result = displacement_detection(sample_df, period=2)
|
||||
|
||||
# Check added columns
|
||||
assert "candle_range" in df_result.columns
|
||||
assert "Variation" in df_result.columns
|
||||
assert "STD" in df_result.columns
|
||||
assert "displacement" in df_result.columns
|
||||
assert "red_displacement" in df_result.columns
|
||||
|
||||
# Check values of displacement
|
||||
assert df_result["displacement"].isin([0, 1]).all()
|
||||
assert df_result["red_displacement"].isin([0, 1]).all()
|
||||
|
||||
def test_set_double_barrier_label(sample_df):
|
||||
"""Test set double barrier label."""
|
||||
# Since our sample_df only has 10 rows and we drop NAs,
|
||||
# we need a small horizon to not drop all rows.
|
||||
df_result = set_double_barrier_label(sample_df, up=0.01, down=0.01, horizon=2)
|
||||
|
||||
# Check columns
|
||||
assert "barrier_label" in df_result.columns
|
||||
|
||||
# Check values
|
||||
assert df_result["barrier_label"].isin([0, 1]).all()
|
||||
@@ -0,0 +1,48 @@
|
||||
import sys
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
# Mock dependencies before importing TradingApp
|
||||
sys.modules['MetaTrader5'] = MagicMock()
|
||||
sys.modules['pandas'] = MagicMock()
|
||||
sys.modules['numpy'] = MagicMock()
|
||||
sys.modules['ta'] = MagicMock()
|
||||
sys.modules['joblib'] = MagicMock()
|
||||
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
from live_trading.multi_bar import TradingApp
|
||||
|
||||
class TestMultiBarTradingApp(unittest.TestCase):
|
||||
@patch('live_trading.multi_bar.joblib.load')
|
||||
@patch('live_trading.multi_bar.log_and_print')
|
||||
def test_load_pipeline_exception_handling(self, mock_log_and_print, mock_joblib_load):
|
||||
# Arrange
|
||||
app = TradingApp(symbol="EURUSD", lot_size=0.01, magic_number=234003)
|
||||
mock_joblib_load.side_effect = Exception("Mocked joblib load error")
|
||||
|
||||
# Act
|
||||
app.load_pipeline("dummy_path.pkl")
|
||||
|
||||
# Assert
|
||||
self.assertIsNone(app.pipeline)
|
||||
mock_joblib_load.assert_called_once_with("dummy_path.pkl")
|
||||
mock_log_and_print.assert_called_once_with("Failed to load pipeline: Mocked joblib load error", is_error=True)
|
||||
|
||||
@patch('live_trading.multi_bar.joblib.load')
|
||||
@patch('live_trading.multi_bar.log_and_print')
|
||||
def test_load_pipeline_success(self, mock_log_and_print, mock_joblib_load):
|
||||
# Arrange
|
||||
app = TradingApp(symbol="EURUSD", lot_size=0.01, magic_number=234003)
|
||||
mock_pipeline = "mock_pipeline_instance"
|
||||
mock_joblib_load.return_value = mock_pipeline
|
||||
|
||||
# Act
|
||||
app.load_pipeline("valid_path.pkl")
|
||||
|
||||
# Assert
|
||||
self.assertEqual(app.pipeline, mock_pipeline)
|
||||
mock_joblib_load.assert_called_once_with("valid_path.pkl")
|
||||
mock_log_and_print.assert_called_once_with("Pipeline loaded from valid_path.pkl")
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user