Overall Statistics |
Total Orders 2723 Average Win -35.75% Average Loss 7.39% Compounding Annual Return -7.907% Drawdown 85.400% Expectancy -1.975 Start Equity 100000 End Equity 73371.46 Net Profit -26.629% Sharpe Ratio 0.211 Sortino Ratio 0.277 Probabilistic Sharpe Ratio 3.739% Loss Rate 75% Win Rate 25% Profit-Loss Ratio -4.84 Alpha -0.02 Beta 2.05 Annual Standard Deviation 0.649 Annual Variance 0.421 Information Ratio 0.1 Tracking Error 0.602 Treynor Ratio 0.067 Total Fees $2206.45 Estimated Strategy Capacity $23000.00 Lowest Capacity Asset AREB XVTYLRAYE2XX Portfolio Turnover 1.15% |
# region imports from AlgorithmImports import * # endregion from datetime import datetime, timedelta import numpy as np class StockScreener(QCAlgorithm): def Initialize(self): self.SetStartDate(2020, 11, 17) self.SetCash(100000) self.UniverseSettings.Resolution = Resolution.Daily self.UniverseSettings.Asynchronous = True # Add specific stocks from Finviz results to test data availability self.symbols = [ "DDD", # 3D Systems Corp "GILT", # Gilat Satellite Networks "HRYU", # Hanryu Holdings Inc "RRGB", # Red Robin Gourmet Burgers "SPCE", # Virgin Galactic Holdings "UNCY", # Unicycive Therapeutics "VSTE", # Vast Renewables "WDH" # Waterdrop Inc ADR ] # Test data availability for specific symbols for symbol in self.symbols: try: equity = self.AddEquity(symbol, Resolution.Daily) history = self.History(equity.Symbol, 200, Resolution.Daily) # Convert to pandas DataFrame first history_df = history.loc[str(equity.Symbol)] if len(history) > 0 else None if history_df is not None and len(history_df) > 0: self.Debug(f"Data available for {symbol}: {len(history_df)} days of history") else: self.Debug(f"No historical data available for {symbol}") except Exception as e: self.Debug(f"Error adding {symbol}: {str(e)}") # Add universe selection self.AddUniverseSelection(FundamentalUniverseSelectionModel(self.FilterStocks)) self.holdings = {} def FilterStocks(self, fundamental: List[Fundamental]) -> List[Symbol]: filtered_stocks = [] for stock in fundamental: try: # Log initial check self.Debug(f"\nAnalyzing {stock.symbol}:") self.Debug(f"Price: ${stock.price:.2f}, Volume: {stock.volume}") # Basic filters with logging if not stock.has_fundamental_data: self.Debug(f"{stock.symbol}: No fundamental data") continue if stock.price >= 7: self.Debug(f"{stock.symbol}: Price ${stock.price:.2f} >= $7") continue if stock.volume <= 50000: self.Debug(f"{stock.symbol}: Volume {stock.volume} <= 50K") continue history = self.History(stock.symbol, 200, Resolution.Daily) history_df = history.loc[str(stock.symbol)] if len(history) > 0 else None if history_df is None or len(history_df) < 200: self.Debug(f"{stock.symbol}: Insufficient history data") continue closes = history_df['close'] current_price = closes.iloc[-1] # Calculate and log technical indicators sma20 = closes[-20:].mean() sma50 = closes[-50:].mean() sma200 = closes[-200:].mean() self.Debug(f"{stock.symbol} Technical Analysis:" + f"\n Current Price: ${current_price:.2f}" + f"\n SMA20: ${sma20:.2f}" + f"\n SMA50: ${sma50:.2f}" + f"\n SMA200: ${sma200:.2f}") # Check each condition individually conditions = { "Price < SMA20": current_price < sma20, "Price > SMA50": current_price > sma50, "Price > SMA200": current_price > sma200, "Price Up": closes.iloc[-1] > closes.iloc[-2] } # Log which conditions passed/failed for condition_name, condition_met in conditions.items(): self.Debug(f"{stock.symbol} - {condition_name}: {'✓' if condition_met else '✗'}") if all(conditions.values()): filtered_stocks.append(stock.symbol) shares = int(self.Portfolio.TotalPortfolioValue * 0.1 / current_price) if shares > 0: self.MarketOrder(stock.symbol, shares) self.Debug(f"✓ ORDER PLACED: {shares} shares of {stock.symbol} at ${current_price:.2f}") except Exception as e: self.Debug(f"Error processing {stock.symbol}: {str(e)}") return filtered_stocks def OnData(self, data): pass