Cycles/scripts/plot_old.py

272 lines
10 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
"""
Plot original strategy results from trades CSV file.
Shows buy/sell signals and portfolio value over time.
"""
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from datetime import datetime
import os
import sys
# Add project root to path
sys.path.insert(0, os.path.abspath('..'))
def load_and_process_trades(trades_file, initial_usd=10000):
"""Load trades and calculate portfolio value over time."""
# Load trades data
trades_df = pd.read_csv(trades_file)
# Convert timestamps
trades_df['entry_time'] = pd.to_datetime(trades_df['entry_time'])
trades_df['exit_time'] = pd.to_datetime(trades_df['exit_time'], errors='coerce')
# Separate buy and sell signals
buy_signals = trades_df[trades_df['type'] == 'BUY'].copy()
sell_signals = trades_df[trades_df['type'] != 'BUY'].copy()
print(f"Loaded {len(buy_signals)} buy signals and {len(sell_signals)} sell signals")
# Calculate portfolio value using compounding
portfolio_value = initial_usd
portfolio_history = []
# Create timeline from all trade times
all_times = []
all_times.extend(buy_signals['entry_time'].tolist())
all_times.extend(sell_signals['exit_time'].dropna().tolist())
all_times = sorted(set(all_times))
print(f"Processing {len(all_times)} trade events...")
# Track portfolio value at each trade
current_value = initial_usd
for sell_trade in sell_signals.itertuples():
# Apply the profit/loss from this trade
profit_pct = sell_trade.profit_pct
current_value *= (1 + profit_pct)
portfolio_history.append({
'timestamp': sell_trade.exit_time,
'portfolio_value': current_value,
'trade_type': 'SELL',
'price': sell_trade.exit_price,
'profit_pct': profit_pct * 100
})
# Convert to DataFrame
portfolio_df = pd.DataFrame(portfolio_history)
portfolio_df = portfolio_df.sort_values('timestamp').reset_index(drop=True)
# Calculate performance metrics
final_value = current_value
total_return = (final_value - initial_usd) / initial_usd * 100
num_trades = len(sell_signals)
winning_trades = len(sell_signals[sell_signals['profit_pct'] > 0])
win_rate = winning_trades / num_trades * 100 if num_trades > 0 else 0
avg_trade = sell_signals['profit_pct'].mean() * 100 if num_trades > 0 else 0
best_trade = sell_signals['profit_pct'].max() * 100 if num_trades > 0 else 0
worst_trade = sell_signals['profit_pct'].min() * 100 if num_trades > 0 else 0
performance = {
'initial_value': initial_usd,
'final_value': final_value,
'total_return': total_return,
'num_trades': num_trades,
'win_rate': win_rate,
'avg_trade': avg_trade,
'best_trade': best_trade,
'worst_trade': worst_trade
}
return buy_signals, sell_signals, portfolio_df, performance
def create_comprehensive_plot(buy_signals, sell_signals, portfolio_df, performance, save_path="original_strategy_analysis.png"):
"""Create comprehensive plot with signals and portfolio value."""
# Create figure with subplots
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(16, 12),
gridspec_kw={'height_ratios': [2, 1]})
# Plot 1: Price chart with buy/sell signals
# Get price range for the chart
all_prices = []
all_prices.extend(buy_signals['entry_price'].tolist())
all_prices.extend(sell_signals['exit_price'].tolist())
price_min = min(all_prices)
price_max = max(all_prices)
# Create a price line by connecting buy and sell points
price_timeline = []
value_timeline = []
# Combine and sort all signals by time
all_signals = []
for _, buy in buy_signals.iterrows():
all_signals.append({
'time': buy['entry_time'],
'price': buy['entry_price'],
'type': 'BUY'
})
for _, sell in sell_signals.iterrows():
all_signals.append({
'time': sell['exit_time'],
'price': sell['exit_price'],
'type': 'SELL'
})
all_signals = sorted(all_signals, key=lambda x: x['time'])
# Create price line
for signal in all_signals:
price_timeline.append(signal['time'])
value_timeline.append(signal['price'])
# Plot price line
if price_timeline:
ax1.plot(price_timeline, value_timeline, color='black', linewidth=1.5, alpha=0.7, label='Price Action')
# Plot buy signals
ax1.scatter(buy_signals['entry_time'], buy_signals['entry_price'],
color='green', marker='^', s=80, label=f"Buy Signals ({len(buy_signals)})",
zorder=5, alpha=0.9, edgecolors='white', linewidth=1)
# Plot sell signals with different colors based on profit/loss
profitable_sells = sell_signals[sell_signals['profit_pct'] > 0]
losing_sells = sell_signals[sell_signals['profit_pct'] <= 0]
if len(profitable_sells) > 0:
ax1.scatter(profitable_sells['exit_time'], profitable_sells['exit_price'],
color='blue', marker='v', s=80, label=f"Profitable Sells ({len(profitable_sells)})",
zorder=5, alpha=0.9, edgecolors='white', linewidth=1)
if len(losing_sells) > 0:
ax1.scatter(losing_sells['exit_time'], losing_sells['exit_price'],
color='red', marker='v', s=80, label=f"Losing Sells ({len(losing_sells)})",
zorder=5, alpha=0.9, edgecolors='white', linewidth=1)
ax1.set_title('Original Strategy - Trading Signals', fontsize=16, fontweight='bold')
ax1.set_ylabel('Price (USD)', fontsize=12)
ax1.legend(loc='upper left', fontsize=10)
ax1.grid(True, alpha=0.3)
# Format y-axis for price
ax1.yaxis.set_major_formatter(plt.FuncFormatter(lambda x, p: f'${x:,.0f}'))
# Plot 2: Portfolio Value Over Time
if len(portfolio_df) > 0:
ax2.plot(portfolio_df['timestamp'], portfolio_df['portfolio_value'],
color='purple', linewidth=2, label='Portfolio Value')
# Add horizontal line for initial value
ax2.axhline(y=performance['initial_value'], color='gray',
linestyle='--', alpha=0.7, label='Initial Value ($10,000)')
# Add profit/loss shading
initial_value = performance['initial_value']
profit_mask = portfolio_df['portfolio_value'] > initial_value
loss_mask = portfolio_df['portfolio_value'] < initial_value
if profit_mask.any():
ax2.fill_between(portfolio_df['timestamp'], portfolio_df['portfolio_value'], initial_value,
where=profit_mask, color='green', alpha=0.2, label='Profit Zone')
if loss_mask.any():
ax2.fill_between(portfolio_df['timestamp'], portfolio_df['portfolio_value'], initial_value,
where=loss_mask, color='red', alpha=0.2, label='Loss Zone')
ax2.set_title('Portfolio Value Over Time', fontsize=14, fontweight='bold')
ax2.set_ylabel('Portfolio Value (USD)', fontsize=12)
ax2.set_xlabel('Date', fontsize=12)
ax2.legend(loc='upper left', fontsize=10)
ax2.grid(True, alpha=0.3)
# Format y-axis for portfolio value
ax2.yaxis.set_major_formatter(plt.FuncFormatter(lambda x, p: f'${x:,.0f}'))
# Format x-axis for both plots
for ax in [ax1, ax2]:
ax.xaxis.set_major_locator(mdates.MonthLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
plt.setp(ax.xaxis.get_majorticklabels(), rotation=45)
# Add performance text box
perf_text = f"""
PERFORMANCE SUMMARY
{'='*30}
Initial Value: ${performance['initial_value']:,.0f}
Final Value: ${performance['final_value']:,.0f}
Total Return: {performance['total_return']:+.1f}%
Trading Statistics:
Number of Trades: {performance['num_trades']}
Win Rate: {performance['win_rate']:.1f}%
Average Trade: {performance['avg_trade']:+.2f}%
Best Trade: {performance['best_trade']:+.1f}%
Worst Trade: {performance['worst_trade']:+.1f}%
Period: {buy_signals['entry_time'].min().strftime('%Y-%m-%d')} to {sell_signals['exit_time'].max().strftime('%Y-%m-%d')}
"""
# Add text box to the plot
ax2.text(1.02, 0.98, perf_text, transform=ax2.transAxes, fontsize=10,
verticalalignment='top', fontfamily='monospace',
bbox=dict(boxstyle="round,pad=0.5", facecolor="lightgray", alpha=0.9))
# Adjust layout and save
plt.tight_layout()
plt.subplots_adjust(right=0.75) # Make room for text box
plt.savefig(save_path, dpi=300, bbox_inches='tight')
plt.show()
print(f"Plot saved to: {save_path}")
def main():
"""Main function to run the analysis."""
print("🚀 Starting Original Strategy Analysis")
print("=" * 50)
# File paths
trades_file = "../results/trades_15min(15min)_ST3pct.csv"
output_file = "../results/original_strategy_analysis.png"
if not os.path.exists(trades_file):
print(f"❌ Error: Trades file not found: {trades_file}")
return
try:
# Load and process trades
buy_signals, sell_signals, portfolio_df, performance = load_and_process_trades(trades_file)
# Print performance summary
print(f"\n📊 PERFORMANCE SUMMARY:")
print(f"Initial Value: ${performance['initial_value']:,.0f}")
print(f"Final Value: ${performance['final_value']:,.0f}")
print(f"Total Return: {performance['total_return']:+.1f}%")
print(f"Number of Trades: {performance['num_trades']}")
print(f"Win Rate: {performance['win_rate']:.1f}%")
print(f"Average Trade: {performance['avg_trade']:+.2f}%")
# Create plot
create_comprehensive_plot(buy_signals, sell_signals, portfolio_df, performance, output_file)
print(f"\n✅ Analysis completed successfully!")
except Exception as e:
print(f"❌ Error during analysis: {e}")
import traceback
traceback.print_exc()
if __name__ == "__main__":
main()