Overall Statistics
Total Orders
1
Average Win
0%
Average Loss
0%
Compounding Annual Return
3.269%
Drawdown
5.600%
Expectancy
0
Start Equity
10000
End Equity
11744.51
Net Profit
17.445%
Sharpe Ratio
-0.452
Sortino Ratio
-0.45
Probabilistic Sharpe Ratio
25.345%
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
-0.022
Beta
0.109
Annual Standard Deviation
0.03
Annual Variance
0.001
Information Ratio
-0.668
Tracking Error
0.129
Treynor Ratio
-0.126
Total Fees
$1.00
Estimated Strategy Capacity
$43000000.00
Lowest Capacity Asset
NVDA RHM8UTD8DT2D
Portfolio Turnover
0.00%
Drawdown Recovery
548
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Common")

from System import *
from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Data.Market import TradeBar
from datetime import datetime, timedelta

# List of approximate NVDA earnings report dates from 2021-2025 (QC compatible format)
# Note: In a real QC algo, you might automate fetching this data.
EARNINGS_DATES = [
    datetime(2021, 2, 24).date(), datetime(2021, 5, 26).date(),
    datetime(2021, 8, 18).date(), datetime(2021, 11, 17).date(),
    datetime(2022, 2, 16).date(), datetime(2022, 5, 25).date(),
    datetime(2022, 8, 24).date(), datetime(2022, 11, 16).date(),
    datetime(2023, 2, 22).date(), datetime(2023, 5, 24).date(),
    datetime(2023, 8, 23).date(), datetime(2023, 11, 21).date(),
    datetime(2024, 2, 21).date(), datetime(2024, 5, 22).date(),
    datetime(2024, 8, 28).date(), datetime(2024, 11, 19).date(),
    datetime(2025, 2, 26).date(), datetime(2025, 5, 21).date(),
    datetime(2025, 8, 27).date(), datetime(2025, 11, 19).date()
]

class NVDAGapQC(QCAlgorithm):
    def initialize(self):
        # Set backtest time frame (5 years)
        self.set_start_date(2021, 1, 1)
        self.set_end_date(2025, 12, 31)
        self.set_cash(10000)

        # Request daily data for NVDA
        self.nvda = self.add_equity("NVDA", Resolution.MINUTE)
        self.nvda_symbol = self.nvda.symbol

        # Set commission model (QC default is 0 for Equity, adjust as needed)
        self.set_security_initializer(lambda security: security.set_fee_model(ConstantFeeModel(0)))
        
        self.entry_price = 0
        self.stop_loss_price = 0
        self.target_price = 0
        self.gap_threshold = 0.01
        self.base_risk_pct = 0.005 # Targeting sub-10% DD with 0.5% risk/trade

    def on_data(self, slice):
        # Only trade on NVDA
        if self.nvda_symbol not in slice.bars:
            return

        # Check for trade execution if an order is pending
        if self.portfolio.invested:
            return 

        # --- Earnings Filter Check ---
        current_date = self.time.date()
        if current_date in EARNINGS_DATES or (current_date - timedelta(days=1)) in EARNINGS_DATES:
            return # Skip trading near earnings

        # --- Gap Calculation ---
        # Need previous day's close price (QuantConnect History call)
        history = self.history(self.nvda_symbol, 2, Resolution.DAILY)
        if len(history) < 2:
            return
        
        prev_close = history.iloc[-2]['close']
        curr_open = slice.bars[self.nvda_symbol].open
        gap_percent = (curr_open - prev_close) / prev_close

        is_monday = self.time.weekday() == 0 # Monday is 0

        if is_monday and abs(gap_percent) > self.gap_threshold:
            # --- Dynamic Position Sizing (Low DD) ---
            # QC requires different DD monitoring via PerformanceMetrics
            # For simplicity here, we use fixed risk 
            
            # Simplified Sizing: Risk 0.5% of equity, assume $5 average stop loss
            cash = self.portfolio.cash
            risk_amount = cash * self.base_risk_pct
            size = int(risk_amount / 5) # Uses $5 stop distance approximation
            
            if size == 0: return

            # --- Trade Execution ---
            if gap_percent < 0: # Gap Down (Buy for fill)
                # Enter Long (Market order), set Stop Loss and Take Profit targets
                self.debug(f"Monday Gap Down detected. Entering Long {size} shares.")
                self.market_order(self.nvda_symbol, size)
                # In QC, OCO orders need separate methods or manual management in OnData
                
            elif gap_percent > 0: # Gap Up (Sell/Short for fill)
                self.debug(f"Monday Gap Up detected. Entering Short {size} shares.")
                self.market_order(self.nvda_symbol, -size)


    def on_order_event(self, order_event):
        # Handle order confirmations/fills here if complex OCO logic is needed
        pass

    def on_end_of_algorithm(self):
        # Calculate final Sharpe ratio and other metrics
        self.log(f"Algorithm finished.")
        # QC automatically generates performance reports with Sharpe Ratio, Drawdown etc.