
import sys
import os
import pandas as pd
from universal_backtesting import UniversalBacktestingEngine

def test_grid_strategy():
    print("🚀 Testing Grid Re-entry Strategy...")
    
    engine = UniversalBacktestingEngine()
    
    # Define the Grid Re-entry Strategy
    # Logic:
    # 1. Open Long if price is below a reference 'grid_price'.
    # 2. Close if price hits Take Profit (entry + 2%).
    # 3. Re-open ONLY if price drops back to the original 'grid_price'.
    
    strategy_code = """
import pandas as pd
import numpy as np

def generate_signals(df: pd.DataFrame, params: dict) -> pd.DataFrame:
    # Parameters
    tp_pct = params.get('tp_pct', 0.02)
    # Start grid at the first close if not specified
    start_price = params.get('grid_price', df['close'].iloc[0])
    
    # State tracking
    position = 0 # 0: flat, 1: long
    entry_price = 0
    signals = []
    
    # We must iterate to maintain state
    for i, row in df.iterrows():
        close = row['close']
        high = row['high']
        low = row['low']
        sig = 0
        
        if position == 0:
            # Entry Condition: Price touches or is below grid price
            if low <= start_price:
                sig = 1 # Buy
                position = 1
                entry_price = start_price
                # Note: In real trading, we'd get filled at start_price or close
                # The engine uses 'close' for fill price by default, 
                # but for signal generation logic, we assume we got in.
        
        elif position == 1:
            # TP Condition: High hit our target
            target = entry_price * (1 + tp_pct)
            
            if high >= target:
                sig = 0 # Sell (Take Profit)
                position = 0
                # We are now flat and will wait for price to drop to start_price again
            else:
                sig = 1 # Hold
        
        signals.append(sig)
    
    df['signal'] = signals
    return df
"""

    # Parameters
    # We'll pick a grid price that we know is crossed frequently in the data
    # For BTCUSD, let's look at the data first or just use the first close
    params = {
        'stake': 1000,
        'tp_pct': 0.01, # 1% TP
        'data_file': 'data/csv/BTCUSD_1hour_ohlc.csv'
    }
    
    print("📊 Running backtest with Grid Re-entry Strategy...")
    result = engine.run_backtest(
        market='crypto',
        strategy_name='dynamic_custom',
        parameters=params,
        strategy_code=strategy_code,
        min_trades=1,
        timeframe='1hour'
    )
    
    if 'error' in result:
        print(f"❌ Test Failed: {result['error']}")
        if 'details' in result:
            print(f"Details: {result['details']}")
    else:
        print("✅ Test Passed!")
        print(f"Total Trades: {result['total_trades']}")
        print(f"Total Profit: ${result['results']['total_profit']}")
        print(f"Win Rate: {result['results']['win_rate']}%")
        
        # Verify specific trade behavior
        if len(result['trades']) >= 2:
            t1 = result['trades'][0]
            t2 = result['trades'][1]
            print("\n🔍 Trade Analysis:")
            print(f"Trade 1: {t1['action']} at {t1['price']} -> Profit: {t1['profit']}")
            print(f"Trade 2: {t2['action']} at {t2['price']} -> Profit: {t2['profit']}")
            
            # Check if we re-entered near the same price
            # Note: The engine fills at 'close' of the signal bar, so it might vary slightly
            # but the logic should hold.

if __name__ == "__main__":
    test_grid_strategy()
