537 lines
22 KiB
Python
537 lines
22 KiB
Python
|
|
"""
|
||
|
|
Tests for Example Strategy Configurations
|
||
|
|
|
||
|
|
Tests the example trading strategies including EMA crossover, momentum,
|
||
|
|
mean reversion, scalping, and swing trading strategies.
|
||
|
|
"""
|
||
|
|
|
||
|
|
import pytest
|
||
|
|
import json
|
||
|
|
from typing import Dict, List
|
||
|
|
|
||
|
|
from components.charts.config.example_strategies import (
|
||
|
|
StrategyExample,
|
||
|
|
create_ema_crossover_strategy,
|
||
|
|
create_momentum_breakout_strategy,
|
||
|
|
create_mean_reversion_strategy,
|
||
|
|
create_scalping_strategy,
|
||
|
|
create_swing_trading_strategy,
|
||
|
|
get_all_example_strategies,
|
||
|
|
get_example_strategy,
|
||
|
|
get_strategies_by_difficulty,
|
||
|
|
get_strategies_by_risk_level,
|
||
|
|
get_strategies_by_market_condition,
|
||
|
|
get_strategy_summary,
|
||
|
|
export_example_strategies_to_json
|
||
|
|
)
|
||
|
|
|
||
|
|
from components.charts.config.strategy_charts import StrategyChartConfig
|
||
|
|
from components.charts.config.defaults import TradingStrategy
|
||
|
|
|
||
|
|
|
||
|
|
class TestStrategyExample:
|
||
|
|
"""Test StrategyExample dataclass."""
|
||
|
|
|
||
|
|
def test_strategy_example_creation(self):
|
||
|
|
"""Test StrategyExample creation with defaults."""
|
||
|
|
# Create a minimal config for testing
|
||
|
|
config = StrategyChartConfig(
|
||
|
|
strategy_name="Test Strategy",
|
||
|
|
strategy_type=TradingStrategy.DAY_TRADING,
|
||
|
|
description="Test strategy",
|
||
|
|
timeframes=["1h"]
|
||
|
|
)
|
||
|
|
|
||
|
|
example = StrategyExample(
|
||
|
|
config=config,
|
||
|
|
description="Test description"
|
||
|
|
)
|
||
|
|
|
||
|
|
assert example.config == config
|
||
|
|
assert example.description == "Test description"
|
||
|
|
assert example.author == "TCPDashboard"
|
||
|
|
assert example.difficulty == "Beginner"
|
||
|
|
assert example.risk_level == "Medium"
|
||
|
|
assert example.market_conditions == ["Trending"] # Default
|
||
|
|
assert example.notes == [] # Default
|
||
|
|
assert example.references == [] # Default
|
||
|
|
|
||
|
|
def test_strategy_example_with_custom_values(self):
|
||
|
|
"""Test StrategyExample with custom values."""
|
||
|
|
config = StrategyChartConfig(
|
||
|
|
strategy_name="Custom Strategy",
|
||
|
|
strategy_type=TradingStrategy.SCALPING,
|
||
|
|
description="Custom strategy",
|
||
|
|
timeframes=["1m"]
|
||
|
|
)
|
||
|
|
|
||
|
|
example = StrategyExample(
|
||
|
|
config=config,
|
||
|
|
description="Custom description",
|
||
|
|
author="Custom Author",
|
||
|
|
difficulty="Advanced",
|
||
|
|
expected_return="10% monthly",
|
||
|
|
risk_level="High",
|
||
|
|
market_conditions=["Volatile", "High Volume"],
|
||
|
|
notes=["Note 1", "Note 2"],
|
||
|
|
references=["Reference 1"]
|
||
|
|
)
|
||
|
|
|
||
|
|
assert example.author == "Custom Author"
|
||
|
|
assert example.difficulty == "Advanced"
|
||
|
|
assert example.expected_return == "10% monthly"
|
||
|
|
assert example.risk_level == "High"
|
||
|
|
assert example.market_conditions == ["Volatile", "High Volume"]
|
||
|
|
assert example.notes == ["Note 1", "Note 2"]
|
||
|
|
assert example.references == ["Reference 1"]
|
||
|
|
|
||
|
|
|
||
|
|
class TestEMACrossoverStrategy:
|
||
|
|
"""Test EMA Crossover strategy."""
|
||
|
|
|
||
|
|
def test_ema_crossover_creation(self):
|
||
|
|
"""Test EMA crossover strategy creation."""
|
||
|
|
strategy = create_ema_crossover_strategy()
|
||
|
|
|
||
|
|
assert isinstance(strategy, StrategyExample)
|
||
|
|
assert isinstance(strategy.config, StrategyChartConfig)
|
||
|
|
|
||
|
|
# Check strategy specifics
|
||
|
|
assert strategy.config.strategy_name == "EMA Crossover Strategy"
|
||
|
|
assert strategy.config.strategy_type == TradingStrategy.DAY_TRADING
|
||
|
|
assert "15m" in strategy.config.timeframes
|
||
|
|
assert "1h" in strategy.config.timeframes
|
||
|
|
assert "4h" in strategy.config.timeframes
|
||
|
|
|
||
|
|
# Check indicators
|
||
|
|
assert "ema_12" in strategy.config.overlay_indicators
|
||
|
|
assert "ema_26" in strategy.config.overlay_indicators
|
||
|
|
assert "ema_50" in strategy.config.overlay_indicators
|
||
|
|
assert "bb_20_20" in strategy.config.overlay_indicators
|
||
|
|
|
||
|
|
# Check subplots
|
||
|
|
assert len(strategy.config.subplot_configs) == 2
|
||
|
|
assert any(subplot.subplot_type.value == "rsi" for subplot in strategy.config.subplot_configs)
|
||
|
|
assert any(subplot.subplot_type.value == "macd" for subplot in strategy.config.subplot_configs)
|
||
|
|
|
||
|
|
# Check metadata
|
||
|
|
assert strategy.difficulty == "Intermediate"
|
||
|
|
assert strategy.risk_level == "Medium"
|
||
|
|
assert "Trending" in strategy.market_conditions
|
||
|
|
assert len(strategy.notes) > 0
|
||
|
|
assert len(strategy.references) > 0
|
||
|
|
|
||
|
|
def test_ema_crossover_validation(self):
|
||
|
|
"""Test EMA crossover strategy validation."""
|
||
|
|
strategy = create_ema_crossover_strategy()
|
||
|
|
is_valid, errors = strategy.config.validate()
|
||
|
|
|
||
|
|
# Strategy should be valid or have minimal issues
|
||
|
|
assert isinstance(is_valid, bool)
|
||
|
|
assert isinstance(errors, list)
|
||
|
|
|
||
|
|
|
||
|
|
class TestMomentumBreakoutStrategy:
|
||
|
|
"""Test Momentum Breakout strategy."""
|
||
|
|
|
||
|
|
def test_momentum_breakout_creation(self):
|
||
|
|
"""Test momentum breakout strategy creation."""
|
||
|
|
strategy = create_momentum_breakout_strategy()
|
||
|
|
|
||
|
|
assert isinstance(strategy, StrategyExample)
|
||
|
|
assert strategy.config.strategy_name == "Momentum Breakout Strategy"
|
||
|
|
assert strategy.config.strategy_type == TradingStrategy.MOMENTUM
|
||
|
|
|
||
|
|
# Check for momentum-specific indicators
|
||
|
|
assert "ema_8" in strategy.config.overlay_indicators
|
||
|
|
assert "ema_21" in strategy.config.overlay_indicators
|
||
|
|
assert "bb_20_25" in strategy.config.overlay_indicators
|
||
|
|
|
||
|
|
# Check for fast indicators
|
||
|
|
rsi_subplot = next((s for s in strategy.config.subplot_configs if s.subplot_type.value == "rsi"), None)
|
||
|
|
assert rsi_subplot is not None
|
||
|
|
assert "rsi_7" in rsi_subplot.indicators
|
||
|
|
assert "rsi_14" in rsi_subplot.indicators
|
||
|
|
|
||
|
|
# Check volume subplot
|
||
|
|
volume_subplot = next((s for s in strategy.config.subplot_configs if s.subplot_type.value == "volume"), None)
|
||
|
|
assert volume_subplot is not None
|
||
|
|
|
||
|
|
# Check metadata
|
||
|
|
assert strategy.difficulty == "Advanced"
|
||
|
|
assert strategy.risk_level == "High"
|
||
|
|
assert "Volatile" in strategy.market_conditions
|
||
|
|
|
||
|
|
|
||
|
|
class TestMeanReversionStrategy:
|
||
|
|
"""Test Mean Reversion strategy."""
|
||
|
|
|
||
|
|
def test_mean_reversion_creation(self):
|
||
|
|
"""Test mean reversion strategy creation."""
|
||
|
|
strategy = create_mean_reversion_strategy()
|
||
|
|
|
||
|
|
assert isinstance(strategy, StrategyExample)
|
||
|
|
assert strategy.config.strategy_name == "Mean Reversion Strategy"
|
||
|
|
assert strategy.config.strategy_type == TradingStrategy.MEAN_REVERSION
|
||
|
|
|
||
|
|
# Check for mean reversion indicators
|
||
|
|
assert "sma_20" in strategy.config.overlay_indicators
|
||
|
|
assert "sma_50" in strategy.config.overlay_indicators
|
||
|
|
assert "bb_20_20" in strategy.config.overlay_indicators
|
||
|
|
assert "bb_20_15" in strategy.config.overlay_indicators
|
||
|
|
|
||
|
|
# Check RSI configurations
|
||
|
|
rsi_subplot = next((s for s in strategy.config.subplot_configs if s.subplot_type.value == "rsi"), None)
|
||
|
|
assert rsi_subplot is not None
|
||
|
|
assert "rsi_14" in rsi_subplot.indicators
|
||
|
|
assert "rsi_21" in rsi_subplot.indicators
|
||
|
|
|
||
|
|
# Check metadata
|
||
|
|
assert strategy.difficulty == "Intermediate"
|
||
|
|
assert strategy.risk_level == "Medium"
|
||
|
|
assert "Sideways" in strategy.market_conditions
|
||
|
|
|
||
|
|
|
||
|
|
class TestScalpingStrategy:
|
||
|
|
"""Test Scalping strategy."""
|
||
|
|
|
||
|
|
def test_scalping_creation(self):
|
||
|
|
"""Test scalping strategy creation."""
|
||
|
|
strategy = create_scalping_strategy()
|
||
|
|
|
||
|
|
assert isinstance(strategy, StrategyExample)
|
||
|
|
assert strategy.config.strategy_name == "Scalping Strategy"
|
||
|
|
assert strategy.config.strategy_type == TradingStrategy.SCALPING
|
||
|
|
|
||
|
|
# Check fast timeframes
|
||
|
|
assert "1m" in strategy.config.timeframes
|
||
|
|
assert "5m" in strategy.config.timeframes
|
||
|
|
|
||
|
|
# Check very fast indicators
|
||
|
|
assert "ema_5" in strategy.config.overlay_indicators
|
||
|
|
assert "ema_12" in strategy.config.overlay_indicators
|
||
|
|
assert "ema_21" in strategy.config.overlay_indicators
|
||
|
|
|
||
|
|
# Check fast RSI
|
||
|
|
rsi_subplot = next((s for s in strategy.config.subplot_configs if s.subplot_type.value == "rsi"), None)
|
||
|
|
assert rsi_subplot is not None
|
||
|
|
assert "rsi_7" in rsi_subplot.indicators
|
||
|
|
|
||
|
|
# Check metadata
|
||
|
|
assert strategy.difficulty == "Advanced"
|
||
|
|
assert strategy.risk_level == "High"
|
||
|
|
assert "High Liquidity" in strategy.market_conditions
|
||
|
|
|
||
|
|
|
||
|
|
class TestSwingTradingStrategy:
|
||
|
|
"""Test Swing Trading strategy."""
|
||
|
|
|
||
|
|
def test_swing_trading_creation(self):
|
||
|
|
"""Test swing trading strategy creation."""
|
||
|
|
strategy = create_swing_trading_strategy()
|
||
|
|
|
||
|
|
assert isinstance(strategy, StrategyExample)
|
||
|
|
assert strategy.config.strategy_name == "Swing Trading Strategy"
|
||
|
|
assert strategy.config.strategy_type == TradingStrategy.SWING_TRADING
|
||
|
|
|
||
|
|
# Check longer timeframes
|
||
|
|
assert "4h" in strategy.config.timeframes
|
||
|
|
assert "1d" in strategy.config.timeframes
|
||
|
|
|
||
|
|
# Check swing trading indicators
|
||
|
|
assert "sma_20" in strategy.config.overlay_indicators
|
||
|
|
assert "sma_50" in strategy.config.overlay_indicators
|
||
|
|
assert "ema_21" in strategy.config.overlay_indicators
|
||
|
|
assert "bb_20_20" in strategy.config.overlay_indicators
|
||
|
|
|
||
|
|
# Check metadata
|
||
|
|
assert strategy.difficulty == "Beginner"
|
||
|
|
assert strategy.risk_level == "Medium"
|
||
|
|
assert "Trending" in strategy.market_conditions
|
||
|
|
|
||
|
|
|
||
|
|
class TestStrategyAccessors:
|
||
|
|
"""Test strategy accessor functions."""
|
||
|
|
|
||
|
|
def test_get_all_example_strategies(self):
|
||
|
|
"""Test getting all example strategies."""
|
||
|
|
strategies = get_all_example_strategies()
|
||
|
|
|
||
|
|
assert isinstance(strategies, dict)
|
||
|
|
assert len(strategies) == 5 # Should have 5 strategies
|
||
|
|
|
||
|
|
expected_strategies = [
|
||
|
|
"ema_crossover", "momentum_breakout", "mean_reversion",
|
||
|
|
"scalping", "swing_trading"
|
||
|
|
]
|
||
|
|
|
||
|
|
for strategy_name in expected_strategies:
|
||
|
|
assert strategy_name in strategies
|
||
|
|
assert isinstance(strategies[strategy_name], StrategyExample)
|
||
|
|
|
||
|
|
def test_get_example_strategy(self):
|
||
|
|
"""Test getting a specific example strategy."""
|
||
|
|
# Test existing strategy
|
||
|
|
ema_strategy = get_example_strategy("ema_crossover")
|
||
|
|
assert ema_strategy is not None
|
||
|
|
assert isinstance(ema_strategy, StrategyExample)
|
||
|
|
assert ema_strategy.config.strategy_name == "EMA Crossover Strategy"
|
||
|
|
|
||
|
|
# Test non-existing strategy
|
||
|
|
non_existent = get_example_strategy("non_existent_strategy")
|
||
|
|
assert non_existent is None
|
||
|
|
|
||
|
|
def test_get_strategies_by_difficulty(self):
|
||
|
|
"""Test filtering strategies by difficulty."""
|
||
|
|
# Test beginner strategies
|
||
|
|
beginner_strategies = get_strategies_by_difficulty("Beginner")
|
||
|
|
assert isinstance(beginner_strategies, list)
|
||
|
|
assert len(beginner_strategies) > 0
|
||
|
|
for strategy in beginner_strategies:
|
||
|
|
assert strategy.difficulty == "Beginner"
|
||
|
|
|
||
|
|
# Test intermediate strategies
|
||
|
|
intermediate_strategies = get_strategies_by_difficulty("Intermediate")
|
||
|
|
assert isinstance(intermediate_strategies, list)
|
||
|
|
assert len(intermediate_strategies) > 0
|
||
|
|
for strategy in intermediate_strategies:
|
||
|
|
assert strategy.difficulty == "Intermediate"
|
||
|
|
|
||
|
|
# Test advanced strategies
|
||
|
|
advanced_strategies = get_strategies_by_difficulty("Advanced")
|
||
|
|
assert isinstance(advanced_strategies, list)
|
||
|
|
assert len(advanced_strategies) > 0
|
||
|
|
for strategy in advanced_strategies:
|
||
|
|
assert strategy.difficulty == "Advanced"
|
||
|
|
|
||
|
|
# Test non-existent difficulty
|
||
|
|
empty_strategies = get_strategies_by_difficulty("Expert")
|
||
|
|
assert isinstance(empty_strategies, list)
|
||
|
|
assert len(empty_strategies) == 0
|
||
|
|
|
||
|
|
def test_get_strategies_by_risk_level(self):
|
||
|
|
"""Test filtering strategies by risk level."""
|
||
|
|
# Test medium risk strategies
|
||
|
|
medium_risk = get_strategies_by_risk_level("Medium")
|
||
|
|
assert isinstance(medium_risk, list)
|
||
|
|
assert len(medium_risk) > 0
|
||
|
|
for strategy in medium_risk:
|
||
|
|
assert strategy.risk_level == "Medium"
|
||
|
|
|
||
|
|
# Test high risk strategies
|
||
|
|
high_risk = get_strategies_by_risk_level("High")
|
||
|
|
assert isinstance(high_risk, list)
|
||
|
|
assert len(high_risk) > 0
|
||
|
|
for strategy in high_risk:
|
||
|
|
assert strategy.risk_level == "High"
|
||
|
|
|
||
|
|
# Test non-existent risk level
|
||
|
|
empty_strategies = get_strategies_by_risk_level("Ultra High")
|
||
|
|
assert isinstance(empty_strategies, list)
|
||
|
|
assert len(empty_strategies) == 0
|
||
|
|
|
||
|
|
def test_get_strategies_by_market_condition(self):
|
||
|
|
"""Test filtering strategies by market condition."""
|
||
|
|
# Test trending market strategies
|
||
|
|
trending_strategies = get_strategies_by_market_condition("Trending")
|
||
|
|
assert isinstance(trending_strategies, list)
|
||
|
|
assert len(trending_strategies) > 0
|
||
|
|
for strategy in trending_strategies:
|
||
|
|
assert "Trending" in strategy.market_conditions
|
||
|
|
|
||
|
|
# Test volatile market strategies
|
||
|
|
volatile_strategies = get_strategies_by_market_condition("Volatile")
|
||
|
|
assert isinstance(volatile_strategies, list)
|
||
|
|
assert len(volatile_strategies) > 0
|
||
|
|
for strategy in volatile_strategies:
|
||
|
|
assert "Volatile" in strategy.market_conditions
|
||
|
|
|
||
|
|
# Test sideways market strategies
|
||
|
|
sideways_strategies = get_strategies_by_market_condition("Sideways")
|
||
|
|
assert isinstance(sideways_strategies, list)
|
||
|
|
assert len(sideways_strategies) > 0
|
||
|
|
for strategy in sideways_strategies:
|
||
|
|
assert "Sideways" in strategy.market_conditions
|
||
|
|
|
||
|
|
|
||
|
|
class TestStrategyUtilities:
|
||
|
|
"""Test strategy utility functions."""
|
||
|
|
|
||
|
|
def test_get_strategy_summary(self):
|
||
|
|
"""Test getting strategy summary."""
|
||
|
|
summary = get_strategy_summary()
|
||
|
|
|
||
|
|
assert isinstance(summary, dict)
|
||
|
|
assert len(summary) == 5 # Should have 5 strategies
|
||
|
|
|
||
|
|
# Check summary structure
|
||
|
|
for strategy_name, strategy_info in summary.items():
|
||
|
|
assert isinstance(strategy_info, dict)
|
||
|
|
required_fields = [
|
||
|
|
"name", "type", "difficulty", "risk_level",
|
||
|
|
"timeframes", "market_conditions", "expected_return"
|
||
|
|
]
|
||
|
|
for field in required_fields:
|
||
|
|
assert field in strategy_info
|
||
|
|
assert isinstance(strategy_info[field], str)
|
||
|
|
|
||
|
|
# Check specific strategy
|
||
|
|
assert "ema_crossover" in summary
|
||
|
|
ema_summary = summary["ema_crossover"]
|
||
|
|
assert ema_summary["name"] == "EMA Crossover Strategy"
|
||
|
|
assert ema_summary["type"] == "day_trading"
|
||
|
|
assert ema_summary["difficulty"] == "Intermediate"
|
||
|
|
|
||
|
|
def test_export_example_strategies_to_json(self):
|
||
|
|
"""Test exporting strategies to JSON."""
|
||
|
|
json_str = export_example_strategies_to_json()
|
||
|
|
|
||
|
|
# Should be valid JSON
|
||
|
|
data = json.loads(json_str)
|
||
|
|
assert isinstance(data, dict)
|
||
|
|
assert len(data) == 5 # Should have 5 strategies
|
||
|
|
|
||
|
|
# Check structure
|
||
|
|
for strategy_name, strategy_data in data.items():
|
||
|
|
assert "config" in strategy_data
|
||
|
|
assert "metadata" in strategy_data
|
||
|
|
|
||
|
|
# Check config structure
|
||
|
|
config = strategy_data["config"]
|
||
|
|
assert "strategy_name" in config
|
||
|
|
assert "strategy_type" in config
|
||
|
|
assert "timeframes" in config
|
||
|
|
|
||
|
|
# Check metadata structure
|
||
|
|
metadata = strategy_data["metadata"]
|
||
|
|
assert "description" in metadata
|
||
|
|
assert "author" in metadata
|
||
|
|
assert "difficulty" in metadata
|
||
|
|
assert "risk_level" in metadata
|
||
|
|
|
||
|
|
# Check specific strategy
|
||
|
|
assert "ema_crossover" in data
|
||
|
|
ema_data = data["ema_crossover"]
|
||
|
|
assert ema_data["config"]["strategy_name"] == "EMA Crossover Strategy"
|
||
|
|
assert ema_data["metadata"]["difficulty"] == "Intermediate"
|
||
|
|
|
||
|
|
|
||
|
|
class TestStrategyValidation:
|
||
|
|
"""Test validation of example strategies."""
|
||
|
|
|
||
|
|
def test_all_strategies_have_required_fields(self):
|
||
|
|
"""Test that all strategies have required fields."""
|
||
|
|
strategies = get_all_example_strategies()
|
||
|
|
|
||
|
|
for strategy_name, strategy in strategies.items():
|
||
|
|
# Check StrategyExample fields
|
||
|
|
assert strategy.config is not None
|
||
|
|
assert strategy.description is not None
|
||
|
|
assert strategy.author is not None
|
||
|
|
assert strategy.difficulty in ["Beginner", "Intermediate", "Advanced"]
|
||
|
|
assert strategy.risk_level in ["Low", "Medium", "High"]
|
||
|
|
assert isinstance(strategy.market_conditions, list)
|
||
|
|
assert isinstance(strategy.notes, list)
|
||
|
|
assert isinstance(strategy.references, list)
|
||
|
|
|
||
|
|
# Check StrategyChartConfig fields
|
||
|
|
config = strategy.config
|
||
|
|
assert config.strategy_name is not None
|
||
|
|
assert config.strategy_type is not None
|
||
|
|
assert isinstance(config.timeframes, list)
|
||
|
|
assert len(config.timeframes) > 0
|
||
|
|
assert isinstance(config.overlay_indicators, list)
|
||
|
|
assert isinstance(config.subplot_configs, list)
|
||
|
|
|
||
|
|
def test_strategy_configurations_are_valid(self):
|
||
|
|
"""Test that all strategy configurations are valid."""
|
||
|
|
strategies = get_all_example_strategies()
|
||
|
|
|
||
|
|
for strategy_name, strategy in strategies.items():
|
||
|
|
# Test basic validation
|
||
|
|
is_valid, errors = strategy.config.validate()
|
||
|
|
|
||
|
|
# Should be valid or have minimal issues (like missing indicators in test environment)
|
||
|
|
assert isinstance(is_valid, bool)
|
||
|
|
assert isinstance(errors, list)
|
||
|
|
|
||
|
|
# If there are errors, they should be reasonable (like missing indicators)
|
||
|
|
if not is_valid:
|
||
|
|
for error in errors:
|
||
|
|
# Common acceptable errors in test environment
|
||
|
|
acceptable_errors = [
|
||
|
|
"not found in defaults", # Missing indicators
|
||
|
|
"not found", # Missing indicators
|
||
|
|
]
|
||
|
|
assert any(acceptable in error for acceptable in acceptable_errors), \
|
||
|
|
f"Unexpected error in {strategy_name}: {error}"
|
||
|
|
|
||
|
|
def test_strategy_timeframes_match_types(self):
|
||
|
|
"""Test that strategy timeframes match their types."""
|
||
|
|
strategies = get_all_example_strategies()
|
||
|
|
|
||
|
|
# Expected timeframes for different strategy types
|
||
|
|
expected_timeframes = {
|
||
|
|
TradingStrategy.SCALPING: ["1m", "5m"],
|
||
|
|
TradingStrategy.DAY_TRADING: ["5m", "15m", "1h", "4h"],
|
||
|
|
TradingStrategy.SWING_TRADING: ["1h", "4h", "1d"],
|
||
|
|
TradingStrategy.MOMENTUM: ["5m", "15m", "1h"],
|
||
|
|
TradingStrategy.MEAN_REVERSION: ["15m", "1h", "4h"]
|
||
|
|
}
|
||
|
|
|
||
|
|
for strategy_name, strategy in strategies.items():
|
||
|
|
strategy_type = strategy.config.strategy_type
|
||
|
|
timeframes = strategy.config.timeframes
|
||
|
|
|
||
|
|
if strategy_type in expected_timeframes:
|
||
|
|
expected = expected_timeframes[strategy_type]
|
||
|
|
# Should have some overlap with expected timeframes
|
||
|
|
overlap = set(timeframes) & set(expected)
|
||
|
|
assert len(overlap) > 0, \
|
||
|
|
f"Strategy {strategy_name} timeframes {timeframes} don't match type {strategy_type}"
|
||
|
|
|
||
|
|
|
||
|
|
class TestStrategyIntegration:
|
||
|
|
"""Test integration with other systems."""
|
||
|
|
|
||
|
|
def test_strategy_configs_work_with_validation(self):
|
||
|
|
"""Test that strategy configs work with validation system."""
|
||
|
|
from components.charts.config.validation import validate_configuration
|
||
|
|
|
||
|
|
strategies = get_all_example_strategies()
|
||
|
|
|
||
|
|
for strategy_name, strategy in strategies.items():
|
||
|
|
try:
|
||
|
|
report = validate_configuration(strategy.config)
|
||
|
|
assert hasattr(report, 'is_valid')
|
||
|
|
assert hasattr(report, 'errors')
|
||
|
|
assert hasattr(report, 'warnings')
|
||
|
|
except Exception as e:
|
||
|
|
pytest.fail(f"Validation failed for {strategy_name}: {e}")
|
||
|
|
|
||
|
|
def test_strategy_json_roundtrip(self):
|
||
|
|
"""Test JSON export and import roundtrip."""
|
||
|
|
from components.charts.config.strategy_charts import (
|
||
|
|
export_strategy_config_to_json,
|
||
|
|
load_strategy_config_from_json
|
||
|
|
)
|
||
|
|
|
||
|
|
# Test one strategy for roundtrip
|
||
|
|
original_strategy = create_ema_crossover_strategy()
|
||
|
|
|
||
|
|
# Export to JSON
|
||
|
|
json_str = export_strategy_config_to_json(original_strategy.config)
|
||
|
|
|
||
|
|
# Import from JSON
|
||
|
|
loaded_config, errors = load_strategy_config_from_json(json_str)
|
||
|
|
|
||
|
|
if loaded_config:
|
||
|
|
# Compare key fields
|
||
|
|
assert loaded_config.strategy_name == original_strategy.config.strategy_name
|
||
|
|
assert loaded_config.strategy_type == original_strategy.config.strategy_type
|
||
|
|
assert loaded_config.timeframes == original_strategy.config.timeframes
|
||
|
|
assert loaded_config.overlay_indicators == original_strategy.config.overlay_indicators
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
pytest.main([__file__])
|