testing strategies consistency after migration
- clean up test folder from old tests
This commit is contained in:
531
test/strategies/test_strategies_comparison.py
Normal file
531
test/strategies/test_strategies_comparison.py
Normal file
@@ -0,0 +1,531 @@
|
||||
"""
|
||||
Strategy Comparison Test Framework
|
||||
|
||||
Comprehensive testing for comparing original incremental strategies from cycles/IncStrategies
|
||||
with new implementations in IncrementalTrader/strategies.
|
||||
|
||||
This test framework validates:
|
||||
1. MetaTrend Strategy: IncMetaTrendStrategy vs MetaTrendStrategy
|
||||
2. Random Strategy: IncRandomStrategy vs RandomStrategy
|
||||
3. BBRS Strategy: BBRSIncrementalState vs BBRSStrategy
|
||||
|
||||
Each test validates signal generation, mathematical equivalence, and behavioral consistency.
|
||||
"""
|
||||
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
import matplotlib.dates as mdates
|
||||
from datetime import datetime
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Tuple, Any
|
||||
import os
|
||||
|
||||
# Add project paths
|
||||
sys.path.append(str(Path(__file__).parent.parent))
|
||||
sys.path.append(str(Path(__file__).parent.parent / "cycles"))
|
||||
sys.path.append(str(Path(__file__).parent.parent / "IncrementalTrader"))
|
||||
|
||||
# Import original strategies
|
||||
from cycles.IncStrategies.metatrend_strategy import IncMetaTrendStrategy
|
||||
from cycles.IncStrategies.random_strategy import IncRandomStrategy
|
||||
from cycles.IncStrategies.bbrs_incremental import BBRSIncrementalState
|
||||
|
||||
# Import new strategies
|
||||
from IncrementalTrader.strategies.metatrend import MetaTrendStrategy
|
||||
from IncrementalTrader.strategies.random import RandomStrategy
|
||||
from IncrementalTrader.strategies.bbrs import BBRSStrategy
|
||||
|
||||
class StrategyComparisonTester:
|
||||
def __init__(self, data_file: str = "data/btcusd_1-min_data.csv"):
|
||||
"""Initialize the strategy comparison tester."""
|
||||
self.data_file = data_file
|
||||
self.data = None
|
||||
self.results_dir = Path("test/results/strategies")
|
||||
self.results_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
def load_data(self, limit: int = 1000) -> bool:
|
||||
"""Load and prepare test data."""
|
||||
try:
|
||||
print(f"Loading data from {self.data_file}...")
|
||||
self.data = pd.read_csv(self.data_file)
|
||||
|
||||
# Limit data for testing
|
||||
if limit:
|
||||
self.data = self.data.head(limit)
|
||||
|
||||
print(f"Loaded {len(self.data)} data points")
|
||||
print(f"Data columns: {list(self.data.columns)}")
|
||||
print(f"Data sample:\n{self.data.head()}")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error loading data: {e}")
|
||||
return False
|
||||
|
||||
def compare_metatrend_strategies(self) -> Dict[str, Any]:
|
||||
"""Compare IncMetaTrendStrategy vs MetaTrendStrategy."""
|
||||
print("\n" + "="*80)
|
||||
print("COMPARING METATREND STRATEGIES")
|
||||
print("="*80)
|
||||
|
||||
try:
|
||||
# Initialize strategies with same parameters
|
||||
original_strategy = IncMetaTrendStrategy()
|
||||
new_strategy = MetaTrendStrategy()
|
||||
|
||||
# Track signals
|
||||
original_entry_signals = []
|
||||
new_entry_signals = []
|
||||
original_exit_signals = []
|
||||
new_exit_signals = []
|
||||
combined_original_signals = []
|
||||
combined_new_signals = []
|
||||
timestamps = []
|
||||
|
||||
# Process data
|
||||
for i, row in self.data.iterrows():
|
||||
timestamp = pd.Timestamp(row['Timestamp'], unit='s')
|
||||
ohlcv_data = {
|
||||
'open': row['Open'],
|
||||
'high': row['High'],
|
||||
'low': row['Low'],
|
||||
'close': row['Close'],
|
||||
'volume': row['Volume']
|
||||
}
|
||||
|
||||
# Update original strategy (uses update_minute_data)
|
||||
original_strategy.update_minute_data(timestamp, ohlcv_data)
|
||||
|
||||
# Update new strategy (uses process_data_point)
|
||||
new_strategy.process_data_point(timestamp, ohlcv_data)
|
||||
|
||||
# Get signals
|
||||
orig_entry = original_strategy.get_entry_signal()
|
||||
new_entry = new_strategy.get_entry_signal()
|
||||
orig_exit = original_strategy.get_exit_signal()
|
||||
new_exit = new_strategy.get_exit_signal()
|
||||
|
||||
# Store signals (both use signal_type)
|
||||
original_entry_signals.append(orig_entry.signal_type if orig_entry else "HOLD")
|
||||
new_entry_signals.append(new_entry.signal_type if new_entry else "HOLD")
|
||||
original_exit_signals.append(orig_exit.signal_type if orig_exit else "HOLD")
|
||||
new_exit_signals.append(new_exit.signal_type if new_exit else "HOLD")
|
||||
|
||||
# Combined signal logic (simplified)
|
||||
orig_signal = "BUY" if orig_entry and orig_entry.signal_type == "ENTRY" else ("SELL" if orig_exit and orig_exit.signal_type == "EXIT" else "HOLD")
|
||||
new_signal = "BUY" if new_entry and new_entry.signal_type == "ENTRY" else ("SELL" if new_exit and new_exit.signal_type == "EXIT" else "HOLD")
|
||||
|
||||
combined_original_signals.append(orig_signal)
|
||||
combined_new_signals.append(new_signal)
|
||||
timestamps.append(timestamp)
|
||||
|
||||
# Calculate consistency metrics
|
||||
entry_matches = sum(1 for o, n in zip(original_entry_signals, new_entry_signals) if o == n)
|
||||
exit_matches = sum(1 for o, n in zip(original_exit_signals, new_exit_signals) if o == n)
|
||||
combined_matches = sum(1 for o, n in zip(combined_original_signals, combined_new_signals) if o == n)
|
||||
|
||||
total_points = len(self.data)
|
||||
entry_consistency = (entry_matches / total_points) * 100
|
||||
exit_consistency = (exit_matches / total_points) * 100
|
||||
combined_consistency = (combined_matches / total_points) * 100
|
||||
|
||||
results = {
|
||||
'strategy_name': 'MetaTrend',
|
||||
'total_points': total_points,
|
||||
'entry_consistency': entry_consistency,
|
||||
'exit_consistency': exit_consistency,
|
||||
'combined_consistency': combined_consistency,
|
||||
'original_entry_signals': original_entry_signals,
|
||||
'new_entry_signals': new_entry_signals,
|
||||
'original_exit_signals': original_exit_signals,
|
||||
'new_exit_signals': new_exit_signals,
|
||||
'combined_original_signals': combined_original_signals,
|
||||
'combined_new_signals': combined_new_signals,
|
||||
'timestamps': timestamps
|
||||
}
|
||||
|
||||
print(f"Entry Signal Consistency: {entry_consistency:.2f}%")
|
||||
print(f"Exit Signal Consistency: {exit_consistency:.2f}%")
|
||||
print(f"Combined Signal Consistency: {combined_consistency:.2f}%")
|
||||
|
||||
return results
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error comparing MetaTrend strategies: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return {}
|
||||
|
||||
def compare_random_strategies(self) -> Dict[str, Any]:
|
||||
"""Compare IncRandomStrategy vs RandomStrategy."""
|
||||
print("\n" + "="*80)
|
||||
print("COMPARING RANDOM STRATEGIES")
|
||||
print("="*80)
|
||||
|
||||
try:
|
||||
# Initialize strategies with same seed for reproducibility
|
||||
# Original: IncRandomStrategy(weight, params)
|
||||
# New: RandomStrategy(name, weight, params)
|
||||
original_strategy = IncRandomStrategy(weight=1.0, params={"random_seed": 42})
|
||||
new_strategy = RandomStrategy(name="random", weight=1.0, params={"random_seed": 42})
|
||||
|
||||
# Track signals
|
||||
original_signals = []
|
||||
new_signals = []
|
||||
timestamps = []
|
||||
|
||||
# Process data
|
||||
for i, row in self.data.iterrows():
|
||||
timestamp = pd.Timestamp(row['Timestamp'], unit='s')
|
||||
ohlcv_data = {
|
||||
'open': row['Open'],
|
||||
'high': row['High'],
|
||||
'low': row['Low'],
|
||||
'close': row['Close'],
|
||||
'volume': row['Volume']
|
||||
}
|
||||
|
||||
# Update strategies
|
||||
original_strategy.update_minute_data(timestamp, ohlcv_data)
|
||||
new_strategy.process_data_point(timestamp, ohlcv_data)
|
||||
|
||||
# Get signals
|
||||
orig_signal = original_strategy.get_entry_signal() # Random strategy uses get_entry_signal
|
||||
new_signal = new_strategy.get_entry_signal()
|
||||
|
||||
# Store signals
|
||||
original_signals.append(orig_signal.signal_type if orig_signal else "HOLD")
|
||||
new_signals.append(new_signal.signal_type if new_signal else "HOLD")
|
||||
timestamps.append(timestamp)
|
||||
|
||||
# Calculate consistency metrics
|
||||
matches = sum(1 for o, n in zip(original_signals, new_signals) if o == n)
|
||||
total_points = len(self.data)
|
||||
consistency = (matches / total_points) * 100
|
||||
|
||||
results = {
|
||||
'strategy_name': 'Random',
|
||||
'total_points': total_points,
|
||||
'consistency': consistency,
|
||||
'original_signals': original_signals,
|
||||
'new_signals': new_signals,
|
||||
'timestamps': timestamps
|
||||
}
|
||||
|
||||
print(f"Signal Consistency: {consistency:.2f}%")
|
||||
|
||||
return results
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error comparing Random strategies: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return {}
|
||||
|
||||
def compare_bbrs_strategies(self) -> Dict[str, Any]:
|
||||
"""Compare BBRSIncrementalState vs BBRSStrategy."""
|
||||
print("\n" + "="*80)
|
||||
print("COMPARING BBRS STRATEGIES")
|
||||
print("="*80)
|
||||
|
||||
try:
|
||||
# Initialize strategies with same configuration
|
||||
# Original: BBRSIncrementalState(config)
|
||||
# New: BBRSStrategy(name, weight, params)
|
||||
original_config = {
|
||||
"timeframe_minutes": 60,
|
||||
"bb_period": 20,
|
||||
"rsi_period": 14,
|
||||
"bb_width": 0.05,
|
||||
"trending": {
|
||||
"bb_std_dev_multiplier": 2.5,
|
||||
"rsi_threshold": [30, 70]
|
||||
},
|
||||
"sideways": {
|
||||
"bb_std_dev_multiplier": 1.8,
|
||||
"rsi_threshold": [40, 60]
|
||||
},
|
||||
"SqueezeStrategy": True
|
||||
}
|
||||
|
||||
new_params = {
|
||||
"timeframe": "1h",
|
||||
"bb_period": 20,
|
||||
"rsi_period": 14,
|
||||
"bb_width_threshold": 0.05,
|
||||
"trending_bb_multiplier": 2.5,
|
||||
"sideways_bb_multiplier": 1.8,
|
||||
"trending_rsi_thresholds": [30, 70],
|
||||
"sideways_rsi_thresholds": [40, 60],
|
||||
"squeeze_strategy": True,
|
||||
"enable_logging": False
|
||||
}
|
||||
|
||||
original_strategy = BBRSIncrementalState(original_config)
|
||||
new_strategy = BBRSStrategy(name="bbrs", weight=1.0, params=new_params)
|
||||
|
||||
# Track signals
|
||||
original_signals = []
|
||||
new_signals = []
|
||||
timestamps = []
|
||||
|
||||
# Process data
|
||||
for i, row in self.data.iterrows():
|
||||
timestamp = pd.Timestamp(row['Timestamp'], unit='s')
|
||||
ohlcv_data = {
|
||||
'open': row['Open'],
|
||||
'high': row['High'],
|
||||
'low': row['Low'],
|
||||
'close': row['Close'],
|
||||
'volume': row['Volume']
|
||||
}
|
||||
|
||||
# Update strategies
|
||||
orig_result = original_strategy.update_minute_data(timestamp, ohlcv_data)
|
||||
new_strategy.process_data_point(timestamp, ohlcv_data)
|
||||
|
||||
# Get signals from original (returns dict with buy_signal/sell_signal)
|
||||
if orig_result and orig_result.get('buy_signal', False):
|
||||
orig_signal = "BUY"
|
||||
elif orig_result and orig_result.get('sell_signal', False):
|
||||
orig_signal = "SELL"
|
||||
else:
|
||||
orig_signal = "HOLD"
|
||||
|
||||
# Get signals from new strategy
|
||||
new_entry = new_strategy.get_entry_signal()
|
||||
new_exit = new_strategy.get_exit_signal()
|
||||
|
||||
if new_entry and new_entry.signal_type == "ENTRY":
|
||||
new_signal = "BUY"
|
||||
elif new_exit and new_exit.signal_type == "EXIT":
|
||||
new_signal = "SELL"
|
||||
else:
|
||||
new_signal = "HOLD"
|
||||
|
||||
# Store signals
|
||||
original_signals.append(orig_signal)
|
||||
new_signals.append(new_signal)
|
||||
timestamps.append(timestamp)
|
||||
|
||||
# Calculate consistency metrics
|
||||
matches = sum(1 for o, n in zip(original_signals, new_signals) if o == n)
|
||||
total_points = len(self.data)
|
||||
consistency = (matches / total_points) * 100
|
||||
|
||||
results = {
|
||||
'strategy_name': 'BBRS',
|
||||
'total_points': total_points,
|
||||
'consistency': consistency,
|
||||
'original_signals': original_signals,
|
||||
'new_signals': new_signals,
|
||||
'timestamps': timestamps
|
||||
}
|
||||
|
||||
print(f"Signal Consistency: {consistency:.2f}%")
|
||||
|
||||
return results
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error comparing BBRS strategies: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return {}
|
||||
|
||||
def generate_report(self, results: List[Dict[str, Any]]) -> None:
|
||||
"""Generate comprehensive comparison report."""
|
||||
print("\n" + "="*80)
|
||||
print("GENERATING STRATEGY COMPARISON REPORT")
|
||||
print("="*80)
|
||||
|
||||
# Create summary report
|
||||
report_file = self.results_dir / "strategy_comparison_report.txt"
|
||||
|
||||
with open(report_file, 'w', encoding='utf-8') as f:
|
||||
f.write("Strategy Comparison Report\n")
|
||||
f.write("=" * 50 + "\n\n")
|
||||
f.write(f"Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
|
||||
f.write(f"Data points tested: {results[0]['total_points'] if results else 'N/A'}\n\n")
|
||||
|
||||
for result in results:
|
||||
if not result:
|
||||
continue
|
||||
|
||||
f.write(f"Strategy: {result['strategy_name']}\n")
|
||||
f.write("-" * 30 + "\n")
|
||||
|
||||
if result['strategy_name'] == 'MetaTrend':
|
||||
f.write(f"Entry Signal Consistency: {result['entry_consistency']:.2f}%\n")
|
||||
f.write(f"Exit Signal Consistency: {result['exit_consistency']:.2f}%\n")
|
||||
f.write(f"Combined Signal Consistency: {result['combined_consistency']:.2f}%\n")
|
||||
|
||||
# Status determination
|
||||
if result['combined_consistency'] >= 95:
|
||||
status = "✅ EXCELLENT"
|
||||
elif result['combined_consistency'] >= 90:
|
||||
status = "✅ GOOD"
|
||||
elif result['combined_consistency'] >= 80:
|
||||
status = "⚠️ ACCEPTABLE"
|
||||
else:
|
||||
status = "❌ NEEDS REVIEW"
|
||||
|
||||
else:
|
||||
f.write(f"Signal Consistency: {result['consistency']:.2f}%\n")
|
||||
|
||||
# Status determination
|
||||
if result['consistency'] >= 95:
|
||||
status = "✅ EXCELLENT"
|
||||
elif result['consistency'] >= 90:
|
||||
status = "✅ GOOD"
|
||||
elif result['consistency'] >= 80:
|
||||
status = "⚠️ ACCEPTABLE"
|
||||
else:
|
||||
status = "❌ NEEDS REVIEW"
|
||||
|
||||
f.write(f"Status: {status}\n\n")
|
||||
|
||||
print(f"Report saved to: {report_file}")
|
||||
|
||||
# Generate plots for each strategy
|
||||
for result in results:
|
||||
if not result:
|
||||
continue
|
||||
self.plot_strategy_comparison(result)
|
||||
|
||||
def plot_strategy_comparison(self, result: Dict[str, Any]) -> None:
|
||||
"""Generate comparison plots for a strategy."""
|
||||
strategy_name = result['strategy_name']
|
||||
|
||||
fig, axes = plt.subplots(2, 1, figsize=(15, 10))
|
||||
fig.suptitle(f'{strategy_name} Strategy Comparison', fontsize=16, fontweight='bold')
|
||||
|
||||
timestamps = result['timestamps']
|
||||
|
||||
if strategy_name == 'MetaTrend':
|
||||
# Plot entry signals
|
||||
axes[0].plot(timestamps, [1 if s == "ENTRY" else 0 for s in result['original_entry_signals']],
|
||||
label='Original Entry', alpha=0.7, linewidth=2)
|
||||
axes[0].plot(timestamps, [1 if s == "ENTRY" else 0 for s in result['new_entry_signals']],
|
||||
label='New Entry', alpha=0.7, linewidth=2, linestyle='--')
|
||||
axes[0].set_title(f'Entry Signals - Consistency: {result["entry_consistency"]:.2f}%')
|
||||
axes[0].set_ylabel('Entry Signal')
|
||||
axes[0].legend()
|
||||
axes[0].grid(True, alpha=0.3)
|
||||
|
||||
# Plot combined signals
|
||||
signal_map = {"BUY": 1, "SELL": -1, "HOLD": 0}
|
||||
orig_combined = [signal_map[s] for s in result['combined_original_signals']]
|
||||
new_combined = [signal_map[s] for s in result['combined_new_signals']]
|
||||
|
||||
axes[1].plot(timestamps, orig_combined, label='Original Combined', alpha=0.7, linewidth=2)
|
||||
axes[1].plot(timestamps, new_combined, label='New Combined', alpha=0.7, linewidth=2, linestyle='--')
|
||||
axes[1].set_title(f'Combined Signals - Consistency: {result["combined_consistency"]:.2f}%')
|
||||
axes[1].set_ylabel('Signal (-1=SELL, 0=HOLD, 1=BUY)')
|
||||
|
||||
else:
|
||||
# For Random and BBRS strategies
|
||||
signal_map = {"BUY": 1, "SELL": -1, "HOLD": 0}
|
||||
orig_signals = [signal_map.get(s, 0) for s in result['original_signals']]
|
||||
new_signals = [signal_map.get(s, 0) for s in result['new_signals']]
|
||||
|
||||
axes[0].plot(timestamps, orig_signals, label='Original', alpha=0.7, linewidth=2)
|
||||
axes[0].plot(timestamps, new_signals, label='New', alpha=0.7, linewidth=2, linestyle='--')
|
||||
axes[0].set_title(f'Signals - Consistency: {result["consistency"]:.2f}%')
|
||||
axes[0].set_ylabel('Signal (-1=SELL, 0=HOLD, 1=BUY)')
|
||||
|
||||
# Plot difference
|
||||
diff = [o - n for o, n in zip(orig_signals, new_signals)]
|
||||
axes[1].plot(timestamps, diff, label='Difference (Original - New)', color='red', alpha=0.7)
|
||||
axes[1].set_title('Signal Differences')
|
||||
axes[1].set_ylabel('Difference')
|
||||
axes[1].axhline(y=0, color='black', linestyle='-', alpha=0.3)
|
||||
|
||||
# Format x-axis
|
||||
for ax in axes:
|
||||
ax.legend()
|
||||
ax.grid(True, alpha=0.3)
|
||||
ax.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))
|
||||
ax.xaxis.set_major_locator(mdates.HourLocator(interval=2))
|
||||
plt.setp(ax.xaxis.get_majorticklabels(), rotation=45)
|
||||
|
||||
plt.xlabel('Time')
|
||||
plt.tight_layout()
|
||||
|
||||
# Save plot
|
||||
plot_file = self.results_dir / f"{strategy_name.lower()}_strategy_comparison.png"
|
||||
plt.savefig(plot_file, dpi=300, bbox_inches='tight')
|
||||
plt.close()
|
||||
|
||||
print(f"Plot saved to: {plot_file}")
|
||||
|
||||
def main():
|
||||
"""Main test execution."""
|
||||
print("Strategy Comparison Test Framework")
|
||||
print("=" * 50)
|
||||
|
||||
# Initialize tester
|
||||
tester = StrategyComparisonTester()
|
||||
|
||||
# Load data
|
||||
if not tester.load_data(limit=1000): # Use 1000 points for testing
|
||||
print("Failed to load data. Exiting.")
|
||||
return
|
||||
|
||||
# Run comparisons
|
||||
results = []
|
||||
|
||||
# Compare MetaTrend strategies
|
||||
metatrend_result = tester.compare_metatrend_strategies()
|
||||
if metatrend_result:
|
||||
results.append(metatrend_result)
|
||||
|
||||
# Compare Random strategies
|
||||
random_result = tester.compare_random_strategies()
|
||||
if random_result:
|
||||
results.append(random_result)
|
||||
|
||||
# Compare BBRS strategies
|
||||
bbrs_result = tester.compare_bbrs_strategies()
|
||||
if bbrs_result:
|
||||
results.append(bbrs_result)
|
||||
|
||||
# Generate comprehensive report
|
||||
if results:
|
||||
tester.generate_report(results)
|
||||
|
||||
print("\n" + "="*80)
|
||||
print("STRATEGY COMPARISON SUMMARY")
|
||||
print("="*80)
|
||||
|
||||
for result in results:
|
||||
if not result:
|
||||
continue
|
||||
|
||||
strategy_name = result['strategy_name']
|
||||
|
||||
if strategy_name == 'MetaTrend':
|
||||
consistency = result['combined_consistency']
|
||||
print(f"{strategy_name}: {consistency:.2f}% consistency")
|
||||
else:
|
||||
consistency = result['consistency']
|
||||
print(f"{strategy_name}: {consistency:.2f}% consistency")
|
||||
|
||||
if consistency >= 95:
|
||||
status = "✅ EXCELLENT"
|
||||
elif consistency >= 90:
|
||||
status = "✅ GOOD"
|
||||
elif consistency >= 80:
|
||||
status = "⚠️ ACCEPTABLE"
|
||||
else:
|
||||
status = "❌ NEEDS REVIEW"
|
||||
|
||||
print(f" Status: {status}")
|
||||
|
||||
print(f"\nDetailed results saved in: {tester.results_dir}")
|
||||
else:
|
||||
print("No successful comparisons completed.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
618
test/strategies/test_strategies_comparison_2025.py
Normal file
618
test/strategies/test_strategies_comparison_2025.py
Normal file
@@ -0,0 +1,618 @@
|
||||
"""
|
||||
Enhanced Strategy Comparison Test Framework for 2025 Data
|
||||
|
||||
Comprehensive testing for comparing original incremental strategies from cycles/IncStrategies
|
||||
with new implementations in IncrementalTrader/strategies using real 2025 data.
|
||||
|
||||
Features:
|
||||
- Interactive plots using Plotly
|
||||
- CSV export of all signals
|
||||
- Detailed signal analysis
|
||||
- Performance comparison
|
||||
- Real 2025 data (Jan-Apr)
|
||||
"""
|
||||
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
import plotly.graph_objects as go
|
||||
import plotly.subplots as sp
|
||||
from plotly.offline import plot
|
||||
from datetime import datetime
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Tuple, Any
|
||||
import warnings
|
||||
warnings.filterwarnings('ignore')
|
||||
|
||||
# Add project paths
|
||||
project_root = Path(__file__).parent.parent
|
||||
sys.path.insert(0, str(project_root))
|
||||
sys.path.insert(0, str(project_root / "cycles"))
|
||||
sys.path.insert(0, str(project_root / "IncrementalTrader"))
|
||||
|
||||
# Import original strategies
|
||||
from cycles.IncStrategies.metatrend_strategy import IncMetaTrendStrategy
|
||||
from cycles.IncStrategies.random_strategy import IncRandomStrategy
|
||||
from cycles.IncStrategies.bbrs_incremental import BBRSIncrementalState
|
||||
|
||||
# Import new strategies
|
||||
from IncrementalTrader.strategies.metatrend import MetaTrendStrategy
|
||||
from IncrementalTrader.strategies.random import RandomStrategy
|
||||
from IncrementalTrader.strategies.bbrs import BBRSStrategy
|
||||
|
||||
class Enhanced2025StrategyComparison:
|
||||
"""Enhanced strategy comparison framework with interactive plots and CSV export."""
|
||||
|
||||
def __init__(self, data_file: str = "data/temp_2025_data.csv"):
|
||||
"""Initialize the comparison framework."""
|
||||
self.data_file = data_file
|
||||
self.data = None
|
||||
self.results = {}
|
||||
|
||||
# Create results directory
|
||||
self.results_dir = Path("test/results/strategies_2025")
|
||||
self.results_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
print("Enhanced 2025 Strategy Comparison Framework")
|
||||
print("=" * 60)
|
||||
|
||||
def load_data(self) -> None:
|
||||
"""Load and prepare 2025 data."""
|
||||
print(f"Loading data from {self.data_file}...")
|
||||
|
||||
self.data = pd.read_csv(self.data_file)
|
||||
|
||||
# Convert timestamp to datetime
|
||||
self.data['DateTime'] = pd.to_datetime(self.data['Timestamp'], unit='s')
|
||||
|
||||
print(f"Data loaded: {len(self.data):,} rows")
|
||||
print(f"Date range: {self.data['DateTime'].iloc[0]} to {self.data['DateTime'].iloc[-1]}")
|
||||
print(f"Columns: {list(self.data.columns)}")
|
||||
|
||||
def compare_metatrend_strategies(self) -> Dict[str, Any]:
|
||||
"""Compare IncMetaTrendStrategy vs MetaTrendStrategy with detailed analysis."""
|
||||
print("\n" + "="*80)
|
||||
print("COMPARING METATREND STRATEGIES - 2025 DATA")
|
||||
print("="*80)
|
||||
|
||||
try:
|
||||
# Initialize strategies
|
||||
original_strategy = IncMetaTrendStrategy(weight=1.0, params={})
|
||||
new_strategy = MetaTrendStrategy(name="metatrend", weight=1.0, params={})
|
||||
|
||||
# Track all signals and data
|
||||
signals_data = []
|
||||
price_data = []
|
||||
|
||||
print("Processing data points...")
|
||||
|
||||
# Process data
|
||||
for i, row in self.data.iterrows():
|
||||
if i % 10000 == 0:
|
||||
print(f"Processed {i:,} / {len(self.data):,} data points...")
|
||||
|
||||
timestamp = row['DateTime']
|
||||
ohlcv_data = {
|
||||
'open': row['Open'],
|
||||
'high': row['High'],
|
||||
'low': row['Low'],
|
||||
'close': row['Close'],
|
||||
'volume': row['Volume']
|
||||
}
|
||||
|
||||
# Update strategies
|
||||
original_strategy.update_minute_data(timestamp, ohlcv_data)
|
||||
new_strategy.process_data_point(timestamp, ohlcv_data)
|
||||
|
||||
# Get signals
|
||||
orig_entry = original_strategy.get_entry_signal()
|
||||
new_entry = new_strategy.get_entry_signal()
|
||||
orig_exit = original_strategy.get_exit_signal()
|
||||
new_exit = new_strategy.get_exit_signal()
|
||||
|
||||
# Determine combined signals
|
||||
orig_signal = "BUY" if orig_entry and orig_entry.signal_type == "ENTRY" else (
|
||||
"SELL" if orig_exit and orig_exit.signal_type == "EXIT" else "HOLD")
|
||||
new_signal = "BUY" if new_entry and new_entry.signal_type == "ENTRY" else (
|
||||
"SELL" if new_exit and new_exit.signal_type == "EXIT" else "HOLD")
|
||||
|
||||
# Store data
|
||||
signals_data.append({
|
||||
'timestamp': timestamp,
|
||||
'price': row['Close'],
|
||||
'original_entry': orig_entry.signal_type if orig_entry else "HOLD",
|
||||
'new_entry': new_entry.signal_type if new_entry else "HOLD",
|
||||
'original_exit': orig_exit.signal_type if orig_exit else "HOLD",
|
||||
'new_exit': new_exit.signal_type if new_exit else "HOLD",
|
||||
'original_combined': orig_signal,
|
||||
'new_combined': new_signal,
|
||||
'signals_match': orig_signal == new_signal
|
||||
})
|
||||
|
||||
price_data.append({
|
||||
'timestamp': timestamp,
|
||||
'open': row['Open'],
|
||||
'high': row['High'],
|
||||
'low': row['Low'],
|
||||
'close': row['Close'],
|
||||
'volume': row['Volume']
|
||||
})
|
||||
|
||||
# Convert to DataFrame
|
||||
signals_df = pd.DataFrame(signals_data)
|
||||
price_df = pd.DataFrame(price_data)
|
||||
|
||||
# Calculate statistics
|
||||
total_signals = len(signals_df)
|
||||
matching_signals = signals_df['signals_match'].sum()
|
||||
consistency = (matching_signals / total_signals) * 100
|
||||
|
||||
# Signal distribution
|
||||
orig_signal_counts = signals_df['original_combined'].value_counts()
|
||||
new_signal_counts = signals_df['new_combined'].value_counts()
|
||||
|
||||
# Save signals to CSV
|
||||
csv_file = self.results_dir / "metatrend_signals_2025.csv"
|
||||
signals_df.to_csv(csv_file, index=False, encoding='utf-8')
|
||||
|
||||
# Create interactive plot
|
||||
self.create_interactive_plot(signals_df, price_df, "MetaTrend", "metatrend_2025")
|
||||
|
||||
results = {
|
||||
'strategy': 'MetaTrend',
|
||||
'total_signals': total_signals,
|
||||
'matching_signals': matching_signals,
|
||||
'consistency_percentage': consistency,
|
||||
'original_signal_distribution': orig_signal_counts.to_dict(),
|
||||
'new_signal_distribution': new_signal_counts.to_dict(),
|
||||
'signals_dataframe': signals_df,
|
||||
'csv_file': str(csv_file)
|
||||
}
|
||||
|
||||
print(f"✅ MetaTrend Strategy Comparison Complete")
|
||||
print(f" Signal Consistency: {consistency:.2f}%")
|
||||
print(f" Total Signals: {total_signals:,}")
|
||||
print(f" Matching Signals: {matching_signals:,}")
|
||||
print(f" CSV Saved: {csv_file}")
|
||||
|
||||
return results
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error in MetaTrend comparison: {str(e)}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return {'error': str(e)}
|
||||
|
||||
def compare_random_strategies(self) -> Dict[str, Any]:
|
||||
"""Compare IncRandomStrategy vs RandomStrategy with detailed analysis."""
|
||||
print("\n" + "="*80)
|
||||
print("COMPARING RANDOM STRATEGIES - 2025 DATA")
|
||||
print("="*80)
|
||||
|
||||
try:
|
||||
# Initialize strategies with same seed for reproducibility
|
||||
original_strategy = IncRandomStrategy(weight=1.0, params={"random_seed": 42})
|
||||
new_strategy = RandomStrategy(name="random", weight=1.0, params={"random_seed": 42})
|
||||
|
||||
# Track all signals and data
|
||||
signals_data = []
|
||||
|
||||
print("Processing data points...")
|
||||
|
||||
# Process data (use subset for Random strategy to speed up)
|
||||
subset_data = self.data.iloc[::10] # Every 10th point for Random strategy
|
||||
|
||||
for i, row in subset_data.iterrows():
|
||||
if i % 1000 == 0:
|
||||
print(f"Processed {i:,} data points...")
|
||||
|
||||
timestamp = row['DateTime']
|
||||
ohlcv_data = {
|
||||
'open': row['Open'],
|
||||
'high': row['High'],
|
||||
'low': row['Low'],
|
||||
'close': row['Close'],
|
||||
'volume': row['Volume']
|
||||
}
|
||||
|
||||
# Update strategies
|
||||
original_strategy.update_minute_data(timestamp, ohlcv_data)
|
||||
new_strategy.process_data_point(timestamp, ohlcv_data)
|
||||
|
||||
# Get signals
|
||||
orig_entry = original_strategy.get_entry_signal()
|
||||
new_entry = new_strategy.get_entry_signal()
|
||||
orig_exit = original_strategy.get_exit_signal()
|
||||
new_exit = new_strategy.get_exit_signal()
|
||||
|
||||
# Determine combined signals
|
||||
orig_signal = "BUY" if orig_entry and orig_entry.signal_type == "ENTRY" else (
|
||||
"SELL" if orig_exit and orig_exit.signal_type == "EXIT" else "HOLD")
|
||||
new_signal = "BUY" if new_entry and new_entry.signal_type == "ENTRY" else (
|
||||
"SELL" if new_exit and new_exit.signal_type == "EXIT" else "HOLD")
|
||||
|
||||
# Store data
|
||||
signals_data.append({
|
||||
'timestamp': timestamp,
|
||||
'price': row['Close'],
|
||||
'original_entry': orig_entry.signal_type if orig_entry else "HOLD",
|
||||
'new_entry': new_entry.signal_type if new_entry else "HOLD",
|
||||
'original_exit': orig_exit.signal_type if orig_exit else "HOLD",
|
||||
'new_exit': new_exit.signal_type if new_exit else "HOLD",
|
||||
'original_combined': orig_signal,
|
||||
'new_combined': new_signal,
|
||||
'signals_match': orig_signal == new_signal
|
||||
})
|
||||
|
||||
# Convert to DataFrame
|
||||
signals_df = pd.DataFrame(signals_data)
|
||||
|
||||
# Calculate statistics
|
||||
total_signals = len(signals_df)
|
||||
matching_signals = signals_df['signals_match'].sum()
|
||||
consistency = (matching_signals / total_signals) * 100
|
||||
|
||||
# Save signals to CSV
|
||||
csv_file = self.results_dir / "random_signals_2025.csv"
|
||||
signals_df.to_csv(csv_file, index=False, encoding='utf-8')
|
||||
|
||||
results = {
|
||||
'strategy': 'Random',
|
||||
'total_signals': total_signals,
|
||||
'matching_signals': matching_signals,
|
||||
'consistency_percentage': consistency,
|
||||
'signals_dataframe': signals_df,
|
||||
'csv_file': str(csv_file)
|
||||
}
|
||||
|
||||
print(f"✅ Random Strategy Comparison Complete")
|
||||
print(f" Signal Consistency: {consistency:.2f}%")
|
||||
print(f" Total Signals: {total_signals:,}")
|
||||
print(f" CSV Saved: {csv_file}")
|
||||
|
||||
return results
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error in Random comparison: {str(e)}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return {'error': str(e)}
|
||||
|
||||
def compare_bbrs_strategies(self) -> Dict[str, Any]:
|
||||
"""Compare BBRSIncrementalState vs BBRSStrategy with detailed analysis."""
|
||||
print("\n" + "="*80)
|
||||
print("COMPARING BBRS STRATEGIES - 2025 DATA")
|
||||
print("="*80)
|
||||
|
||||
try:
|
||||
# Initialize strategies
|
||||
bbrs_config = {
|
||||
"bb_period": 20,
|
||||
"bb_std": 2.0,
|
||||
"rsi_period": 14,
|
||||
"volume_ma_period": 20
|
||||
}
|
||||
|
||||
original_strategy = BBRSIncrementalState(config=bbrs_config)
|
||||
new_strategy = BBRSStrategy(name="bbrs", weight=1.0, params=bbrs_config)
|
||||
|
||||
# Track all signals and data
|
||||
signals_data = []
|
||||
|
||||
print("Processing data points...")
|
||||
|
||||
# Process data
|
||||
for i, row in self.data.iterrows():
|
||||
if i % 10000 == 0:
|
||||
print(f"Processed {i:,} / {len(self.data):,} data points...")
|
||||
|
||||
timestamp = row['DateTime']
|
||||
ohlcv_data = {
|
||||
'open': row['Open'],
|
||||
'high': row['High'],
|
||||
'low': row['Low'],
|
||||
'close': row['Close'],
|
||||
'volume': row['Volume']
|
||||
}
|
||||
|
||||
# Update strategies
|
||||
orig_result = original_strategy.update_minute_data(timestamp, ohlcv_data)
|
||||
new_strategy.process_data_point(timestamp, ohlcv_data)
|
||||
|
||||
# Get signals - original returns signals in result, new uses methods
|
||||
if orig_result is not None:
|
||||
orig_buy = orig_result.get('buy_signal', False)
|
||||
orig_sell = orig_result.get('sell_signal', False)
|
||||
else:
|
||||
orig_buy = False
|
||||
orig_sell = False
|
||||
|
||||
new_entry = new_strategy.get_entry_signal()
|
||||
new_exit = new_strategy.get_exit_signal()
|
||||
new_buy = new_entry and new_entry.signal_type == "ENTRY"
|
||||
new_sell = new_exit and new_exit.signal_type == "EXIT"
|
||||
|
||||
# Determine combined signals
|
||||
orig_signal = "BUY" if orig_buy else ("SELL" if orig_sell else "HOLD")
|
||||
new_signal = "BUY" if new_buy else ("SELL" if new_sell else "HOLD")
|
||||
|
||||
# Store data
|
||||
signals_data.append({
|
||||
'timestamp': timestamp,
|
||||
'price': row['Close'],
|
||||
'original_entry': "ENTRY" if orig_buy else "HOLD",
|
||||
'new_entry': new_entry.signal_type if new_entry else "HOLD",
|
||||
'original_exit': "EXIT" if orig_sell else "HOLD",
|
||||
'new_exit': new_exit.signal_type if new_exit else "HOLD",
|
||||
'original_combined': orig_signal,
|
||||
'new_combined': new_signal,
|
||||
'signals_match': orig_signal == new_signal
|
||||
})
|
||||
|
||||
# Convert to DataFrame
|
||||
signals_df = pd.DataFrame(signals_data)
|
||||
|
||||
# Calculate statistics
|
||||
total_signals = len(signals_df)
|
||||
matching_signals = signals_df['signals_match'].sum()
|
||||
consistency = (matching_signals / total_signals) * 100
|
||||
|
||||
# Save signals to CSV
|
||||
csv_file = self.results_dir / "bbrs_signals_2025.csv"
|
||||
signals_df.to_csv(csv_file, index=False, encoding='utf-8')
|
||||
|
||||
# Create interactive plot
|
||||
self.create_interactive_plot(signals_df, self.data, "BBRS", "bbrs_2025")
|
||||
|
||||
results = {
|
||||
'strategy': 'BBRS',
|
||||
'total_signals': total_signals,
|
||||
'matching_signals': matching_signals,
|
||||
'consistency_percentage': consistency,
|
||||
'signals_dataframe': signals_df,
|
||||
'csv_file': str(csv_file)
|
||||
}
|
||||
|
||||
print(f"✅ BBRS Strategy Comparison Complete")
|
||||
print(f" Signal Consistency: {consistency:.2f}%")
|
||||
print(f" Total Signals: {total_signals:,}")
|
||||
print(f" CSV Saved: {csv_file}")
|
||||
|
||||
return results
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error in BBRS comparison: {str(e)}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return {'error': str(e)}
|
||||
|
||||
def create_interactive_plot(self, signals_df: pd.DataFrame, price_df: pd.DataFrame,
|
||||
strategy_name: str, filename: str) -> None:
|
||||
"""Create interactive Plotly chart with signals and price data."""
|
||||
print(f"Creating interactive plot for {strategy_name}...")
|
||||
|
||||
# Create subplots
|
||||
fig = sp.make_subplots(
|
||||
rows=3, cols=1,
|
||||
shared_xaxes=True,
|
||||
vertical_spacing=0.05,
|
||||
subplot_titles=(
|
||||
f'{strategy_name} Strategy - Price & Signals',
|
||||
'Signal Comparison',
|
||||
'Signal Consistency'
|
||||
),
|
||||
row_heights=[0.6, 0.2, 0.2]
|
||||
)
|
||||
|
||||
# Price chart with signals
|
||||
fig.add_trace(
|
||||
go.Scatter(
|
||||
x=price_df['timestamp'],
|
||||
y=price_df['close'],
|
||||
mode='lines',
|
||||
name='Price',
|
||||
line=dict(color='blue', width=1)
|
||||
),
|
||||
row=1, col=1
|
||||
)
|
||||
|
||||
# Add buy signals
|
||||
buy_signals_orig = signals_df[signals_df['original_combined'] == 'BUY']
|
||||
buy_signals_new = signals_df[signals_df['new_combined'] == 'BUY']
|
||||
|
||||
if len(buy_signals_orig) > 0:
|
||||
fig.add_trace(
|
||||
go.Scatter(
|
||||
x=buy_signals_orig['timestamp'],
|
||||
y=buy_signals_orig['price'],
|
||||
mode='markers',
|
||||
name='Original BUY',
|
||||
marker=dict(color='green', size=8, symbol='triangle-up')
|
||||
),
|
||||
row=1, col=1
|
||||
)
|
||||
|
||||
if len(buy_signals_new) > 0:
|
||||
fig.add_trace(
|
||||
go.Scatter(
|
||||
x=buy_signals_new['timestamp'],
|
||||
y=buy_signals_new['price'],
|
||||
mode='markers',
|
||||
name='New BUY',
|
||||
marker=dict(color='lightgreen', size=6, symbol='triangle-up')
|
||||
),
|
||||
row=1, col=1
|
||||
)
|
||||
|
||||
# Add sell signals
|
||||
sell_signals_orig = signals_df[signals_df['original_combined'] == 'SELL']
|
||||
sell_signals_new = signals_df[signals_df['new_combined'] == 'SELL']
|
||||
|
||||
if len(sell_signals_orig) > 0:
|
||||
fig.add_trace(
|
||||
go.Scatter(
|
||||
x=sell_signals_orig['timestamp'],
|
||||
y=sell_signals_orig['price'],
|
||||
mode='markers',
|
||||
name='Original SELL',
|
||||
marker=dict(color='red', size=8, symbol='triangle-down')
|
||||
),
|
||||
row=1, col=1
|
||||
)
|
||||
|
||||
if len(sell_signals_new) > 0:
|
||||
fig.add_trace(
|
||||
go.Scatter(
|
||||
x=sell_signals_new['timestamp'],
|
||||
y=sell_signals_new['price'],
|
||||
mode='markers',
|
||||
name='New SELL',
|
||||
marker=dict(color='pink', size=6, symbol='triangle-down')
|
||||
),
|
||||
row=1, col=1
|
||||
)
|
||||
|
||||
# Signal comparison chart
|
||||
signal_mapping = {'HOLD': 0, 'BUY': 1, 'SELL': -1}
|
||||
signals_df['original_numeric'] = signals_df['original_combined'].map(signal_mapping)
|
||||
signals_df['new_numeric'] = signals_df['new_combined'].map(signal_mapping)
|
||||
|
||||
fig.add_trace(
|
||||
go.Scatter(
|
||||
x=signals_df['timestamp'],
|
||||
y=signals_df['original_numeric'],
|
||||
mode='lines',
|
||||
name='Original Signals',
|
||||
line=dict(color='blue', width=2)
|
||||
),
|
||||
row=2, col=1
|
||||
)
|
||||
|
||||
fig.add_trace(
|
||||
go.Scatter(
|
||||
x=signals_df['timestamp'],
|
||||
y=signals_df['new_numeric'],
|
||||
mode='lines',
|
||||
name='New Signals',
|
||||
line=dict(color='red', width=1, dash='dash')
|
||||
),
|
||||
row=2, col=1
|
||||
)
|
||||
|
||||
# Signal consistency chart
|
||||
signals_df['consistency_numeric'] = signals_df['signals_match'].astype(int)
|
||||
|
||||
fig.add_trace(
|
||||
go.Scatter(
|
||||
x=signals_df['timestamp'],
|
||||
y=signals_df['consistency_numeric'],
|
||||
mode='lines',
|
||||
name='Signal Match',
|
||||
line=dict(color='green', width=1),
|
||||
fill='tonexty'
|
||||
),
|
||||
row=3, col=1
|
||||
)
|
||||
|
||||
# Update layout
|
||||
fig.update_layout(
|
||||
title=f'{strategy_name} Strategy Comparison - 2025 Data',
|
||||
height=800,
|
||||
showlegend=True,
|
||||
hovermode='x unified'
|
||||
)
|
||||
|
||||
# Update y-axes
|
||||
fig.update_yaxes(title_text="Price ($)", row=1, col=1)
|
||||
fig.update_yaxes(title_text="Signal", row=2, col=1, tickvals=[-1, 0, 1], ticktext=['SELL', 'HOLD', 'BUY'])
|
||||
fig.update_yaxes(title_text="Match", row=3, col=1, tickvals=[0, 1], ticktext=['No', 'Yes'])
|
||||
|
||||
# Save interactive plot
|
||||
html_file = self.results_dir / f"{filename}_interactive.html"
|
||||
plot(fig, filename=str(html_file), auto_open=False)
|
||||
|
||||
print(f" Interactive plot saved: {html_file}")
|
||||
|
||||
def generate_comprehensive_report(self) -> None:
|
||||
"""Generate comprehensive comparison report."""
|
||||
print("\n" + "="*80)
|
||||
print("GENERATING COMPREHENSIVE REPORT")
|
||||
print("="*80)
|
||||
|
||||
report_file = self.results_dir / "comprehensive_strategy_comparison_2025.md"
|
||||
|
||||
with open(report_file, 'w', encoding='utf-8') as f:
|
||||
f.write("# Comprehensive Strategy Comparison Report - 2025 Data\n\n")
|
||||
f.write(f"**Generated**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n")
|
||||
f.write(f"**Data Period**: January 1, 2025 - April 30, 2025\n")
|
||||
f.write(f"**Total Data Points**: {len(self.data):,} minute-level OHLCV records\n\n")
|
||||
|
||||
f.write("## Executive Summary\n\n")
|
||||
f.write("This report compares the signal generation consistency between original incremental strategies ")
|
||||
f.write("from `cycles/IncStrategies` and new implementations in `IncrementalTrader/strategies` ")
|
||||
f.write("using real market data from 2025.\n\n")
|
||||
|
||||
f.write("## Strategy Comparison Results\n\n")
|
||||
|
||||
for strategy_name, results in self.results.items():
|
||||
if 'error' not in results:
|
||||
f.write(f"### {results['strategy']} Strategy\n\n")
|
||||
f.write(f"- **Signal Consistency**: {results['consistency_percentage']:.2f}%\n")
|
||||
f.write(f"- **Total Signals Compared**: {results['total_signals']:,}\n")
|
||||
f.write(f"- **Matching Signals**: {results['matching_signals']:,}\n")
|
||||
f.write(f"- **CSV Export**: `{results['csv_file']}`\n\n")
|
||||
|
||||
if 'original_signal_distribution' in results:
|
||||
f.write("**Original Strategy Signal Distribution:**\n")
|
||||
for signal, count in results['original_signal_distribution'].items():
|
||||
f.write(f"- {signal}: {count:,}\n")
|
||||
f.write("\n")
|
||||
|
||||
f.write("**New Strategy Signal Distribution:**\n")
|
||||
for signal, count in results['new_signal_distribution'].items():
|
||||
f.write(f"- {signal}: {count:,}\n")
|
||||
f.write("\n")
|
||||
|
||||
f.write("## Files Generated\n\n")
|
||||
f.write("### CSV Signal Exports\n")
|
||||
for csv_file in self.results_dir.glob("*_signals_2025.csv"):
|
||||
f.write(f"- `{csv_file.name}`: Complete signal history with timestamps\n")
|
||||
|
||||
f.write("\n### Interactive Plots\n")
|
||||
for html_file in self.results_dir.glob("*_interactive.html"):
|
||||
f.write(f"- `{html_file.name}`: Interactive Plotly visualization\n")
|
||||
|
||||
f.write("\n## Conclusion\n\n")
|
||||
f.write("The strategy comparison validates the migration accuracy by comparing signal generation ")
|
||||
f.write("between original and refactored implementations. High consistency percentages indicate ")
|
||||
f.write("successful preservation of strategy behavior during the refactoring process.\n")
|
||||
|
||||
print(f"✅ Comprehensive report saved: {report_file}")
|
||||
|
||||
def run_all_comparisons(self) -> None:
|
||||
"""Run all strategy comparisons."""
|
||||
print("Starting comprehensive strategy comparison with 2025 data...")
|
||||
|
||||
# Load data
|
||||
self.load_data()
|
||||
|
||||
# Run comparisons
|
||||
self.results['metatrend'] = self.compare_metatrend_strategies()
|
||||
self.results['random'] = self.compare_random_strategies()
|
||||
self.results['bbrs'] = self.compare_bbrs_strategies()
|
||||
|
||||
# Generate report
|
||||
self.generate_comprehensive_report()
|
||||
|
||||
print("\n" + "="*80)
|
||||
print("ALL STRATEGY COMPARISONS COMPLETED")
|
||||
print("="*80)
|
||||
print(f"Results directory: {self.results_dir}")
|
||||
print("Files generated:")
|
||||
for file in sorted(self.results_dir.glob("*")):
|
||||
print(f" - {file.name}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Run the enhanced comparison
|
||||
comparison = Enhanced2025StrategyComparison()
|
||||
comparison.run_all_comparisons()
|
||||
Reference in New Issue
Block a user