#!/usr/bin/env python3 """ Performance Test Script for MA44 Strategy Tests backtesting performance on Synology DS218+ with 6GB RAM Usage: python test_ma44_performance.py [--days DAYS] [--interval INTERVAL] Example: python test_ma44_performance.py --days 7 --interval 1m """ import asyncio import argparse import time import sys import os from datetime import datetime, timedelta, timezone # Add src to path sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'src')) from data_collector.database import DatabaseManager from data_collector.indicator_engine import IndicatorEngine, IndicatorConfig from data_collector.brain import Brain from data_collector.backtester import Backtester async def run_performance_test(days: int = 7, interval: str = "1m"): """Run MA44 backtest and measure performance""" print("=" * 70) print(f"PERFORMANCE TEST: MA44 Strategy") print(f"Timeframe: {interval}") print(f"Period: Last {days} days") print(f"Hardware: Synology DS218+ (6GB RAM)") print("=" * 70) print() # Database connection (adjust these if needed) db = DatabaseManager( host=os.getenv('DB_HOST', 'localhost'), port=int(os.getenv('DB_PORT', 5432)), database=os.getenv('DB_NAME', 'btc_data'), user=os.getenv('DB_USER', 'btc_bot'), password=os.getenv('DB_PASSWORD', '') ) try: await db.connect() print("āœ“ Database connected") # Calculate date range end_date = datetime.now(timezone.utc) start_date = end_date - timedelta(days=days) print(f"āœ“ Date range: {start_date.date()} to {end_date.date()}") print(f"āœ“ Symbol: BTC") print(f"āœ“ Strategy: MA44 (44-period SMA)") print() # Check data availability async with db.acquire() as conn: count = await conn.fetchval(""" SELECT COUNT(*) FROM candles WHERE symbol = 'BTC' AND interval = $1 AND time >= $2 AND time <= $3 """, interval, start_date, end_date) print(f"šŸ“Š Data points: {count:,} {interval} candles") if count == 0: print("āŒ ERROR: No data found for this period!") print(f" Run: python -m data_collector.backfill --days {days} --intervals {interval}") return print(f" (Expected: ~{count * int(interval.replace('m','').replace('h','').replace('d',''))} minutes of data)") print() # Setup indicator configuration indicator_configs = [ IndicatorConfig("ma44", "sma", 44, [interval]) ] engine = IndicatorEngine(db, indicator_configs) brain = Brain(db, engine) backtester = Backtester(db, engine, brain) print("āš™ļø Running backtest...") print("-" * 70) # Measure execution time start_time = time.time() await backtester.run("BTC", [interval], start_date, end_date) end_time = time.time() execution_time = end_time - start_time print("-" * 70) print() # Fetch results from database async with db.acquire() as conn: latest_backtest = await conn.fetchrow(""" SELECT id, strategy, start_time, end_time, intervals, results, created_at FROM backtest_runs WHERE strategy LIKE '%ma44%' ORDER BY created_at DESC LIMIT 1 """) if latest_backtest and latest_backtest['results']: import json results = json.loads(latest_backtest['results']) print("šŸ“ˆ RESULTS:") print("=" * 70) print(f" Total Trades: {results.get('total_trades', 'N/A')}") print(f" Win Rate: {results.get('win_rate', 0):.1f}%") print(f" Win Count: {results.get('win_count', 0)}") print(f" Loss Count: {results.get('loss_count', 0)}") print(f" Total P&L: ${results.get('total_pnl', 0):.2f}") print(f" P&L Percent: {results.get('total_pnl_pct', 0):.2f}%") print(f" Initial Balance: ${results.get('initial_balance', 1000):.2f}") print(f" Final Balance: ${results.get('final_balance', 1000):.2f}") print(f" Max Drawdown: {results.get('max_drawdown', 0):.2f}%") print() print("ā±ļø PERFORMANCE:") print(f" Execution Time: {execution_time:.2f} seconds") print(f" Candles/Second: {count / execution_time:.0f}") print(f" Backtest ID: {latest_backtest['id']}") print() # Performance assessment if execution_time < 30: print("āœ… PERFORMANCE: Excellent (< 30s)") elif execution_time < 60: print("āœ… PERFORMANCE: Good (< 60s)") elif execution_time < 300: print("āš ļø PERFORMANCE: Acceptable (1-5 min)") else: print("āŒ PERFORMANCE: Slow (> 5 min) - Consider shorter periods or higher TFs") print() print("šŸ’” RECOMMENDATIONS:") if execution_time > 60: print(" • For faster results, use higher timeframes (15m, 1h, 4h)") print(" • Or reduce date range (< 7 days)") else: print(" • Hardware is sufficient for this workload") print(" • Can handle larger date ranges or multiple timeframes") else: print("āŒ ERROR: No results found in database!") print(" The backtest may have failed. Check server logs.") except Exception as e: print(f"\nāŒ ERROR: {e}") import traceback traceback.print_exc() finally: await db.disconnect() print() print("=" * 70) print("Test completed") print("=" * 70) def main(): parser = argparse.ArgumentParser(description='Test MA44 backtest performance') parser.add_argument('--days', type=int, default=7, help='Number of days to backtest (default: 7)') parser.add_argument('--interval', type=str, default='1m', help='Candle interval (default: 1m)') args = parser.parse_args() # Run the async test asyncio.run(run_performance_test(args.days, args.interval)) if __name__ == "__main__": main()