Cycles/test/compare_trade_timing.py

209 lines
8.5 KiB
Python
Raw Normal View History

#!/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)