I will show you my strat implementation. Rate the strategy. Ignore the implementation itself. import numpy as np
import pandas as pd
import vectorbt as vbt
import yfinance as yf
from datetime import datetime, timedelta

class IntradayStatArb:
    def __init__(self, coin1, coin2, window=60, entry_threshold=2, exit_threshold=0, risk_per_trade=0.02, interval='5m'):
        self.coin1 = coin1
        self.coin2 = coin2
        self.window = window
        self.entry_threshold = entry_threshold
        self.exit_threshold = exit_threshold
        self.risk_per_trade = risk_per_trade
        self.interval = interval

    def fetch_data(self, period='1mo'):
        end_date = datetime.now()
        start_date = end_date - timedelta(days=30) if period == '1mo' else end_date - timedelta(weeks=1) if period == '1wk' else end_date - timedelta(days=int(period[:-1]))

        coin1_data = yf.download(f'{self.coin1}-USD', start=start_date, end=end_date, interval=self.interval)
        coin2_data = yf.download(f'{self.coin2}-USD', start=start_date, end=end_date, interval=self.interval)

        df = pd.DataFrame(index=coin1_data.index.union(coin2_data.index))
        df[self.coin1] = coin1_data['Close']
        df[self.coin2] = coin2_data['Close']
        df = df.dropna()

        df['ratio'] = df[self.coin1] / df[self.coin2]
        df['zscore'] = (df['ratio'] - df['ratio'].rolling(window=self.window).mean()) / df['ratio'].rolling(window=self.window).std()
        return df

    def generate_signals(self, data):
        long_entries = data['zscore'] < -self.entry_threshold
        long_exits = data['zscore'] >= -self.exit_threshold
        short_entries = data['zscore'] > self.entry_threshold
        short_exits = data['zscore'] <= self.exit_threshold

        return pd.DataFrame({
            'long_entries': long_entries,
            'long_exits': long_exits,
            'short_entries': short_entries,
            'short_exits': short_exits
        }, index=data.index)

    def backtest(self, initial_capital, fee_rate, period):
        data = self.fetch_data(period=period)
        signals = self.generate_signals(data)

        long_entries = signals['long_entries']
        long_exits = signals['long_exits'] | signals['short_entries']  # Exit longs if short signal appears
        short_entries = signals['short_entries']
        short_exits = signals['short_exits'] | signals['long_entries'] # Exit shorts if long signal appears
        
        # Calculate entry prices
        entry_prices = pd.DataFrame(np.nan, index=data.index, columns=[self.coin1, self.coin2])
        entry_prices.loc[long_entries, self.coin1] = data.loc[long_entries, self.coin1]  # Coin 1 entry price
        entry_prices.loc[short_entries, self.coin2] = data.loc[short_entries, self.coin2] # Coin 2 entry price


        # Calculate stop-loss prices SEPARATELY
        long_stop_prices = pd.Series(np.nan, index=data.index)
        short_stop_prices = pd.Series(np.nan, index=data.index)

        long_stop_prices.loc[long_entries] = entry_prices.loc[long_entries, self.coin1] * (1 - self.risk_per_trade)
        short_stop_prices.loc[short_entries] = entry_prices.loc[short_entries, self.coin2] * (1 + self.risk_per_trade)



        # Fixed fractional size for each trade (adjust as needed)
        size = initial_capital / 2 / data[self.coin1].iloc[0]

        coin1_pf = vbt.Portfolio.from_signals(
            data[self.coin1],
            entries=long_entries,
            exits=long_exits,  # Use combined exit signal
            sl_stop=long_stop_prices,
            init_cash=initial_capital / 2,
            fees=fee_rate,
            size=size,
            accumulate=True,
            sl_trail=False
        )

        coin2_pf = vbt.Portfolio.from_signals(
            data[self.coin2],
            entries=short_entries,
            exits=short_exits,  # Use combined exit signal
            sl_stop=short_stop_prices,
            init_cash=initial_capital / 2,
            fees=fee_rate,
            size=size,
            accumulate=True,
            sl_trail=False,
        )
            
        # Calculate combined returns and metrics
        total_returns = coin1_pf.returns() + coin2_pf.returns()
        sharpe_ratio = total_returns.mean() / total_returns.std() * np.sqrt(252)  # Annualized
        max_drawdown = (coin1_pf.drawdown().min() + coin2_pf.drawdown().min()) / 2
        
        # Get trade counts
        coin1_trade_count = coin1_pf.trades.count()
        coin2_trade_count = coin2_pf.trades.count()
        total_trades = coin1_trade_count + coin2_trade_count
        
        # Calculate win rates
        coin1_win_rate = (coin1_pf.trades.win_rate() * 100) if coin1_trade_count > 0 else 0
        coin2_win_rate = (coin2_pf.trades.win_rate() * 100) if coin2_trade_count > 0 else 0
        
        # Calculate combined win rate
        combined_win_rate = (
            (coin1_win_rate * coin1_trade_count + coin2_win_rate * coin2_trade_count) / total_trades
        ) if total_trades > 0 else 0
        
        metrics = {
            'Total Return (%)': (total_returns.sum() * 100),
            'Sharpe Ratio': sharpe_ratio,
            'Max Drawdown (%)': max_drawdown * 100,
            'Number of Trades': total_trades,
            'Win Rate (%)': combined_win_rate,
            coin1 + ' Trades': coin1_trade_count,
            coin2 + ' Trades': coin2_trade_count,
            coin1 + ' Win Rate (%)': coin1_win_rate,
            coin2 + ' Win Rate (%)': coin2_win_rate,
            'Average Return per Trade (%)': (total_returns.sum() * 100) / total_trades if total_trades > 0 else 0
        }
        
        return metrics, coin1_pf, coin2_pf, data

# Example Usage (Intraday):
coin1 = 'BTC'
coin2 = 'ETH'

strategy = IntradayStatArb(
    coin1=coin1,
    coin2=coin2,
    window=20,
    entry_threshold=2.5,
    exit_threshold=-2.5,
    risk_per_trade=0.02,
    interval='15m'     
)

metrics, coin1_pf, coin2_pf, data = strategy.backtest(initial_capital=6000, fee_rate=0.001, period='60d')

print("\nBacktest Results:")
for metric, value in metrics.items():
    print(f"{metric}: {value:.2f}")

# Plot results
import matplotlib.pyplot as plt

fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(15, 15))

# Plot z-score
data['zscore'].plot(ax=ax1)
ax1.axhline(y=strategy.entry_threshold, color='r', linestyle='--', label='Entry Threshold')
ax1.axhline(y=-strategy.entry_threshold, color='r', linestyle='--')
ax1.axhline(y=0, color='black', linestyle='-', label='Mean')
ax1.set_title('Z-Score of ' + coin1 + '/' + coin2 + ' Ratio')
ax1.legend()

# Plot price ratio
data['ratio'].plot(ax=ax2)
ax2.set_title(coin1 + '/' + coin2 + ' Price Ratio')

# Plot cumulative returns
cumulative_returns = (1 + coin1_pf.returns() + coin2_pf.returns()).cumprod()
cumulative_returns.plot(ax=ax3)
ax3.set_title('Cumulative Strategy Returns')

plt.tight_layout()
plt.show()