#!/usr/bin/env python3 """ Compare Trade Timing Between Strategies ======================================= This script analyzes the timing differences between the original and incremental strategies to understand why there's still a performance difference despite having similar exit conditions. """ import pandas as pd import matplotlib.pyplot as plt import numpy as np from datetime import datetime, timedelta def load_and_compare_trades(): """Load and compare trade timing between strategies.""" print("šŸ” COMPARING TRADE TIMING BETWEEN STRATEGIES") print("=" * 80) # Load original strategy trades original_file = "../results/trades_15min(15min)_ST3pct.csv" incremental_file = "../results/trades_incremental_15min(15min)_ST3pct.csv" print(f"šŸ“Š Loading original trades from: {original_file}") original_df = pd.read_csv(original_file) original_df['entry_time'] = pd.to_datetime(original_df['entry_time']) original_df['exit_time'] = pd.to_datetime(original_df['exit_time']) print(f"šŸ“Š Loading incremental trades from: {incremental_file}") incremental_df = pd.read_csv(incremental_file) incremental_df['entry_time'] = pd.to_datetime(incremental_df['entry_time']) incremental_df['exit_time'] = pd.to_datetime(incremental_df['exit_time']) # Filter to only buy signals for entry timing comparison original_buys = original_df[original_df['type'] == 'BUY'].copy() incremental_buys = incremental_df[incremental_df['type'] == 'BUY'].copy() print(f"\nšŸ“ˆ TRADE COUNT COMPARISON:") print(f"Original strategy: {len(original_buys)} buy signals") print(f"Incremental strategy: {len(incremental_buys)} buy signals") print(f"Difference: {len(incremental_buys) - len(original_buys)} more in incremental") # Compare first 10 trades print(f"\nšŸ• FIRST 10 TRADE TIMINGS:") print("-" * 60) print("Original Strategy:") for i, row in original_buys.head(10).iterrows(): print(f" {i//2 + 1:2d}. {row['entry_time']} - ${row['entry_price']:.0f}") print("\nIncremental Strategy:") for i, row in incremental_buys.head(10).iterrows(): print(f" {i//2 + 1:2d}. {row['entry_time']} - ${row['entry_price']:.0f}") # Analyze timing differences analyze_timing_differences(original_buys, incremental_buys) # Analyze price differences analyze_price_differences(original_buys, incremental_buys) return original_buys, incremental_buys def analyze_timing_differences(original_buys, incremental_buys): """Analyze the timing differences between strategies.""" print(f"\nšŸ• TIMING ANALYSIS:") print("-" * 60) # Find the earliest and latest trades orig_start = original_buys['entry_time'].min() orig_end = original_buys['entry_time'].max() inc_start = incremental_buys['entry_time'].min() inc_end = incremental_buys['entry_time'].max() print(f"Original strategy:") print(f" First trade: {orig_start}") print(f" Last trade: {orig_end}") print(f" Duration: {orig_end - orig_start}") print(f"\nIncremental strategy:") print(f" First trade: {inc_start}") print(f" Last trade: {inc_end}") print(f" Duration: {inc_end - inc_start}") # Check if incremental strategy misses early trades time_diff = inc_start - orig_start print(f"\nā° TIME DIFFERENCE:") print(f"Incremental starts {time_diff} after original") if time_diff > timedelta(hours=1): print("āš ļø SIGNIFICANT DELAY DETECTED!") print("The incremental strategy is missing early profitable trades!") # Count how many original trades happened before incremental started early_trades = original_buys[original_buys['entry_time'] < inc_start] print(f"šŸ“Š Original trades before incremental started: {len(early_trades)}") if len(early_trades) > 0: early_profits = [] for i in range(0, len(early_trades) * 2, 2): if i + 1 < len(original_buys.index): profit_pct = original_buys.iloc[i + 1]['profit_pct'] early_profits.append(profit_pct) if early_profits: avg_early_profit = np.mean(early_profits) * 100 total_early_profit = np.sum(early_profits) * 100 print(f"šŸ“ˆ Average profit of early trades: {avg_early_profit:.2f}%") print(f"šŸ“ˆ Total profit from early trades: {total_early_profit:.2f}%") def analyze_price_differences(original_buys, incremental_buys): """Analyze price differences at similar times.""" print(f"\nšŸ’° PRICE ANALYSIS:") print("-" * 60) # Find trades that happen on the same day original_buys['date'] = original_buys['entry_time'].dt.date incremental_buys['date'] = incremental_buys['entry_time'].dt.date common_dates = set(original_buys['date']) & set(incremental_buys['date']) print(f"šŸ“… Common trading dates: {len(common_dates)}") # Compare prices on common dates price_differences = [] for date in sorted(list(common_dates))[:10]: # First 10 common dates orig_trades = original_buys[original_buys['date'] == date] inc_trades = incremental_buys[incremental_buys['date'] == date] if len(orig_trades) > 0 and len(inc_trades) > 0: orig_price = orig_trades.iloc[0]['entry_price'] inc_price = inc_trades.iloc[0]['entry_price'] price_diff = ((inc_price - orig_price) / orig_price) * 100 price_differences.append(price_diff) print(f" {date}: Original ${orig_price:.0f}, Incremental ${inc_price:.0f} ({price_diff:+.2f}%)") if price_differences: avg_price_diff = np.mean(price_differences) print(f"\nšŸ“Š Average price difference: {avg_price_diff:+.2f}%") if avg_price_diff > 1: print("āš ļø Incremental strategy consistently buys at higher prices!") elif avg_price_diff < -1: print("āœ… Incremental strategy consistently buys at lower prices!") def create_timing_visualization(original_buys, incremental_buys): """Create a visualization of trade timing differences.""" print(f"\nšŸ“Š CREATING TIMING VISUALIZATION...") fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(15, 10)) # Plot 1: Trade timing over time ax1.scatter(original_buys['entry_time'], original_buys['entry_price'], alpha=0.6, label='Original Strategy', color='blue', s=30) ax1.scatter(incremental_buys['entry_time'], incremental_buys['entry_price'], alpha=0.6, label='Incremental Strategy', color='red', s=30) ax1.set_title('Trade Entry Timing Comparison') ax1.set_xlabel('Date') ax1.set_ylabel('Entry Price ($)') ax1.legend() ax1.grid(True, alpha=0.3) # Plot 2: Cumulative trade count original_buys_sorted = original_buys.sort_values('entry_time') incremental_buys_sorted = incremental_buys.sort_values('entry_time') ax2.plot(original_buys_sorted['entry_time'], range(1, len(original_buys_sorted) + 1), label='Original Strategy', color='blue', linewidth=2) ax2.plot(incremental_buys_sorted['entry_time'], range(1, len(incremental_buys_sorted) + 1), label='Incremental Strategy', color='red', linewidth=2) ax2.set_title('Cumulative Trade Count Over Time') ax2.set_xlabel('Date') ax2.set_ylabel('Cumulative Trades') ax2.legend() ax2.grid(True, alpha=0.3) plt.tight_layout() plt.savefig('../results/trade_timing_comparison.png', dpi=300, bbox_inches='tight') print("šŸ“Š Timing visualization saved to: ../results/trade_timing_comparison.png") def main(): """Main analysis function.""" try: original_buys, incremental_buys = load_and_compare_trades() create_timing_visualization(original_buys, incremental_buys) print(f"\nšŸŽÆ SUMMARY:") print("=" * 80) print("Key findings from trade timing analysis:") print("1. Check if incremental strategy starts trading later") print("2. Compare entry prices on same dates") print("3. Identify any systematic timing delays") print("4. Quantify impact of timing differences on performance") return True except Exception as e: print(f"\nāŒ Error during analysis: {e}") import traceback traceback.print_exc() return False if __name__ == "__main__": success = main() exit(0 if success else 1)