'Missing q parameter']); exit; } $url = 'https://query1.finance.yahoo.com/v1/finance/search?q=' . urlencode($q) . '"esCount=1&newsCount=0'; $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_TIMEOUT, 10); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode !== 200 || !$response) { echo json_encode(['error' => 'Yahoo proxy failed', 'http_code' => $httpCode]); } else { echo $response; } exit; } // ─── Get JSON endpoint ────────────────────────────────────────────────────── if (isset($_GET['get_json']) && $_GET['get_json'] == '1') { header('Content-Type: application/json'); $jsonFile = __DIR__ . '/stockscreener.json'; if (file_exists($jsonFile)) { echo file_get_contents($jsonFile); } else { echo '[]'; } exit; } // ─── Save to JSON endpoint ────────────────────────────────────────────────── if (isset($_POST['save_json']) && $_POST['save_json'] === '1') { header('Content-Type: application/json'); $data = isset($_POST['data']) ? json_decode($_POST['data'], true) : null; if (!$data || !is_array($data)) { echo json_encode(['error' => 'Invalid data']); exit; } $jsonFile = __DIR__ . '/stockscreener.json'; $existing = []; if (file_exists($jsonFile)) { $existing = json_decode(file_get_contents($jsonFile), true); if (!is_array($existing)) $existing = []; } // Build a lookup of symbols already present, so we can update them // in place (e.g. a changed comment) instead of only appending new ones. $existingIndexBySymbol = []; foreach ($existing as $idx => $e) { if (!empty($e['symbol'])) { $existingIndexBySymbol[$e['symbol']] = $idx; } } $added = 0; $updated = 0; foreach ($data as $entry) { if (empty($entry['symbol'])) continue; if (isset($existingIndexBySymbol[$entry['symbol']])) { // Symbol already present — merge in any changed fields // (isin, gettex_status, comment, etc.) rather than skipping it. $idx = $existingIndexBySymbol[$entry['symbol']]; $existing[$idx] = array_merge($existing[$idx], $entry); $updated++; } else { $existing[] = $entry; $existingIndexBySymbol[$entry['symbol']] = count($existing) - 1; $added++; } } if (file_put_contents($jsonFile, json_encode($existing, JSON_PRETTY_PRINT))) { echo json_encode(['success' => true, 'count' => count($existing), 'added' => $added, 'updated' => $updated]); } else { echo json_encode(['error' => 'Failed to write file']); } exit; } // ─── Config ────────────────────────────────────────────────────────────────── $MIN_AVG_VOLUME = 70000; $MIN_PRICE = 0.50; $MAX_PRICE = 5.00; $MIN_PCT_CHANGE = 3.0; $LOOKBACK_DAYS = 20; $BREAKOUT_THRESHOLD = 1.02; $VOLUME_SPIKE = 1.2; $MAX_RSI_BREAKOUT = 80; $VOL_SURGE_MIN = 2.0; $VOL_SURGE_PRICE_MIN = 1.02; $REVERSAL_MAX_RSI = 35; $REVERSAL_MIN_VOL = 1.5; $REVERSAL_MIN_BOUNCE = 1.05; $HIGH_MOMENTUM_THRESHOLD = 15; $MOM_GAP_THRESHOLD = 10; $TICKER_BASE_URL = 'https://alceawis.de/other/extra/fetchdata/2026-05-13-Finance/2026-05-13-Stocks/process.php?symbol='; // ─── NASDAQ Cap Band Definitions ──────────────────────────────────────────── define('CAP_MEDIUM_MIN', 2_000_000_000); define('CAP_MEDIUM_MAX', 10_000_000_000); define('CAP_SMALL_MIN', 300_000_000); define('CAP_SMALL_MAX', 2_000_000_000); define('CAP_MICRO_MIN', 50_000_000); define('CAP_MICRO_MAX', 300_000_000); define('CAP_NANO_MAX', 50_000_000); function capBand(float $cap): ?string { if ($cap >= CAP_MEDIUM_MIN && $cap < CAP_MEDIUM_MAX) return 'Medium'; if ($cap >= CAP_SMALL_MIN && $cap < CAP_SMALL_MAX) return 'Small'; if ($cap >= CAP_MICRO_MIN && $cap < CAP_MICRO_MAX) return 'Micro'; if ($cap > 0 && $cap < CAP_NANO_MAX) return 'Nano'; return null; } // ─── Check if this is a streaming request ────────────────────────────────── $isStream = isset($_GET['stream']) && $_GET['stream'] === '1'; if ($isStream) { header('Content-Type: text/event-stream'); header('Cache-Control: no-cache'); header('X-Accel-Buffering: no'); ob_end_flush(); runStreamingScan(); exit; } // ─── Run streaming scan ───────────────────────────────────────────────────── function runStreamingScan() { global $MIN_AVG_VOLUME, $MIN_PRICE, $MAX_PRICE, $MIN_PCT_CHANGE, $LOOKBACK_DAYS; global $BREAKOUT_THRESHOLD, $VOLUME_SPIKE, $MAX_RSI_BREAKOUT; global $VOL_SURGE_MIN, $VOL_SURGE_PRICE_MIN; global $REVERSAL_MAX_RSI, $REVERSAL_MIN_VOL, $REVERSAL_MIN_BOUNCE; global $HIGH_MOMENTUM_THRESHOLD, $MOM_GAP_THRESHOLD; $seenSymbols = []; $stats = [ 'tv_checked' => 0, 'tv_signals' => 0, 'tv_total' => 0, 'nas_checked' => 0, 'nas_signals' => 0, 'nas_total' => 0, 'nas_skipped_price' => 0, 'nas_skipped_change' => 0, 'nas_skipped_cap' => 0, 'nasg_checked' => 0, 'nasg_signals' => 0, 'nasg_total' => 0, 'ytrend_checked' => 0, 'ytrend_signals' => 0, 'ytrend_total' => 0, ]; // ── Run 1: TradingView ── sendEvent('status', ['message' => 'Fetching TradingView volatile stocks...', 'type' => 'info']); $tvCandidates = fetchTradingViewVolatile(); runSimpleSourceScan('TradingView', 'tv', $tvCandidates, $seenSymbols, $stats); // ── Run 2: NASDAQ ── sendEvent('status', ['message' => 'Fetching NASDAQ screener data...', 'type' => 'info']); $allNasdaqStocks = fetchNasdaqScreener(); $filteredCandidates = []; $skipReasons = [ 'price_too_high' => 0, 'price_too_low' => 0, 'cap_too_big' => 0, 'pct_change_too_low' => 0, 'no_data' => 0 ]; foreach ($allNasdaqStocks as $cand) { $price = (float) str_replace(['$', ','], '', $cand['lastsale'] ?? '0'); $pctChangeRaw = str_replace('%', '', $cand['pctchange'] ?? '0'); $pctChange = (float) $pctChangeRaw; $cap = $cand['marketCap'] ?? 0; if ($price > $MAX_PRICE) { $skipReasons['price_too_high']++; continue; } if ($price < $MIN_PRICE) { $skipReasons['price_too_low']++; continue; } if ($cap > 10_000_000_000) { $skipReasons['cap_too_big']++; continue; } if (abs($pctChange) < 1.0) { $skipReasons['pct_change_too_low']++; continue; } if ($price <= 0 || $cap <= 0) { $skipReasons['no_data']++; continue; } $filteredCandidates[] = $cand; } $stats['nas_total'] = count($filteredCandidates); $stats['nas_original'] = count($allNasdaqStocks); $stats['nas_skipped_price'] = $skipReasons['price_too_high'] + $skipReasons['price_too_low']; $stats['nas_skipped_cap'] = $skipReasons['cap_too_big']; $stats['nas_skipped_change'] = $skipReasons['pct_change_too_low']; $stats['nas_skipped_total'] = array_sum($skipReasons); $totalSkipped = $stats['nas_skipped_total']; $keptPercent = $stats['nas_total'] > 0 ? round(($stats['nas_total'] / max($stats['nas_original'], 1)) * 100, 1) : 0; sendEvent('status', [ 'message' => "NASDAQ: {$stats['nas_original']} → {$stats['nas_total']} candidates (price≤$".$MAX_PRICE.", skipped {$totalSkipped}) - Price too high: {$skipReasons['price_too_high']}, Change<1%: {$skipReasons['pct_change_too_low']}, Cap: {$skipReasons['cap_too_big']}", 'type' => 'info' ]); foreach ($filteredCandidates as $idx => $cand) { $stats['nas_checked']++; $sym = $cand['symbol']; if ($idx % 5 === 0) { sendEvent('progress', [ 'source' => 'NASDAQ', 'checked' => $stats['nas_checked'], 'total' => $stats['nas_total'], 'signals' => $stats['nas_signals'], 'symbol' => $sym, 'skipped' => $stats['nas_skipped_total'], 'kept_pct' => $keptPercent ]); } if (isset($seenSymbols[$sym])) continue; $hist = fetchHistory($sym); if (!$hist) continue; if ($sig = screen($hist, $sym)) { $sig['source'] = 'NASDAQ'; $sig['marketCap'] = $cand['marketCap']; $sig['sector'] = $cand['sector']; $sig['band'] = $cand['band']; $sig['companyName'] = $cand['name'] ?? $sym; $stats['nas_signals']++; $seenSymbols[$sym] = true; sendEvent('signal', array_merge($sig, ['stats' => $stats])); } usleep(50000); } sendEvent('status', [ 'message' => "NASDAQ done: {$stats['nas_signals']} signals found", 'type' => 'info' ]); // ── Run 3: NASDAQ Top Gainers ── sendEvent('status', ['message' => 'Fetching NASDAQ top gainers...', 'type' => 'info']); $nasgCandidates = fetchNasdaqGainers(); runSimpleSourceScan('NasdaqGainers', 'nasg', $nasgCandidates, $seenSymbols, $stats); // ── Run 4: Yahoo Trending ── sendEvent('status', ['message' => 'Fetching Yahoo Finance trending symbols...', 'type' => 'info']); $ytrendCandidates = fetchYahooTrending(); runSimpleSourceScan('YahooTrending', 'ytrend', $ytrendCandidates, $seenSymbols, $stats); $totalSignals = $stats['tv_signals'] + $stats['nas_signals'] + $stats['nasg_signals'] + $stats['ytrend_signals']; sendEvent('done', [ 'message' => "✅ Complete! Found {$totalSignals} signals across 4 sources.", 'stats' => $stats ]); } // ─── Generic scan loop ────────────────────────────────────────────────────── function runSimpleSourceScan(string $sourceLabel, string $statPrefix, array $candidates, array &$seenSymbols, array &$stats) { $totalKey = "{$statPrefix}_total"; $checkedKey = "{$statPrefix}_checked"; $signalsKey = "{$statPrefix}_signals"; $stats[$totalKey] = count($candidates); sendEvent('status', [ 'message' => "Found {$stats[$totalKey]} candidates from {$sourceLabel}, screening...", 'type' => 'info' ]); foreach ($candidates as $idx => $sym) { $stats[$checkedKey]++; if ($idx % 5 === 0) { sendEvent('progress', [ 'source' => $sourceLabel, 'checked' => $stats[$checkedKey], 'total' => $stats[$totalKey], 'signals' => $stats[$signalsKey], 'symbol' => $sym ]); } if (isset($seenSymbols[$sym])) continue; $hist = fetchHistory($sym); if (!$hist) continue; if ($sig = screen($hist, $sym)) { $sig['source'] = $sourceLabel; $sig['marketCap'] = null; $sig['sector'] = null; $sig['band'] = null; $sig['companyName'] = $sym; // Will be enriched by JS if needed $stats[$signalsKey]++; $seenSymbols[$sym] = true; sendEvent('signal', array_merge($sig, ['stats' => $stats])); } usleep(50000); } sendEvent('status', [ 'message' => "{$sourceLabel} done: {$stats[$signalsKey]} signals found", 'type' => 'info' ]); } // ─── Helper to send SSE event ────────────────────────────────────────────── function sendEvent($event, $data) { echo "event: {$event}\n"; echo "data: " . json_encode($data) . "\n\n"; flush(); if (connection_aborted()) { exit; } } // ─── Discovery Functions ──────────────────────────────────────────────────── function fetchTradingViewVolatile(): array { $url = 'https://www.tradingview.com/markets/stocks-usa/market-movers-most-volatile/'; $opts = [ 'http' => [ 'header' => "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36\r\n", 'timeout' => 20 ] ]; $html = @file_get_contents($url, false, stream_context_create($opts)); if (!$html) return []; preg_match_all('/data-rowkey="([A-Z]+:[A-Z]+)"/', $html, $matches); $symbols = []; foreach ($matches[1] as $rowkey) { $parts = explode(':', $rowkey); $symbols[] = $parts[1] ?? $rowkey; } return array_values(array_unique($symbols)); } function fetchNasdaqScreener(): array { $url = 'https://api.nasdaq.com/api/screener/stocks?' . http_build_query([ 'tableonly' => 'true', 'limit' => 0, 'offset' => 0, 'download' => 'true', ]); $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Accept: application/json, text/plain, */*', 'Accept-Language: en-US,en;q=0.9', 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ' . '(KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36', 'Origin: https://www.nasdaq.com', 'Referer: https://www.nasdaq.com/market-activity/stocks/screener', ], CURLOPT_ENCODING => '', CURLOPT_TIMEOUT => 60, ]); $response = curl_exec($ch); if (curl_errno($ch) || curl_getinfo($ch, CURLINFO_HTTP_CODE) !== 200) { curl_close($ch); return []; } curl_close($ch); $data = json_decode($response, true); if (json_last_error() !== JSON_ERROR_NONE) { return []; } $allRows = $data['data']['rows'] ?? $data['data']['table']['rows'] ?? $data['rows'] ?? $data['table']['rows'] ?? []; if (empty($allRows)) return []; $wanted = ['Medium', 'Small', 'Micro', 'Nano']; $filtered = []; foreach ($allRows as $row) { $capRaw = str_replace(',', '', $row['marketCap'] ?? '0'); $cap = is_numeric($capRaw) ? (float) $capRaw : 0.0; $band = capBand($cap); if ($band !== null && in_array($band, $wanted, true)) { $filtered[] = [ 'symbol' => $row['symbol'] ?? '', 'name' => $row['name'] ?? '', 'marketCap' => $cap, 'sector' => $row['sector'] ?? '', 'lastsale' => $row['lastsale'] ?? '0', 'pctchange' => $row['pctchange'] ?? '0%', 'band' => $band, ]; } } return $filtered; } function fetchNasdaqGainers(): array { $url = 'https://api.nasdaq.com/api/quote/list-type-extended/gainers?' . http_build_query([ 'assetclass' => 'stocks', ]); $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Accept: application/json, text/plain, */*', 'Accept-Language: en-US,en;q=0.9', 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ' . '(KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36', 'Origin: https://www.nasdaq.com', 'Referer: https://www.nasdaq.com/market-activity/stocks/gainers', ], CURLOPT_ENCODING => '', CURLOPT_TIMEOUT => 30, ]); $resp = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $curlErr = curl_error($ch); curl_close($ch); if ($resp === false || $httpCode !== 200) { error_log("NASDAQ Gainers fetch failed: HTTP {$httpCode}, curl_error: {$curlErr}"); return []; } $data = json_decode($resp, true); if (json_last_error() !== JSON_ERROR_NONE) { error_log("NASDAQ Gainers JSON decode failed: " . json_last_error_msg()); return []; } $rows = $data['data']['gainers']['rows'] ?? $data['data']['rows'] ?? $data['data']['table']['rows'] ?? []; $symbols = []; foreach ($rows as $row) { if (!empty($row['symbol'])) $symbols[] = $row['symbol']; } return array_values(array_unique($symbols)); } function fetchYahooTrending(): array { $url = 'https://query1.finance.yahoo.com/v1/finance/trending/US?' . http_build_query([ 'count' => 50, ]); $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Accept: application/json', 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ' . '(KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36', ], CURLOPT_ENCODING => '', CURLOPT_TIMEOUT => 15, ]); $resp = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $curlErr = curl_error($ch); curl_close($ch); if ($resp === false || $httpCode !== 200) { error_log("Yahoo Trending fetch failed: HTTP {$httpCode}, curl_error: {$curlErr}"); return []; } $data = json_decode($resp, true); if (json_last_error() !== JSON_ERROR_NONE) { error_log("Yahoo Trending JSON decode failed: " . json_last_error_msg()); return []; } $quotes = $data['finance']['result'][0]['quotes'] ?? []; $symbols = []; foreach ($quotes as $q) { if (!empty($q['symbol'])) $symbols[] = $q['symbol']; } return array_values(array_unique($symbols)); } function fetchHistory(string $symbol): ?array { $p1 = strtotime("-90 days"); $p2 = time(); $url = "https://query1.finance.yahoo.com/v8/finance/chart/{$symbol}?period1={$p1}&period2={$p2}&interval=1d&events=history&includeAdjustedClose=true"; $opts = ['http' => ['header' => "User-Agent: Mozilla/5.0\r\n", 'timeout' => 12]]; $json = @file_get_contents($url, false, stream_context_create($opts)); if (!$json) return null; $d = json_decode($json, true); if (empty($d['chart']['result'][0])) return null; $r = $d['chart']['result'][0]; $ts = $r['timestamp'] ?? []; $q = $r['indicators']['quote'][0] ?? []; $adj = $r['indicators']['adjclose'][0]['adjclose'] ?? []; $hist = []; for ($i = 0; $i < count($ts); $i++) { if (!isset($adj[$i]) || $adj[$i] === null) continue; $hist[] = [ 'date' => date('Y-m-d', $ts[$i]), 'open' => $q['open'][$i] ?? null, 'high' => $q['high'][$i] ?? null, 'low' => $q['low'][$i] ?? null, 'close' => $adj[$i], 'volume' => $q['volume'][$i] ?? 0, ]; } return $hist; } // ─── Technical Helpers ─────────────────────────────────────────────────────── function calcRSI(array $closes, int $period = 14): float { if (count($closes) < $period + 1) return 50; $gains = $losses = []; for ($i = count($closes) - $period; $i < count($closes); $i++) { $change = $closes[$i] - $closes[$i - 1]; $gains[] = max($change, 0); $losses[] = max(-$change, 0); } $avgGain = array_sum($gains) / $period; $avgLoss = array_sum($losses) / $period; if ($avgLoss == 0) return 100; return 100 - (100 / (1 + ($avgGain / $avgLoss))); } function screen(array $h, string $sym): ?array { global $LOOKBACK_DAYS, $MIN_AVG_VOLUME, $MIN_PRICE, $MAX_PRICE; global $BREAKOUT_THRESHOLD, $VOLUME_SPIKE, $MAX_RSI_BREAKOUT; global $VOL_SURGE_MIN, $VOL_SURGE_PRICE_MIN; global $REVERSAL_MAX_RSI, $REVERSAL_MIN_VOL, $REVERSAL_MIN_BOUNCE; global $HIGH_MOMENTUM_THRESHOLD, $MOM_GAP_THRESHOLD; if (count($h) < $LOOKBACK_DAYS + 5) return null; $today = end($h); $price = $today['close']; $vol = $today['volume']; if ($price < $MIN_PRICE) return null; if ($price > $MAX_PRICE) return null; $past = array_slice($h, -($LOOKBACK_DAYS + 1), $LOOKBACK_DAYS); $high20 = max(array_column($past, 'high')); $low20 = min(array_column($past, 'low')); $avgVol = array_sum(array_column($past, 'volume')) / count($past); if ($avgVol < 5000) return null; $closes = array_column($h, 'close'); $rsi = calcRSI($closes); $threeAgo = $h[count($h) - 4]['close'] ?? $price; $mom3d = (($price - $threeAgo) / $threeAgo) * 100; if (count($h) >= 6) { $fiveDaysAgo = $h[count($h) - 6]['close'] ?? $price; $mom5d = (($price - $fiveDaysAgo) / $fiveDaysAgo) * 100; if ($mom5d >= $HIGH_MOMENTUM_THRESHOLD && $rsi < 85) { return [ 'symbol' => $sym, 'strategy' => 'HIGH-MOMENTUM', 'price' => $price, 'trigger' => $mom5d.'% in 5d', 'trigger_pct' => round($mom5d, 1), 'rsi' => round($rsi,1), 'spike' => round($vol/max($avgVol,1),1), 'vol' => $vol, 'avg_vol' => round($avgVol), 'mom3d' => round($mom3d, 1), ]; } } if ($mom3d >= $MOM_GAP_THRESHOLD && $vol < $avgVol * 0.5 && $rsi < 80) { return [ 'symbol' => $sym, 'strategy' => 'MOM-GAP', 'price' => $price, 'trigger' => $mom3d.'% in 3d (low vol)', 'trigger_pct' => round($mom3d, 1), 'rsi' => round($rsi,1), 'spike' => round($vol/max($avgVol,1),1), 'vol' => $vol, 'avg_vol' => round($avgVol), 'mom3d' => round($mom3d, 1), ]; } if ($price >= $high20 * $BREAKOUT_THRESHOLD && $vol >= $avgVol * $VOLUME_SPIKE && $rsi <= $MAX_RSI_BREAKOUT) { return [ 'symbol' => $sym, 'strategy' => 'BREAKOUT', 'price' => $price, 'trigger' => '$'.number_format($high20,2).' high', 'trigger_pct' => round((($price - $high20) / $high20) * 100, 1), 'rsi' => round($rsi,1), 'spike' => round($vol/max($avgVol,1),1), 'vol' => $vol, 'avg_vol' => round($avgVol), 'mom3d' => round($mom3d, 1), ]; } $yesterday = $h[count($h) - 2] ?? $today; $priceChange = (($price - $yesterday['close']) / $yesterday['close']); if ($vol >= $avgVol * $VOL_SURGE_MIN && $priceChange >= 0.02 && $rsi < 75) { return [ 'symbol' => $sym, 'strategy' => 'VOL-SURGE', 'price' => $price, 'trigger' => '+'.round($priceChange*100,1).'% today', 'trigger_pct' => round($priceChange*100, 1), 'rsi' => round($rsi,1), 'spike' => round($vol/max($avgVol,1),1), 'vol' => $vol, 'avg_vol' => round($avgVol), 'mom3d' => round($mom3d, 1), ]; } if ($rsi <= $REVERSAL_MAX_RSI && $vol >= $avgVol * $REVERSAL_MIN_VOL && $price >= $low20 * $REVERSAL_MIN_BOUNCE) { return [ 'symbol' => $sym, 'strategy' => 'REVERSAL', 'price' => $price, 'trigger' => 'RSI '.round($rsi,1).' + bounce', 'trigger_pct' => round((($price - $low20) / $low20) * 100, 1), 'rsi' => round($rsi,1), 'spike' => round($vol/max($avgVol,1),1), 'vol' => $vol, 'avg_vol' => round($avgVol), 'mom3d' => round($mom3d, 1), ]; } return null; } // ─── If not streaming, show the UI ────────────────────────────────────────── header('Content-Type: text/html; charset=utf-8'); ?> Momentum Screener — Real-time

🎯 Momentum Signals (live streaming)

Click "Scan Now" to start
⚡ Auto-filter: Only stocks under $x — focusing on high-momentum small caps
Ready to scan
Total Signals
0
TradingView
0
NASDAQ
0
NASDAQ Gainers
0
Yahoo Trending
0
Breakouts
0
Vol Surge
0
Reversals
0
High Mom
0
Mom Gap
0
Progress
0%
All Sources
TradingView
NASDAQ
NASDAQ Gainers
Yahoo Trending
Symbol Source Strategy Trigger Trigger % Price Volume Avg Vol Spike RSI 3d Mom Band ISIN Comment
×

Select ISIN for