import ccxt import time import pandas as pd import numpy as np import ta import matplotlib.pyplot as plt import os from dotenv import load_dotenv load_dotenv() # Connect to Binance exchange exchange = ccxt.binance({ 'apiKey': os.getenv("API_KEY"), 'secret': os.getenv("API_SECRET"), }) # Fetch historical data with pagination def fetch_full_ohlcv(symbol, timeframe, since): all_data = [] while True: try: data = exchange.fetch_ohlcv(symbol, timeframe, since=since, limit=1000) print(f"Fetched {len(data)} records from {exchange.iso8601(since)}") if not data: break all_data.extend(data) since = data[-1][0] + 1 time.sleep(0.2) except Exception as e: print(f"Error fetching data: {e}") break return all_data # Fetch historical data timeframe = '1m' symbol = 'BTC/USDC' since = exchange.parse8601('2025-04-01T00:00:00Z') historical_data = fetch_full_ohlcv(symbol, timeframe, since) # Load historical data into DataFrame df = pd.DataFrame(historical_data, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume']) df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms') virtual_balance = 50 open_trades = [] trade_log = [] def calculate_indicators(df): df['rsi'] = ta.momentum.RSIIndicator(df['close'], window=14).rsi() macd = ta.trend.MACD(df['close']) df['macd'] = macd.macd() df['signal'] = macd.macd_signal() return df df = calculate_indicators(df) RISK_PER_TRADE = 0.3 STOP_LOSS = 1 # 100% TAKE_PROFIT = 0.03 # 5% # Open new trades with investment tracking for index, row in df.iterrows(): current_price = row['close'] # Close existing trades for trade in open_trades[:]: if current_price >= trade['entry_price'] * (1 + TAKE_PROFIT) or \ current_price <= trade['entry_price'] * (1 - STOP_LOSS): open_trades.remove(trade) profit_pct = (current_price / trade['entry_price'] - 1) trade_log.append({ 'entry_time': trade['entry_time'], 'exit_time': row['timestamp'], 'profit': profit_pct * 100, 'success': profit_pct > 0, 'investment_usd': trade['size'] }) virtual_balance += trade['size'] * profit_pct # Calculate available capital for new trades allocated_capital = sum(trade['size'] for trade in open_trades) available_capital = max(0, virtual_balance - allocated_capital) # Open new trades with capital check if available_capital > 0 and len(open_trades) < 15: if row['rsi'] < 30 and row['macd'] > row['signal']: position_size = min( RISK_PER_TRADE * virtual_balance, # Normal risk amount available_capital # Never exceed remaining balance ) open_trades.append({ 'entry_time': row['timestamp'], 'entry_price': current_price, 'size': position_size, 'investment_usd': position_size # Track investment in USD }) print(open_trades) # Calculate Performance Metrics total_trades = len(trade_log) winning_trades = sum(1 for trade in trade_log if trade['success']) win_rate = (winning_trades / total_trades) * 100 if total_trades > 0 else 0 total_return = ((virtual_balance / 50) - 1) * 100 returns = [trade['profit'] for trade in trade_log] sharpe_ratio = np.mean(returns) / np.std(returns) if len(returns) > 1 else 0 # Print Results print(f""" Backtest Results: - Starting Capital: $50 USDC - Ending Balance: ${virtual_balance:.2f} USDC - Total Return: {total_return:.2f}% - Win Rate: {win_rate:.2f}% - Trades Executed: {total_trades} - Sharpe Ratio: {sharpe_ratio:.2f} """) # Visualization plt.figure(figsize=(16, 12)) # Price Chart ax1 = plt.subplot(3, 1, 1) plt.plot(df['timestamp'], df['close'], label='Price', color='black') for trade in trade_log: entry_idx = df[df['timestamp'] == trade['entry_time']].index[0] exit_idx = df[df['timestamp'] == trade['exit_time']].index[0] plt.plot([trade['entry_time'], trade['exit_time']], [df.loc[entry_idx, 'close'], df.loc[exit_idx, 'close']], color='green' if trade['success'] else 'red', alpha=0.3) plt.scatter(trade['entry_time'], df.loc[entry_idx, 'close'], marker='^', color='green', s=100) plt.scatter(trade['exit_time'], df.loc[exit_idx, 'close'], marker='v', color='red', s=100) # Annotate investment amount plt.text(trade['entry_time'], df.loc[entry_idx, 'close'], f"${trade['investment_usd']:.2f}", fontsize=8, color='blue') plt.title('Trading Strategy Performance') plt.ylabel('Price') # Plot open trades with orange and annotate investments for trade in open_trades: entry_idx = df[df['timestamp'] == trade['entry_time']].index[0] plt.plot([trade['entry_time'], df['timestamp'].iloc[-1]], [df.loc[entry_idx, 'close'], df.iloc[-1]['close']], color='orange', alpha=0.3) plt.scatter(trade['entry_time'], df.loc[entry_idx, 'close'], marker='^', color='orange', s=100) # Annotate investment amount for open trades plt.text(trade['entry_time'], df.loc[entry_idx, 'close'], f"${trade['investment_usd']:.2f}", fontsize=8, color='blue') # Indicators plt.subplot(3, 1, 2, sharex=ax1) plt.plot(df['timestamp'], df['rsi'], label='RSI', color='purple') plt.axhline(30, linestyle='--', color='green') plt.axhline(70, linestyle='--', color='red') plt.ylabel('RSI') plt.subplot(3, 1, 3, sharex=ax1) plt.plot(df['timestamp'], df['macd'], label='MACD', color='blue') plt.plot(df['timestamp'], df['signal'], label='Signal', color='orange') plt.ylabel('MACD') plt.tight_layout() plt.show()