├── JIT-SprayedROP.pdf ├── README.md └── stock_research ├── analyst_consensus.py ├── analyze_analysts.csv ├── analyze_analysts.py ├── analyze_govtraders.py ├── esg_analyze.py ├── esg_dependence_results.csv ├── esg_returns_data.csv ├── etf_sector_graph.html ├── etf_sectors.py ├── etfs.txt ├── individuals.txt ├── insider_correlate.py ├── symbols.txt ├── test.txt ├── top_analysts.py └── top_analysts.txt /JIT-SprayedROP.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcdannyboy/Research/3255f1cbe61013905f4b140a06c2f4380fe4a723/JIT-SprayedROP.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Research 2 | General Research Repository - Only updated when I feel like it 3 | 4 | 1. JIT-Sprayed ROP Attacks - https://github.com/bcdannyboy/Research/blob/master/JIT-SprayedROP.pdf 5 | 2. stock_research - a collection of stock analysis scripts and data -------------------------------------------------------------------------------- /stock_research/analyst_consensus.py: -------------------------------------------------------------------------------- 1 | import os 2 | import requests 3 | import argparse 4 | import urllib.parse 5 | from datetime import datetime, timedelta 6 | from tqdm import tqdm 7 | import yfinance as yf 8 | from dotenv import load_dotenv 9 | 10 | # Load the API key from the .env file 11 | load_dotenv() 12 | API_KEY = os.getenv("FMP_API_KEY") 13 | 14 | # Function to fetch the latest price targets for a given analyst within the last month 15 | def get_latest_price_targets(analyst_name): 16 | # Encode the analyst name for URL 17 | encoded_name = urllib.parse.quote(analyst_name) 18 | url = f"https://financialmodelingprep.com/api/v4/price-target-analyst-name?name={encoded_name}&apikey={API_KEY}" 19 | 20 | response = requests.get(url) 21 | if response.status_code == 200: 22 | data = response.json() 23 | if data: 24 | # Filter data to only those within the last month 25 | one_month_ago = datetime.utcnow() - timedelta(days=30) 26 | data = [item for item in data if datetime.strptime(item['publishedDate'], '%Y-%m-%dT%H:%M:%S.%fZ') >= one_month_ago] 27 | if not data: 28 | return None 29 | # Sort data by publishedDate descending 30 | data.sort(key=lambda x: x['publishedDate'], reverse=True) 31 | # For each symbol, keep only the latest alert 32 | latest_alerts = {} 33 | for item in data: 34 | symbol = item['symbol'] 35 | if symbol not in latest_alerts: 36 | latest_alerts[symbol] = item 37 | # Return the list of latest alerts per ticker 38 | return list(latest_alerts.values()) 39 | else: 40 | return None 41 | else: 42 | raise Exception(f"Error fetching data for {analyst_name}: HTTP {response.status_code}") 43 | 44 | # Function to get current stock price using yfinance 45 | def get_current_stock_price(symbol): 46 | try: 47 | stock = yf.Ticker(symbol) 48 | data = stock.history(period='1d') 49 | if not data.empty: 50 | current_price = data['Close'].iloc[-1] 51 | return current_price 52 | else: 53 | return None 54 | except Exception: 55 | return None 56 | 57 | # Main function to process the input file and print the latest alerts 58 | def fetch_latest_alerts(input_file): 59 | # Read analyst names from the input file 60 | try: 61 | with open(input_file, 'r') as f: 62 | analyst_names = [line.strip() for line in f if line.strip()] 63 | except FileNotFoundError: 64 | print(f"Input file {input_file} not found.") 65 | return 66 | 67 | if not analyst_names: 68 | print("No analyst names found in the input file.") 69 | return 70 | 71 | print(f"Fetching latest price target alerts for {len(analyst_names)} analysts...\n") 72 | 73 | # Iterate over the analyst names and fetch their latest alerts 74 | for analyst_name in tqdm(analyst_names, desc="Processing analysts"): 75 | try: 76 | latest_alerts = get_latest_price_targets(analyst_name) 77 | if latest_alerts: 78 | for alert in latest_alerts: 79 | # Extract relevant information 80 | symbol = alert.get('symbol', 'N/A') 81 | published_date = alert.get('publishedDate', 'N/A') 82 | news_url = alert.get('newsURL', 'N/A') 83 | news_title = alert.get('newsTitle', 'N/A') 84 | price_target = alert.get('priceTarget', 'N/A') 85 | price_when_posted = alert.get('priceWhenPosted', 'N/A') 86 | analyst_company = alert.get('analystCompany', 'N/A') 87 | news_publisher = alert.get('newsPublisher', 'N/A') 88 | 89 | # Convert published_date to readable format 90 | if published_date != 'N/A': 91 | published_date_dt = datetime.strptime(published_date, '%Y-%m-%dT%H:%M:%S.%fZ') 92 | published_date_str = published_date_dt.strftime('%Y-%m-%d %H:%M:%S') 93 | else: 94 | published_date_str = 'N/A' 95 | 96 | # Fetch current stock price using yfinance 97 | current_price = get_current_stock_price(symbol) 98 | if current_price is not None and price_target is not None: 99 | # Calculate delta between current price and price target 100 | delta = price_target - current_price 101 | delta_percentage = (delta / current_price) * 100 102 | delta_str = f"{delta:.2f} ({delta_percentage:.2f}%)" 103 | current_price_str = f"{current_price:.2f}" 104 | else: 105 | current_price_str = 'N/A' 106 | delta_str = 'N/A' 107 | 108 | # Print the latest alert information 109 | print(f"Analyst: {analyst_name}") 110 | print(f"Company: {analyst_company}") 111 | print(f"Symbol: {symbol}") 112 | print(f"Published Date: {published_date_str}") 113 | print(f"Price Target: {price_target}") 114 | print(f"Current Price: {current_price_str}") 115 | print(f"Delta to Price Target: {delta_str}") 116 | print(f"News Title: {news_title}") 117 | print(f"News URL: {news_url}") 118 | print(f"News Publisher: {news_publisher}") 119 | print("-" * 80) 120 | else: 121 | print(f"No recent price target data available for analyst: {analyst_name}") 122 | print("-" * 80) 123 | except Exception as e: 124 | print(f"Error processing analyst {analyst_name}: {e}") 125 | print("-" * 80) 126 | -------------------------------------------------------------------------------- /stock_research/analyze_analysts.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import argparse 4 | import requests 5 | import pandas as pd 6 | import yfinance as yf 7 | from dotenv import load_dotenv 8 | import plotly.express as px 9 | from datetime import timedelta 10 | import time 11 | from tqdm import tqdm 12 | from concurrent.futures import ThreadPoolExecutor, as_completed 13 | from threading import Lock 14 | 15 | # Load the API key from the .env file 16 | load_dotenv() 17 | API_KEY = os.getenv("FMP_API_KEY") 18 | 19 | # Maximum number of requests per minute 20 | MAX_REQUESTS_PER_MINUTE = 500 21 | 22 | # Lock for thread-safe operations 23 | lock = Lock() 24 | 25 | # Global variables for rate limiting 26 | request_times = [] 27 | 28 | def rate_limited_request(url): 29 | global request_times 30 | current_time = time.time() 31 | with lock: 32 | # Remove timestamps older than 60 seconds 33 | request_times = [t for t in request_times if current_time - t < 60] 34 | 35 | if len(request_times) >= MAX_REQUESTS_PER_MINUTE: 36 | # Sleep until we can make a new request 37 | sleep_time = 60 - (current_time - request_times[0]) + 0.1 38 | time.sleep(sleep_time) 39 | # Update current time and request_times after sleep 40 | current_time = time.time() 41 | request_times = [t for t in request_times if current_time - t < 60] 42 | 43 | request_times.append(current_time) 44 | 45 | # Make the actual API request 46 | response = requests.get(url) 47 | return response 48 | 49 | # Function to get the price target data 50 | def get_price_target(symbol): 51 | url = f"https://financialmodelingprep.com/api/v4/price-target?symbol={symbol}&apikey={API_KEY}" 52 | response = rate_limited_request(url) 53 | if response.status_code == 200: 54 | data = response.json() 55 | return data 56 | else: 57 | raise Exception(f"Error fetching price target data for {symbol}: {response.status_code}") 58 | 59 | # Function to get historical data using yfinance 60 | def get_historical_data(symbol): 61 | stock = yf.Ticker(symbol) 62 | hist = stock.history(period="max") 63 | if not hist.empty: 64 | return hist 65 | else: 66 | raise Exception(f"No historical data available for symbol: {symbol}") 67 | 68 | # Function to analyze analyst skill based on predictions 69 | def analyze_analyst_skill(symbols, output_file, time_horizon_days=90): 70 | all_price_targets = [] 71 | all_hist_data = {} 72 | 73 | # Fetch price target data in parallel 74 | with ThreadPoolExecutor(max_workers=50) as executor: 75 | future_to_symbol = {executor.submit(get_price_target, symbol): symbol for symbol in symbols} 76 | for future in tqdm(as_completed(future_to_symbol), total=len(symbols), desc="Fetching price target data"): 77 | symbol = future_to_symbol[future] 78 | try: 79 | price_targets = future.result() 80 | if price_targets: 81 | price_target_df = pd.DataFrame(price_targets) 82 | price_target_df["symbol"] = symbol 83 | all_price_targets.append(price_target_df) 84 | except Exception as e: 85 | pass # Ignore errors for individual symbols 86 | 87 | if not all_price_targets: 88 | print("No price target data to analyze.") 89 | return 90 | 91 | all_price_target_df = pd.concat(all_price_targets, ignore_index=True) 92 | all_price_target_df["publishedDate"] = pd.to_datetime(all_price_target_df["publishedDate"]).dt.normalize() 93 | all_price_target_df.set_index("publishedDate", inplace=True) 94 | 95 | # Fetch historical data in parallel 96 | with ThreadPoolExecutor(max_workers=50) as executor: 97 | future_to_symbol = {executor.submit(get_historical_data, symbol): symbol for symbol in symbols} 98 | for future in tqdm(as_completed(future_to_symbol), total=len(symbols), desc="Fetching historical data"): 99 | symbol = future_to_symbol[future] 100 | try: 101 | hist_data = future.result() 102 | hist_data = hist_data["Close"] 103 | hist_data.index = hist_data.index.normalize() 104 | all_hist_data[symbol] = hist_data 105 | except Exception as e: 106 | pass # Ignore errors for individual symbols 107 | 108 | # Prepare data for analysis 109 | analyst_skill = {} 110 | 111 | # Analyze each symbol 112 | for symbol in tqdm(symbols, desc="Analyzing symbols"): 113 | if symbol not in all_hist_data: 114 | continue 115 | 116 | hist_data = all_hist_data[symbol] 117 | price_target_df = all_price_target_df[all_price_target_df["symbol"] == symbol] 118 | 119 | if price_target_df.empty: 120 | continue 121 | 122 | # For each price target, compute the error after the time horizon 123 | errors = [] 124 | for idx, row in price_target_df.iterrows(): 125 | published_date = idx 126 | target_date = published_date + timedelta(days=time_horizon_days) 127 | 128 | # Find the closest available date in historical data 129 | actual_dates = hist_data.index 130 | if target_date > actual_dates[-1]: 131 | # Cannot compute error if target date is beyond available historical data 132 | continue 133 | idx_closest = actual_dates.get_indexer([target_date], method='nearest')[0] 134 | if idx_closest == -1: 135 | continue # Skip if no nearest date is found 136 | actual_date = actual_dates[idx_closest] 137 | 138 | actual_price = hist_data.loc[actual_date] 139 | 140 | # Compute percentage error 141 | predicted_price = row["priceTarget"] 142 | percentage_error = abs((actual_price - predicted_price) / predicted_price) * 100 143 | errors.append({ 144 | "analystName": row["analystName"], 145 | "analystCompany": row["analystCompany"], 146 | "publisher": row["newsPublisher"], 147 | "symbol": symbol, 148 | "predicted_price": predicted_price, 149 | "actual_price": actual_price, 150 | "percentage_error": percentage_error 151 | }) 152 | 153 | if not errors: 154 | continue 155 | 156 | errors_df = pd.DataFrame(errors) 157 | 158 | # Aggregate errors per analyst 159 | for name, group in errors_df.groupby("analystName"): 160 | avg_error = group["percentage_error"].mean() 161 | count = len(group) 162 | diversity = group["symbol"].nunique() 163 | breadth = count * diversity # Number of predictions times number of unique symbols 164 | accuracy = 1 / avg_error if avg_error != 0 else float('inf') # Avoid division by zero 165 | skill_score = accuracy * breadth # Skill is breadth x accuracy 166 | 167 | if name in analyst_skill: 168 | analyst_skill[name]["breadth"] += breadth 169 | analyst_skill[name]["total_predictions"] += count 170 | analyst_skill[name]["total_error"] += group["percentage_error"].sum() 171 | analyst_skill[name]["unique_symbols"].update(group["symbol"].unique()) 172 | else: 173 | analyst_skill[name] = { 174 | "analystCompany": group["analystCompany"].iloc[0], 175 | "publisher": group["publisher"].iloc[0], 176 | "breadth": breadth, 177 | "total_predictions": count, 178 | "total_error": group["percentage_error"].sum(), 179 | "unique_symbols": set(group["symbol"].unique()) 180 | } 181 | 182 | # Calculate final skill score for each analyst 183 | for name in analyst_skill: 184 | total_error = analyst_skill[name]["total_error"] 185 | total_predictions = analyst_skill[name]["total_predictions"] 186 | avg_error = total_error / total_predictions if total_predictions != 0 else float('inf') 187 | accuracy = 1 / avg_error if avg_error != 0 else float('inf') 188 | breadth = analyst_skill[name]["breadth"] 189 | skill_score = accuracy * breadth 190 | analyst_skill[name]["avg_error"] = avg_error 191 | analyst_skill[name]["accuracy"] = accuracy 192 | analyst_skill[name]["skill_score"] = skill_score 193 | analyst_skill[name]["diversity"] = len(analyst_skill[name]["unique_symbols"]) 194 | 195 | # Convert analyst_skill to DataFrame 196 | analyst_skill_df = pd.DataFrame.from_dict(analyst_skill, orient='index') 197 | analyst_skill_df.reset_index(inplace=True) 198 | analyst_skill_df.rename(columns={'index': 'analystName'}, inplace=True) 199 | 200 | # Sort analysts by skill score 201 | analyst_skill_df.sort_values(by='skill_score', ascending=False, inplace=True) 202 | 203 | # Write the results to the output file 204 | columns_to_output = [ 205 | 'analystName', 'analystCompany', 'publisher', 'skill_score', 206 | 'accuracy', 'avg_error', 'breadth', 'total_predictions', 'diversity' 207 | ] 208 | analyst_skill_df.to_csv(output_file, columns=columns_to_output, index=False) 209 | 210 | print(f"Analyst skill scores have been written to {output_file}") 211 | 212 | # Plotting the skill score for visualization using Plotly 213 | if not analyst_skill_df.empty: 214 | fig = px.scatter( 215 | analyst_skill_df, 216 | x='total_predictions', 217 | y='skill_score', 218 | text='analystName', 219 | labels={"total_predictions": "Number of Predictions", "skill_score": "Skill Score"}, 220 | title="Analyst Skill: Number of Predictions vs Skill Score", 221 | hover_name='analystName', 222 | hover_data={ 223 | "Avg Error (%)": analyst_skill_df['avg_error'], 224 | "Company": analyst_skill_df['analystCompany'], 225 | "Publisher": analyst_skill_df['publisher'], 226 | "Diversity": analyst_skill_df['diversity'] 227 | } 228 | ) 229 | fig.update_traces(marker=dict(size=12, opacity=0.6), mode='markers+text', textposition='top center') 230 | fig.show() 231 | else: 232 | print("No analyst skill scores could be calculated.") 233 | -------------------------------------------------------------------------------- /stock_research/analyze_govtraders.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import aiohttp 3 | import yfinance as yf 4 | import pandas as pd 5 | import numpy as np 6 | import argparse 7 | import math 8 | import logging 9 | from datetime import datetime, timedelta 10 | from collections import defaultdict 11 | from aiohttp import ClientSession, TCPConnector 12 | from tqdm import tqdm 13 | import os 14 | import sys 15 | import re 16 | from aiolimiter import AsyncLimiter 17 | 18 | API_KEY = 'Your_API_Key_Here' # Replace with your actual API key 19 | 20 | # Configure logging 21 | logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') 22 | 23 | # Rate limiter settings 24 | MAX_REQUESTS_PER_MINUTE = 500 # Adjusted to match your actual rate limit 25 | 26 | # Global in-memory cache for price data 27 | price_data_cache = {} 28 | 29 | def parse_amount(amount_str): 30 | """ 31 | Parses the transaction amount string and returns the maximum amount. 32 | 33 | Handles various formats such as: 34 | - "$1,001 - $15,000" 35 | - "Over $50,000,000" 36 | - "> $1,000,000" 37 | - "$15,000" 38 | 39 | Always assumes the maximum amount for estimation. 40 | """ 41 | if not amount_str: 42 | logging.warning("Amount string is None or empty.") 43 | return 0.0 44 | amount_str = amount_str.strip().replace(',', '') 45 | try: 46 | if 'Over' in amount_str: 47 | # Example: "Over $50,000,000" 48 | match = re.search(r'Over\s*\$\s*(\d+(?:\.\d+)?)', amount_str) 49 | if match: 50 | max_amount = float(match.group(1)) 51 | logging.debug(f"Parsed amount (Over): {max_amount}") 52 | return max_amount 53 | elif '-' in amount_str: 54 | # Example: "$1,001 - $15,000" 55 | match = re.search(r'\$\s*(\d+(?:\.\d+)?)\s*-\s*\$\s*(\d+(?:\.\d+)?)', amount_str) 56 | if match: 57 | max_amount = float(match.group(2)) 58 | logging.debug(f"Parsed amount (Range): {max_amount}") 59 | return max_amount 60 | elif '>' in amount_str: 61 | # Example: "> $1,000,000" 62 | match = re.search(r'>\s*\$\s*(\d+(?:\.\d+)?)', amount_str) 63 | if match: 64 | max_amount = float(match.group(1)) 65 | logging.debug(f"Parsed amount (Greater than): {max_amount}") 66 | return max_amount 67 | else: 68 | # Example: "$15,000" 69 | amount_value = float(amount_str.replace('$', '')) 70 | logging.debug(f"Parsed amount (Single value): {amount_value}") 71 | return amount_value 72 | except Exception as e: 73 | logging.warning(f"Unable to parse amount in standard formats: '{amount_str}'. Error: {e}") 74 | pass # Continue to fallback 75 | 76 | # Fallback: Extract all digits and try to parse 77 | try: 78 | amount_value = float(re.sub(r'[^\d.]', '', amount_str)) 79 | logging.debug(f"Parsed amount (Fallback): {amount_value}") 80 | return amount_value 81 | except Exception as e: 82 | logging.warning(f"Unable to parse amount: '{amount_str}'. Error: {e}") 83 | return 0.0 # Return 0.0 if parsing fails 84 | 85 | async def rate_limited_fetch(session, url, limiter): 86 | """ 87 | Fetches data from the given URL while respecting the rate limit. 88 | 89 | Args: 90 | session: The aiohttp ClientSession to use for the request. 91 | url: The URL to fetch data from. 92 | limiter: The AsyncLimiter instance for rate limiting. 93 | 94 | Returns: 95 | The JSON response if successful, None otherwise. 96 | """ 97 | async with limiter: 98 | async with session.get(url) as response: 99 | if response.status == 200: 100 | return await response.json() 101 | elif response.status == 429: 102 | # Handle rate limit exceeded 103 | logging.error(f"Rate limit exceeded when fetching {url}: Status {response.status}") 104 | return None 105 | else: 106 | logging.error(f"Failed to fetch {url}: Status {response.status}") 107 | return None 108 | 109 | async def fetch_trades(symbols, limiter): 110 | """ 111 | Fetches trade data for the given list of symbols. 112 | 113 | Args: 114 | symbols: List of stock symbols to fetch trade data for. 115 | limiter: The AsyncLimiter instance for rate limiting. 116 | 117 | Returns: 118 | A list of trade dictionaries with standardized keys. 119 | """ 120 | tasks = [] 121 | trades = [] 122 | 123 | async with ClientSession(connector=TCPConnector(ssl=False)) as session: 124 | for symbol in symbols: 125 | # URLs for Senate and House trade data 126 | senate_url = f'https://financialmodelingprep.com/api/v4/senate-trading?symbol={symbol}&apikey={API_KEY}' 127 | house_url = f'https://financialmodelingprep.com/api/v4/house-disclosure?symbol={symbol}&apikey={API_KEY}' 128 | 129 | # Schedule fetching tasks 130 | tasks.append(rate_limited_fetch(session, senate_url, limiter)) 131 | tasks.append(rate_limited_fetch(session, house_url, limiter)) 132 | 133 | # Collect responses asynchronously 134 | responses = [] 135 | for f in tqdm(asyncio.as_completed(tasks), total=len(tasks), desc="Fetching trade data"): 136 | result = await f 137 | responses.append(result) 138 | 139 | # Process responses and standardize trade data 140 | for response in responses: 141 | if response: 142 | for trade in response: 143 | # Normalize and standardize trade data 144 | if 'firstName' in trade: 145 | # Senate trade 146 | trader_name = f"{trade.get('firstName', '')} {trade.get('lastName', '')}".strip() 147 | trade_data = { 148 | 'trader': trader_name, 149 | 'symbol': trade.get('symbol'), 150 | 'transaction_date': trade.get('transactionDate'), 151 | 'type': trade.get('type'), 152 | 'amount': trade.get('amount'), 153 | 'owner': trade.get('owner'), 154 | 'asset_description': trade.get('assetDescription'), 155 | 'source': 'Senate' 156 | } 157 | elif 'representative' in trade: 158 | # House trade 159 | trader_name = trade.get('representative', '').strip() 160 | trade_data = { 161 | 'trader': trader_name, 162 | 'symbol': trade.get('ticker'), 163 | 'transaction_date': trade.get('transactionDate'), 164 | 'type': trade.get('type'), 165 | 'amount': trade.get('amount'), 166 | 'owner': trade.get('owner'), 167 | 'asset_description': trade.get('assetDescription'), 168 | 'source': 'House' 169 | } 170 | else: 171 | continue # Skip unrecognized data 172 | trades.append(trade_data) 173 | 174 | return trades 175 | 176 | def get_price_data(symbol): 177 | """ 178 | Fetches historical price data for the given symbol using yfinance. 179 | 180 | Args: 181 | symbol: The stock symbol to fetch data for. 182 | 183 | Returns: 184 | A pandas DataFrame with historical price data, or None if not available. 185 | """ 186 | if symbol in price_data_cache: 187 | return price_data_cache[symbol] 188 | try: 189 | data = yf.download(symbol, period='max', progress=False) 190 | if not data.empty: 191 | data.index = data.index.strftime('%Y-%m-%d') 192 | price_data_cache[symbol] = data 193 | return data 194 | else: 195 | logging.warning(f"No price data found for {symbol}") 196 | except Exception as e: 197 | logging.error(f"Error fetching price data for {symbol}: {e}") 198 | return None 199 | 200 | def compute_trade_performance(trade, price_data, holding_period_days): 201 | """ 202 | Computes the performance of a single trade over a holding period. 203 | 204 | Args: 205 | trade: A dictionary containing trade information. 206 | price_data: A pandas DataFrame with historical price data for the symbol. 207 | holding_period_days: The holding period in days. 208 | 209 | Returns: 210 | A dictionary with profit, holding period, and return percentage, or None if calculation fails. 211 | """ 212 | symbol = trade['symbol'] 213 | transaction_date = trade['transaction_date'] 214 | trade_type = trade['type'].lower() # Convert to lowercase for case-insensitive comparison 215 | amount = parse_amount(trade['amount']) 216 | 217 | # Check if amount is valid 218 | if amount is None or amount == 0: 219 | logging.warning(f"Amount is None or zero for trade: {trade}") 220 | return None 221 | 222 | # Find the closest available date on or after the transaction date 223 | available_dates = price_data.index 224 | if transaction_date not in available_dates: 225 | transaction_datetime = datetime.strptime(transaction_date, '%Y-%m-%d') 226 | future_dates = [date for date in available_dates if datetime.strptime(date, '%Y-%m-%d') >= transaction_datetime] 227 | if not future_dates: 228 | logging.warning(f"No future price data for {symbol} after {transaction_date}") 229 | return None 230 | transaction_date = future_dates[0] 231 | 232 | # Get transaction price 233 | transaction_price = price_data.loc[transaction_date]['Close'] 234 | if transaction_price is None or transaction_price == 0 or math.isnan(transaction_price): 235 | logging.warning(f"Invalid transaction price for {symbol} on {transaction_date}") 236 | return None 237 | 238 | shares = amount / transaction_price 239 | 240 | # Assume we hold the position for the specified holding period or until the last available date 241 | start_date = datetime.strptime(transaction_date, '%Y-%m-%d') 242 | end_date = start_date + timedelta(days=holding_period_days) 243 | end_date_str = end_date.strftime('%Y-%m-%d') 244 | 245 | # Find the closest available date on or after the end date 246 | if end_date_str not in available_dates: 247 | future_dates = [date for date in available_dates if datetime.strptime(date, '%Y-%m-%d') >= end_date] 248 | if not future_dates: 249 | end_date_str = available_dates[-1] # Use the latest available date 250 | else: 251 | end_date_str = future_dates[0] 252 | 253 | # Get closing price at the end of the holding period 254 | end_price = price_data.loc[end_date_str]['Close'] 255 | if end_price is None or end_price == 0 or math.isnan(end_price): 256 | logging.warning(f"Invalid end price for {symbol} on {end_date_str}") 257 | return None 258 | 259 | # Calculate profit based on trade type 260 | profit = 0.0 261 | # Define buy and sell types 262 | buy_types = ['purchase', 'buy', 'receive', 'exchange'] 263 | sell_types = ['sale', 'sell'] 264 | 265 | if any(buy_type in trade_type for buy_type in buy_types): 266 | # For buy trades, profit is calculated as (End Price - Transaction Price) * Shares 267 | profit = (end_price - transaction_price) * shares 268 | elif any(sell_type in trade_type for sell_type in sell_types): 269 | # For sell trades, profit is calculated as (Transaction Price - End Price) * Shares 270 | profit = (transaction_price - end_price) * shares 271 | else: 272 | logging.warning(f"Unknown trade type: {trade_type}") 273 | return None 274 | 275 | return { 276 | 'profit': profit, 277 | 'holding_period': (end_date - start_date).days, 278 | 'return_percentage': (profit / amount) * 100 if amount != 0 else 0 279 | } 280 | 281 | def calculate_trader_skill(trades, holding_period_days): 282 | """ 283 | Calculates the skill metrics for each trader based on their trades. 284 | 285 | Args: 286 | trades: A list of trade dictionaries. 287 | holding_period_days: The holding period in days for backtesting. 288 | 289 | Returns: 290 | A dictionary mapping traders to their skill metrics. 291 | """ 292 | trader_performance = defaultdict(list) 293 | 294 | # Fetch price data for all symbols involved 295 | symbols = set(trade['symbol'] for trade in trades) 296 | for symbol in tqdm(symbols, desc="Fetching price data"): 297 | get_price_data(symbol) 298 | 299 | # Compute individual trade performances 300 | for trade in tqdm(trades, desc="Computing trade performance"): 301 | symbol = trade['symbol'] 302 | price_data = price_data_cache.get(symbol) 303 | if price_data is None: 304 | continue 305 | 306 | performance = compute_trade_performance(trade, price_data, holding_period_days) 307 | if performance: 308 | trader_performance[trade['trader']].append(performance) 309 | 310 | # Calculate skill metrics for each trader 311 | trader_skills = {} 312 | MIN_TRADES = 10 # Set your desired minimum number of trades 313 | 314 | for trader, performances in trader_performance.items(): 315 | trade_count = len(performances) 316 | if trade_count < MIN_TRADES: 317 | continue # Skip traders with fewer than MIN_TRADES 318 | 319 | profits = [p['profit'] for p in performances] 320 | returns = [p['return_percentage'] for p in performances] 321 | holding_periods = [p['holding_period'] for p in performances] 322 | 323 | total_profit = sum(profits) 324 | average_return = np.mean(returns) 325 | average_holding_period = np.mean(holding_periods) 326 | trade_breadth = len(set(trade['symbol'] for trade in trades if trade['trader'] == trader)) 327 | 328 | # Calculate standard deviation of returns 329 | if len(returns) > 1: 330 | return_std = np.std(returns, ddof=1) 331 | if return_std != 0: 332 | sharpe_ratio = average_return / return_std 333 | else: 334 | sharpe_ratio = 0.0 335 | else: 336 | return_std = 0.0 # Not enough data to compute std deviation 337 | sharpe_ratio = 0.0 338 | 339 | # Skill score combining multiple factors 340 | skill_score = ( 341 | (average_return * total_profit * math.log1p(trade_count) * math.log1p(trade_breadth) * sharpe_ratio) 342 | / (1 + return_std) 343 | ) 344 | 345 | trader_skills[trader] = { 346 | 'Total Profit ($)': total_profit, 347 | 'Average Return (%)': average_return, 348 | 'Return Std Dev (%)': return_std, 349 | 'Sharpe Ratio': sharpe_ratio, 350 | 'Average Holding Period (days)': average_holding_period, 351 | 'Number of Trades': trade_count, 352 | 'Trade Breadth': trade_breadth, 353 | 'Skill Score': skill_score 354 | } 355 | 356 | return trader_skills 357 | 358 | def save_results(trader_skills, outfile): 359 | """ 360 | Saves the trader skills data to a CSV file. 361 | 362 | Args: 363 | trader_skills: A dictionary mapping traders to their skill metrics. 364 | outfile: The path to the output CSV file. 365 | """ 366 | df = pd.DataFrame.from_dict(trader_skills, orient='index') 367 | df.index.name = 'Trader' 368 | df.sort_values(by='Skill Score', ascending=False, inplace=True) 369 | df.to_csv(outfile) 370 | logging.info(f"Results saved to {outfile}") 371 | 372 | async def main(): 373 | """ 374 | Main function to parse arguments, fetch data, compute skills, and save results. 375 | """ 376 | parser = argparse.ArgumentParser(description='Analyze government trades and rank traders by skill.') 377 | parser.add_argument('--symbols', required=True, help='Path to symbols file (one symbol per line)') 378 | parser.add_argument('--outfile', required=True, help='Output CSV file path') 379 | parser.add_argument('--verbose', action='store_true', help='Enable verbose logging') 380 | parser.add_argument('--holding-period', type=int, default=30, help='Holding period in days for backtesting') 381 | args = parser.parse_args() 382 | 383 | if args.verbose: 384 | logging.getLogger().setLevel(logging.DEBUG) 385 | 386 | # Read symbols from file 387 | if not os.path.exists(args.symbols): 388 | logging.error(f"Symbols file not found: {args.symbols}") 389 | sys.exit(1) 390 | 391 | with open(args.symbols, 'r') as f: 392 | symbols = [line.strip().upper() for line in f if line.strip()] 393 | 394 | if not symbols: 395 | logging.error("No symbols provided.") 396 | sys.exit(1) 397 | 398 | # Initialize limiter for rate limiting 399 | limiter = AsyncLimiter(MAX_REQUESTS_PER_MINUTE, time_period=60) # Rate limiter 400 | 401 | # Fetch trades 402 | trades = await fetch_trades(symbols, limiter) 403 | 404 | if not trades: 405 | logging.error("No trades found.") 406 | sys.exit(1) 407 | 408 | # Calculate trader skills 409 | trader_skills = calculate_trader_skill(trades, args.holding_period) 410 | 411 | if not trader_skills: 412 | logging.error("No trader skills calculated.") 413 | sys.exit(1) 414 | 415 | # Save results 416 | save_results(trader_skills, args.outfile) 417 | 418 | if __name__ == "__main__": 419 | asyncio.run(main()) 420 | -------------------------------------------------------------------------------- /stock_research/esg_analyze.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pandas as pd 3 | import numpy as np 4 | import datetime 5 | from dotenv import load_dotenv 6 | from tqdm import tqdm 7 | import asyncio 8 | import aiohttp 9 | import time 10 | import plotly.express as px 11 | from scipy.stats import kendalltau, spearmanr 12 | from statsmodels.distributions.copula.api import ( 13 | ClaytonCopula, FrankCopula, GumbelCopula, 14 | GaussianCopula, StudentTCopula 15 | ) 16 | from statsmodels.distributions.empirical_distribution import ECDF 17 | 18 | # Load API key from .env file 19 | load_dotenv() 20 | FMP_API_KEY = os.getenv('FMP_API_KEY') 21 | 22 | # Check if API key is loaded 23 | if not FMP_API_KEY: 24 | raise ValueError("FMP_API_KEY not found in .env file.") 25 | 26 | # 1. Load the list of symbols from symbols.txt 27 | with open('symbols.txt', 'r') as file: 28 | symbols = [line.strip() for line in file.readlines()] 29 | 30 | # Remove any empty symbols 31 | symbols = [symbol for symbol in symbols if symbol] 32 | 33 | # Optimized RateLimiter class for FMP API 34 | class RateLimiter: 35 | def __init__(self, max_calls, period): 36 | self._max_calls = max_calls 37 | self._period = period 38 | self._tokens = max_calls 39 | self._last = time.monotonic() 40 | self._lock = asyncio.Lock() 41 | 42 | async def acquire(self): 43 | async with self._lock: 44 | now = time.monotonic() 45 | elapsed = now - self._last 46 | self._last = now 47 | self._tokens += elapsed * (self._max_calls / self._period) 48 | if self._tokens > self._max_calls: 49 | self._tokens = self._max_calls 50 | if self._tokens < 1: 51 | await asyncio.sleep((1 - self._tokens) * (self._period / self._max_calls)) 52 | self._tokens = 0 53 | else: 54 | self._tokens -= 1 55 | 56 | # 2. Fetch ESG data asynchronously 57 | async def fetch_esg_data(session, symbol, rate_limiter): 58 | await rate_limiter.acquire() 59 | url = f'https://financialmodelingprep.com/api/v4/esg-environmental-social-governance-data?symbol={symbol}&apikey={FMP_API_KEY}' 60 | try: 61 | async with session.get(url) as response: 62 | if response.status == 200: 63 | data = await response.json() 64 | if data: 65 | return 'esg', symbol, data[0] 66 | else: 67 | return 'esg', symbol, None 68 | else: 69 | return 'esg', symbol, None 70 | except Exception as e: 71 | return 'esg', symbol, None 72 | 73 | # 3. Fetch historical stock prices from FMP API asynchronously 74 | async def fetch_stock_price_fmp(session, symbol, start_date, end_date, rate_limiter): 75 | await rate_limiter.acquire() 76 | url = f'https://financialmodelingprep.com/api/v3/historical-price-full/{symbol}?from={start_date}&to={end_date}&apikey={FMP_API_KEY}' 77 | try: 78 | async with session.get(url) as response: 79 | if response.status == 200: 80 | data = await response.json() 81 | if 'historical' in data and data['historical']: 82 | df = pd.DataFrame(data['historical']) 83 | df['date'] = pd.to_datetime(df['date']) 84 | df = df[['date', 'close']].sort_values('date') 85 | df['symbol'] = symbol # Add symbol column for later merging 86 | return 'price', symbol, df 87 | else: 88 | return 'price', symbol, None 89 | else: 90 | return 'price', symbol, None 91 | except Exception as e: 92 | return 'price', symbol, None 93 | 94 | # 4. Compute cumulative return 95 | def compute_cumulative_return(df): 96 | df = df.sort_values('date') 97 | initial_price = df['close'].iloc[0] 98 | final_price = df['close'].iloc[-1] 99 | cumulative_return = (final_price - initial_price) / initial_price 100 | return cumulative_return 101 | 102 | # Main function to run the async tasks with optimizations 103 | async def main(): 104 | # Rate limiter allows 10 requests per second (adjust based on API limits) 105 | rate_limiter = RateLimiter(max_calls=10, period=1) 106 | 107 | esg_data_list = [] 108 | stock_prices = {} 109 | 110 | # Define date range (e.g., past one year) 111 | end_date = datetime.date.today().isoformat() 112 | start_date = (datetime.date.today() - datetime.timedelta(days=365)).isoformat() 113 | 114 | async with aiohttp.ClientSession() as session: 115 | tasks = [] 116 | for symbol in symbols: 117 | esg_task = asyncio.create_task(fetch_esg_data(session, symbol, rate_limiter)) 118 | tasks.append(esg_task) 119 | 120 | price_task = asyncio.create_task(fetch_stock_price_fmp(session, symbol, start_date, end_date, rate_limiter)) 121 | tasks.append(price_task) 122 | 123 | print("\nFetching ESG data and stock prices:") 124 | for f in tqdm(asyncio.as_completed(tasks), total=len(tasks), desc="Data Fetching", unit="task"): 125 | task_type, symbol, data = await f 126 | if task_type == 'esg': 127 | if data: 128 | esg_data_list.append(data) 129 | else: 130 | print(f"ESG data not found for symbol: {symbol}") 131 | elif task_type == 'price': 132 | if data is not None: 133 | stock_prices[symbol] = data 134 | else: 135 | print(f"Stock price data not found or empty for symbol: {symbol}") 136 | 137 | if not esg_data_list: 138 | raise ValueError("No ESG data was fetched. Please check the symbols and API responses.") 139 | if not stock_prices: 140 | raise ValueError("No stock price data was fetched. Please check the symbols and API responses.") 141 | 142 | # Compute cumulative returns 143 | cumulative_returns = [] 144 | for symbol, df in stock_prices.items(): 145 | cum_return = compute_cumulative_return(df) 146 | cumulative_returns.append({'symbol': symbol, 'cumulative_return': cum_return}) 147 | 148 | cumulative_returns_df = pd.DataFrame(cumulative_returns) 149 | 150 | # Prepare data for correlation analysis 151 | esg_scores = pd.DataFrame(esg_data_list) 152 | esg_scores = esg_scores[['symbol', 'environmentalScore', 'socialScore', 'governanceScore', 'ESGScore']] 153 | 154 | # Merge ESG scores with cumulative returns 155 | merged_data = pd.merge(esg_scores, cumulative_returns_df, on='symbol') 156 | merged_data.dropna(inplace=True) # Remove rows with missing data 157 | 158 | # Check if merged_data is empty 159 | if merged_data.empty: 160 | raise ValueError("No data available after merging ESG scores with cumulative returns.") 161 | 162 | # Analyze dependence using copulas 163 | esg_score_columns = ['environmentalScore', 'socialScore', 'governanceScore', 'ESGScore'] 164 | 165 | # Create a DataFrame to store dependence measures and best copulas 166 | dependence_results = [] 167 | 168 | for score in esg_score_columns: 169 | print(f"\nAnalyzing dependence between {score} and cumulative_return using copulas.") 170 | 171 | data = merged_data[[score, 'cumulative_return']].dropna() 172 | 173 | u = data[score].values 174 | v = data['cumulative_return'].values 175 | 176 | # Check for constant values in data 177 | if np.all(u == u[0]) or np.all(v == v[0]): 178 | print(f"Data for {score} or cumulative_return is constant. Skipping...") 179 | continue 180 | 181 | # Convert data to uniform margins using rank transformation 182 | u_ranks = (pd.Series(u).rank(method='average').values - 0.5) / len(u) 183 | v_ranks = (pd.Series(v).rank(method='average').values - 0.5) / len(v) 184 | 185 | # Ensure the data is in (0,1) 186 | u_uniform = u_ranks 187 | v_uniform = v_ranks 188 | 189 | # Stack the data 190 | data_uniform = np.column_stack([u_uniform, v_uniform]) 191 | 192 | # Compute empirical Kendall's tau 193 | tau_empirical, _ = kendalltau(u, v) 194 | 195 | # Define copulas and estimate parameters from Kendall's tau 196 | copula_models = {} 197 | 198 | # GaussianCopula 199 | rho_gaussian, _ = spearmanr(u, v) 200 | corr_matrix = np.array([[1, rho_gaussian], 201 | [rho_gaussian, 1]]) 202 | copula_gaussian = GaussianCopula() 203 | copula_gaussian.corr = corr_matrix 204 | copula_models['GaussianCopula'] = copula_gaussian 205 | 206 | # StudentTCopula 207 | copula_student_t = StudentTCopula(df=4) 208 | copula_student_t.corr = corr_matrix 209 | copula_models['StudentTCopula'] = copula_student_t 210 | 211 | # ClaytonCopula 212 | if 0 < tau_empirical < 1: 213 | theta_clayton = 2 * tau_empirical / (1 - tau_empirical) 214 | if theta_clayton > 0: 215 | copula_clayton = ClaytonCopula(theta=theta_clayton) 216 | copula_models['ClaytonCopula'] = copula_clayton 217 | else: 218 | print(f"Invalid theta for Clayton Copula: {theta_clayton}") 219 | else: 220 | print(f"Invalid Kendall's tau for Clayton Copula: {tau_empirical}") 221 | 222 | # GumbelCopula 223 | if 0 < tau_empirical < 1: 224 | theta_gumbel = 1 / (1 - tau_empirical) 225 | if theta_gumbel >= 1: 226 | copula_gumbel = GumbelCopula(theta=theta_gumbel) 227 | copula_models['GumbelCopula'] = copula_gumbel 228 | else: 229 | print(f"Invalid theta for Gumbel Copula: {theta_gumbel}") 230 | else: 231 | print(f"Invalid Kendall's tau for Gumbel Copula: {tau_empirical}") 232 | 233 | # FrankCopula 234 | try: 235 | copula_frank = FrankCopula() 236 | theta_frank = copula_frank.params_from_tau(tau_empirical) 237 | copula_frank.theta = theta_frank 238 | copula_models['FrankCopula'] = copula_frank 239 | except Exception as e: 240 | print(f"Failed to estimate parameters for FrankCopula: {e}") 241 | 242 | best_copula = None 243 | best_log_likelihood = -np.inf 244 | best_copula_name = None 245 | 246 | for name, copula in copula_models.items(): 247 | try: 248 | # Compute log-likelihood 249 | log_likelihood = np.sum(copula.logpdf(data_uniform)) 250 | print(f"{name} log-likelihood: {log_likelihood:.4f}") 251 | if log_likelihood > best_log_likelihood: 252 | best_log_likelihood = log_likelihood 253 | best_copula = copula 254 | best_copula_name = name 255 | except Exception as e: 256 | print(f"Failed to compute log-likelihood for {name}: {e}") 257 | 258 | if best_copula is None: 259 | print(f"No copula could be fitted for {score}. Skipping...") 260 | continue 261 | 262 | print(f"Best copula: {best_copula_name} with log-likelihood {best_log_likelihood:.4f}") 263 | 264 | # Use the best copula to sample data 265 | try: 266 | samples_uniform = best_copula.rvs(len(u_uniform), random_state=42) 267 | except Exception as e: 268 | print(f"Failed to generate samples using {best_copula_name}: {e}") 269 | continue 270 | 271 | # Convert uniform samples back to data using inverse rank transformation 272 | samples_u = np.quantile(u, samples_uniform[:, 0]) 273 | samples_v = np.quantile(v, samples_uniform[:, 1]) 274 | 275 | # Compute dependence measures 276 | original_kendall_tau, _ = kendalltau(u, v) 277 | synthetic_kendall_tau, _ = kendalltau(samples_u, samples_v) 278 | 279 | original_spearman_rho, _ = spearmanr(u, v) 280 | synthetic_spearman_rho, _ = spearmanr(samples_u, samples_v) 281 | 282 | print(f"Original Kendall's tau: {original_kendall_tau:.4f}") 283 | print(f"Synthetic Kendall's tau: {synthetic_kendall_tau:.4f}") 284 | 285 | print(f"Original Spearman's rho: {original_spearman_rho:.4f}") 286 | print(f"Synthetic Spearman's rho: {synthetic_spearman_rho:.4f}") 287 | 288 | # Save the results 289 | dependence_results.append({ 290 | 'score': score, 291 | 'best_copula': best_copula_name, 292 | 'log_likelihood': best_log_likelihood, 293 | 'original_kendall_tau': original_kendall_tau, 294 | 'synthetic_kendall_tau': synthetic_kendall_tau, 295 | 'original_spearman_rho': original_spearman_rho, 296 | 'synthetic_spearman_rho': synthetic_spearman_rho 297 | }) 298 | 299 | # Visualize original data vs synthetic data 300 | fig = px.scatter( 301 | x=u, y=v, 302 | title=f'Original Data: {score} vs. Cumulative Return', 303 | labels={'x': score, 'y': 'Cumulative Return'} 304 | ) 305 | fig.show() 306 | 307 | fig = px.scatter( 308 | x=samples_u, y=samples_v, 309 | title=f'Synthetic Data ({best_copula_name}): {score} vs. Cumulative Return', 310 | labels={'x': score, 'y': 'Cumulative Return'} 311 | ) 312 | fig.show() 313 | 314 | # Convert dependence results to DataFrame 315 | dependence_df = pd.DataFrame(dependence_results) 316 | print("\nDependence analysis results:") 317 | print(dependence_df) 318 | 319 | # Save dependence results to CSV 320 | dependence_df.to_csv('esg_dependence_results.csv', index=False) 321 | print("\nDependence results saved to 'esg_dependence_results.csv'.") 322 | 323 | # Save merged data to CSV for further analysis 324 | merged_data.to_csv('esg_returns_data.csv', index=False) 325 | print("\nMerged data saved to 'esg_returns_data.csv'.") 326 | 327 | # Run the main function 328 | if __name__ == "__main__": 329 | asyncio.run(main()) 330 | -------------------------------------------------------------------------------- /stock_research/esg_dependence_results.csv: -------------------------------------------------------------------------------- 1 | score,best_copula,log_likelihood,original_kendall_tau,synthetic_kendall_tau,original_spearman_rho,synthetic_spearman_rho 2 | environmentalScore,GaussianCopula,-2.2049029269055614e-13,-0.012755029600118697,-0.004057062967881666,-0.01957662131700009,-0.006192731487020661 3 | socialScore,GaussianCopula,-2.3070434451710753e-13,-0.016384249020789037,-0.004047170467221082,-0.02574294182864296,-0.006189693106407389 4 | governanceScore,ClaytonCopula,1.569803106471839,0.018970159242752516,0.01700973304561009,0.02778061809682935,0.025298779963663216 5 | ESGScore,GaussianCopula,-2.401412402264214e-13,-0.008310289279570277,-0.004021432642356001,-0.012742760630710568,-0.006156177880289501 6 | -------------------------------------------------------------------------------- /stock_research/etf_sectors.py: -------------------------------------------------------------------------------- 1 | """ 2 | ETF and Sector Analysis Script 3 | 4 | This script reads ETF symbols from a file called 'etfs.txt', fetches data from the Financial Modeling Prep API to analyze ETFs and their sector exposures. 5 | It builds a graph of ETFs and sectors using NetworkX and visualizes it using Plotly. The script computes 6 | node weights for ETFs based on assets under management (AUM), average volume, expense ratio, and historical 7 | performance. It then applies network analysis algorithms to determine: 8 | 9 | 1. The most central ETFs based on NetworkX centrality measures. 10 | 2. The best ETF to invest in per sector, ranked by the best sectors to invest. 11 | 3. The most important nodes combining node weights and centrality measures. 12 | 13 | Usage: 14 | - Ensure you have a .env file in the same directory with your FMP_API_KEY. 15 | - Create an 'etfs.txt' file in the same directory with one ETF symbol per line. 16 | - Install required packages: requests, pandas, networkx, plotly, python-dotenv, concurrent.futures, numpy 17 | - Run the script using Python 3. 18 | 19 | Note: 20 | - The script is designed to stay within the API rate limit of 300 requests per minute. 21 | - Adjust 'max_etfs' in the 'main' function to change the number of ETFs processed. 22 | 23 | Author: Your Name 24 | Date: 2023-10-12 25 | """ 26 | 27 | import os 28 | import requests 29 | import pandas as pd 30 | import networkx as nx 31 | import plotly.graph_objs as go 32 | from plotly.offline import plot # For saving the graph to an HTML file 33 | from dotenv import load_dotenv 34 | import concurrent.futures # For concurrent requests 35 | import numpy as np 36 | import logging 37 | 38 | # Setup logging 39 | logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s') 40 | 41 | # Load the FMP_API_KEY from the .env file 42 | load_dotenv() 43 | FMP_API_KEY = os.getenv('FMP_API_KEY') 44 | 45 | if not FMP_API_KEY: 46 | raise ValueError("FMP_API_KEY not found. Please set it in the .env file.") 47 | 48 | def get_etf_list_from_file(): 49 | """ 50 | Reads ETF symbols from 'etfs.txt' file, one symbol per line. 51 | 52 | Returns: 53 | etf_symbols (list): List of ETF symbols. 54 | """ 55 | if not os.path.exists('etfs.txt'): 56 | raise FileNotFoundError("The file 'etfs.txt' was not found in the current directory.") 57 | with open('etfs.txt', 'r') as f: 58 | etf_symbols = [line.strip().upper() for line in f if line.strip()] 59 | logging.info(f"Total ETFs read from file: {len(etf_symbols)}") 60 | return etf_symbols 61 | 62 | def get_etf_info(symbol): 63 | """ 64 | Fetches detailed information about an ETF. 65 | 66 | Args: 67 | symbol (str): ETF ticker symbol. 68 | 69 | Returns: 70 | etf_info (dict): Dictionary containing ETF information. 71 | """ 72 | url = f"https://financialmodelingprep.com/api/v4/etf-info?symbol={symbol}&apikey={FMP_API_KEY}" 73 | response = requests.get(url) 74 | if response.status_code != 200: 75 | logging.warning(f"Failed to fetch info for ETF: {symbol} (Status Code: {response.status_code})") 76 | return None 77 | data = response.json() 78 | if data: 79 | return data[0] # Returns the first (and only) element 80 | else: 81 | logging.warning(f"No data returned for ETF: {symbol}") 82 | return None 83 | 84 | def get_etf_sector_weightings(symbol): 85 | """ 86 | Fetches sector weightings for an ETF. 87 | 88 | Args: 89 | symbol (str): ETF ticker symbol. 90 | 91 | Returns: 92 | sector_weightings (list of dict): List of sectors and their weight percentages. 93 | """ 94 | url = f"https://financialmodelingprep.com/api/v3/etf-sector-weightings/{symbol}?apikey={FMP_API_KEY}" 95 | response = requests.get(url) 96 | if response.status_code != 200: 97 | logging.warning(f"Failed to fetch sector weightings for ETF: {symbol} (Status Code: {response.status_code})") 98 | return None 99 | data = response.json() 100 | if not data: 101 | logging.warning(f"No sector weightings data returned for ETF: {symbol}") 102 | return data 103 | 104 | def get_sector_performance(): 105 | """ 106 | Fetches current sector performance data. 107 | 108 | Returns: 109 | sector_performance (pd.DataFrame): DataFrame containing sectors and their performance percentages. 110 | """ 111 | url = f"https://financialmodelingprep.com/api/v3/sectors-performance?apikey={FMP_API_KEY}" 112 | response = requests.get(url) 113 | if response.status_code != 200: 114 | raise Exception("Failed to fetch sector performance data.") 115 | data = response.json() 116 | sector_performance = pd.DataFrame(data) 117 | # Process 'changesPercentage' to remove '%' and convert to float 118 | sector_performance['changesPercentage'] = sector_performance['changesPercentage'].str.replace('%', '').astype(float) 119 | logging.info(f"Fetched performance data for {len(sector_performance)} sectors.") 120 | return sector_performance 121 | 122 | def get_etf_historical_performance(symbol, period='3months'): 123 | """ 124 | Fetches historical performance data for an ETF. 125 | 126 | Args: 127 | symbol (str): ETF ticker symbol. 128 | period (str): Period for historical data ('1month', '3months', '6months', '1year') 129 | 130 | Returns: 131 | performance (float): Percentage change over the specified period. 132 | """ 133 | periods = { 134 | '1month': 21, 135 | '3months': 63, 136 | '6months': 126, 137 | '1year': 252 138 | } 139 | days = periods.get(period, 63) # Default to '3months' if not specified 140 | url = f"https://financialmodelingprep.com/api/v3/historical-price-full/{symbol}?serietype=line×eries={days}&apikey={FMP_API_KEY}" 141 | response = requests.get(url) 142 | if response.status_code != 200: 143 | logging.warning(f"Failed to fetch historical data for ETF: {symbol} (Status Code: {response.status_code})") 144 | return None 145 | data = response.json() 146 | if 'historical' in data and len(data['historical']) > 1: 147 | prices = pd.DataFrame(data['historical']) 148 | start_price = prices.iloc[-1]['close'] 149 | end_price = prices.iloc[0]['close'] 150 | if start_price == 0: 151 | logging.warning(f"Start price is zero for ETF: {symbol}") 152 | return 0.0 153 | performance = ((end_price - start_price) / start_price) * 100 154 | return performance 155 | else: 156 | logging.warning(f"Not enough historical data for ETF: {symbol}") 157 | return None 158 | 159 | def compute_node_weights(G): 160 | """ 161 | Computes node weights for ETFs and Sectors in the graph. 162 | 163 | Args: 164 | G (networkx.Graph): The graph containing ETF and Sector nodes. 165 | """ 166 | # Small number to avoid division by zero 167 | epsilon = 1e-6 168 | 169 | # Collect data for normalization 170 | aum_list = [] 171 | performance_list = [] 172 | volume_list = [] 173 | expense_ratio_list = [] 174 | 175 | # First, ensure 'node_weight' is set for all sector nodes 176 | for node in G.nodes(): 177 | node_data = G.nodes[node] 178 | if node_data.get('type') == 'Sector': 179 | performance = node_data.get('performance', 0.0) 180 | if not isinstance(performance, (int, float)): 181 | performance = 0.0 182 | node_data['node_weight'] = performance 183 | 184 | # Now process ETF nodes 185 | etf_nodes = [n for n, d in G.nodes(data=True) if d.get('type') == 'ETF'] 186 | if not etf_nodes: 187 | logging.error("No ETF nodes found in the graph.") 188 | return 189 | 190 | for node in etf_nodes: 191 | node_data = G.nodes[node] 192 | aum = node_data.get('aum', 0.0) 193 | historical_performance = node_data.get('historical_performance', 0.0) 194 | avg_volume = node_data.get('avg_volume', 0.0) 195 | expense_ratio = node_data.get('expense_ratio', epsilon) 196 | 197 | # Check if data is valid 198 | if aum == 0.0: 199 | logging.warning(f"AUM is zero for ETF: {node}") 200 | if avg_volume == 0.0: 201 | logging.warning(f"Average volume is zero for ETF: {node}") 202 | if expense_ratio == epsilon: 203 | logging.warning(f"Expense ratio is zero or missing for ETF: {node}") 204 | if historical_performance == 0.0: 205 | logging.warning(f"Historical performance is zero or missing for ETF: {node}") 206 | 207 | aum_list.append(aum) 208 | performance_list.append(historical_performance) 209 | volume_list.append(avg_volume) 210 | expense_ratio_list.append(expense_ratio) 211 | 212 | # Check if lists have valid data 213 | if not any(aum_list) or not any(performance_list) or not any(volume_list) or not any(expense_ratio_list): 214 | logging.error("Insufficient valid data to compute node weights for ETFs.") 215 | return 216 | 217 | # Convert lists to numpy arrays 218 | aum_array = np.array(aum_list) 219 | performance_array = np.array(performance_list) 220 | volume_array = np.array(volume_list) 221 | expense_ratio_array = np.array(expense_ratio_list) 222 | 223 | # Handle cases where the ptp (max - min) is zero 224 | def safe_normalize(array): 225 | ptp = array.ptp() 226 | if ptp == 0: 227 | logging.warning("Peak-to-peak (ptp) is zero during normalization.") 228 | return np.zeros_like(array) 229 | else: 230 | return (array - array.min()) / (ptp + epsilon) 231 | 232 | aum_norm = safe_normalize(aum_array) 233 | performance_norm = safe_normalize(performance_array) 234 | volume_norm = safe_normalize(volume_array) 235 | expense_ratio_norm = safe_normalize(expense_ratio_array.max() - expense_ratio_array) # Invert expense ratio 236 | 237 | # Assign normalized values back to nodes 238 | for idx, node in enumerate(etf_nodes): 239 | node_data = G.nodes[node] 240 | node_data['aum_norm'] = aum_norm[idx] 241 | node_data['performance_norm'] = performance_norm[idx] 242 | node_data['volume_norm'] = volume_norm[idx] 243 | node_data['expense_ratio_norm'] = expense_ratio_norm[idx] 244 | 245 | # Compute node weights for ETFs 246 | for node in etf_nodes: 247 | node_data = G.nodes[node] 248 | # Weight factors (can be adjusted as needed) 249 | weight_aum = 0.3 250 | weight_performance = 0.4 251 | weight_volume = 0.2 252 | weight_expense_ratio = 0.1 253 | 254 | node_weight = ( 255 | weight_aum * node_data['aum_norm'] + 256 | weight_performance * node_data['performance_norm'] + 257 | weight_volume * node_data['volume_norm'] + 258 | weight_expense_ratio * node_data['expense_ratio_norm'] 259 | ) 260 | node_data['node_weight'] = node_weight 261 | 262 | logging.info("Node weights computed successfully.") 263 | 264 | def compute_centrality_measures(G): 265 | """ 266 | Computes centrality measures for each node in the graph. 267 | 268 | Args: 269 | G (networkx.Graph): The graph containing ETF and Sector nodes. 270 | """ 271 | logging.info("Computing centrality measures...") 272 | # Compute centrality measures 273 | degree_centrality = nx.degree_centrality(G) 274 | betweenness_centrality = nx.betweenness_centrality(G) 275 | try: 276 | eigenvector_centrality = nx.eigenvector_centrality(G, max_iter=1000) 277 | except nx.NetworkXException as e: 278 | logging.warning(f"Eigenvector centrality did not converge: {e}") 279 | eigenvector_centrality = {node: 0.0 for node in G.nodes()} 280 | 281 | # Assign centrality measures to nodes 282 | for node in G.nodes(): 283 | G.nodes[node]['degree_centrality'] = degree_centrality.get(node, 0.0) 284 | G.nodes[node]['betweenness_centrality'] = betweenness_centrality.get(node, 0.0) 285 | G.nodes[node]['eigenvector_centrality'] = eigenvector_centrality.get(node, 0.0) 286 | logging.info("Centrality measures computed successfully.") 287 | 288 | def find_most_important_nodes(G, top_n=10): 289 | """ 290 | Finds the most important nodes by combining node weights and centrality measures. 291 | 292 | Args: 293 | G (networkx.Graph): The graph containing ETF and Sector nodes. 294 | top_n (int): Number of top nodes to return. 295 | """ 296 | logging.info("Calculating combined importance scores for nodes...") 297 | # Collect node weights and centrality measures 298 | node_scores = {} 299 | for node, data in G.nodes(data=True): 300 | if data.get('type') == 'ETF': 301 | node_weight = data.get('node_weight', 0.0) 302 | degree_centrality = data.get('degree_centrality', 0.0) 303 | betweenness_centrality = data.get('betweenness_centrality', 0.0) 304 | eigenvector_centrality = data.get('eigenvector_centrality', 0.0) 305 | # Normalize node_weight between 0 and 1 306 | node_weight_norm = node_weight # Already normalized 307 | # Combine centrality measures (weights can be adjusted) 308 | centrality_combined = ( 309 | 0.4 * degree_centrality + 310 | 0.3 * betweenness_centrality + 311 | 0.3 * eigenvector_centrality 312 | ) 313 | # Combine node weight and centrality 314 | importance_score = ( 315 | 0.6 * node_weight_norm + # 60% weight 316 | 0.4 * centrality_combined # 40% weight 317 | ) 318 | node_scores[node] = importance_score 319 | elif data.get('type') == 'Sector': 320 | node_weight = data.get('node_weight', 0.0) # Performance 321 | # For sectors, centrality measures are also available 322 | degree_centrality = data.get('degree_centrality', 0.0) 323 | betweenness_centrality = data.get('betweenness_centrality', 0.0) 324 | eigenvector_centrality = data.get('eigenvector_centrality', 0.0) 325 | # Normalize node_weight between 0 and 1 326 | node_weight_norm = (node_weight - G.nodes[node]['node_weight']) / (max([d.get('node_weight',0) for n,d in G.nodes(data=True) if d.get('type')=='Sector'], default=1) - min([d.get('node_weight',0) for n,d in G.nodes(data=True) if d.get('type')=='Sector'], default=0) + 1e-6) 327 | # Combine centrality measures (weights can be adjusted) 328 | centrality_combined = ( 329 | 0.4 * degree_centrality + 330 | 0.3 * betweenness_centrality + 331 | 0.3 * eigenvector_centrality 332 | ) 333 | # Combine node weight and centrality 334 | importance_score = ( 335 | 0.6 * node_weight_norm + # 60% weight 336 | 0.4 * centrality_combined # 40% weight 337 | ) 338 | node_scores[node] = importance_score 339 | else: 340 | continue # Skip nodes without a valid type 341 | 342 | # Sort nodes based on importance_score 343 | sorted_nodes = sorted(node_scores.items(), key=lambda x: x[1], reverse=True) 344 | 345 | # Output the most important nodes 346 | print("\nMost Important Nodes (ETFs and Sectors):") 347 | for node, score in sorted_nodes[:top_n]: 348 | node_type = G.nodes[node].get('type', '') 349 | if node_type == 'ETF': 350 | name = G.nodes[node].get('name', '') 351 | print(f"ETF: {node} ({name}), Importance Score: {score:.4f}") 352 | elif node_type == 'Sector': 353 | performance = G.nodes[node].get('node_weight', 0.0) 354 | print(f"Sector: {node}, Performance: {performance:.2f}%, Importance Score: {score:.4f}") 355 | logging.info("Most important nodes identified.") 356 | 357 | def find_most_central_etfs(G): 358 | """ 359 | Finds the most central ETFs based on centrality measures. 360 | 361 | Args: 362 | G (networkx.Graph): The graph containing ETF and Sector nodes. 363 | """ 364 | # Collect ETFs and their centrality measures 365 | etfs = [n for n, d in G.nodes(data=True) if d.get('type') == 'ETF'] 366 | centrality_scores = [] 367 | 368 | for etf in etfs: 369 | data = G.nodes[etf] 370 | # Combine centrality measures (weights can be adjusted) 371 | centrality_score = ( 372 | data.get('degree_centrality', 0) * 0.4 + 373 | data.get('betweenness_centrality', 0) * 0.3 + 374 | data.get('eigenvector_centrality', 0) * 0.3 375 | ) 376 | centrality_scores.append((etf, centrality_score)) 377 | 378 | # Sort ETFs based on centrality scores 379 | centrality_scores.sort(key=lambda x: x[1], reverse=True) 380 | 381 | # Output the most central ETFs 382 | print("\nMost Central ETFs based on NetworkX Centrality Measures:") 383 | for etf_symbol, centrality_score in centrality_scores[:10]: # Top 10 ETFs 384 | print(f"ETF: {etf_symbol}, Centrality Score: {centrality_score:.4f}") 385 | 386 | def find_best_etfs_per_sector(G): 387 | """ 388 | Finds the best ETF to invest in per sector based on node weights. 389 | 390 | Args: 391 | G (networkx.Graph): The graph containing ETF and Sector nodes. 392 | """ 393 | # Create a dictionary to store the best ETF per sector 394 | best_etfs_per_sector = {} 395 | 396 | # Iterate through each sector 397 | sectors = [n for n, d in G.nodes(data=True) if d.get('type') == 'Sector'] 398 | for sector in sectors: 399 | connected_etfs = list(G.neighbors(sector)) 400 | if not connected_etfs: 401 | best_etfs_per_sector[sector] = None 402 | continue 403 | # Find the ETF with the highest node_weight 404 | best_etf = max(connected_etfs, key=lambda x: G.nodes[x].get('node_weight', 0)) 405 | best_etfs_per_sector[sector] = best_etf 406 | 407 | # Rank sectors based on their performance 408 | sector_rankings = sorted(sectors, key=lambda x: G.nodes[x].get('node_weight', 0), reverse=True) 409 | 410 | # Output the best ETF per sector, ranked by sector performance 411 | print("\nBest ETFs to invest in per sector, ranked by sector performance:") 412 | for sector in sector_rankings: 413 | sector_perf = G.nodes[sector].get('node_weight', 0.0) 414 | best_etf = best_etfs_per_sector.get(sector) 415 | if best_etf: 416 | etf_weight = G.nodes[best_etf].get('node_weight', 0.0) 417 | print(f"Sector: {sector} (Performance: {sector_perf:.2f}%), Best ETF: {best_etf} (Score: {etf_weight:.4f})") 418 | else: 419 | print(f"Sector: {sector} (Performance: {sector_perf:.2f}%), No ETFs available") 420 | 421 | def visualize_graph(G): 422 | """ 423 | Visualizes the ETF-Sector graph using Plotly and saves it to an HTML file. 424 | 425 | Args: 426 | G (networkx.Graph): The graph containing ETF and Sector nodes. 427 | """ 428 | # Create positions for nodes using networkx layout 429 | pos = nx.spring_layout(G, k=0.15, iterations=20) 430 | 431 | # Create edge traces 432 | edge_trace = [] 433 | min_width = 0.5 # Minimum line width 434 | for edge in G.edges(): 435 | x0, y0 = pos[edge[0]] 436 | x1, y1 = pos[edge[1]] 437 | weight = G.edges[edge]['weight'] 438 | # Ensure weight is non-negative 439 | if weight < 0: 440 | weight = 0.0 441 | line_width = max(weight * 5, min_width) 442 | edge_trace.append(go.Scatter( 443 | x=[x0, x1], 444 | y=[y0, y1], 445 | line=dict(width=line_width, color='#888'), 446 | hoverinfo='none', 447 | mode='lines')) 448 | 449 | # Create node traces for ETFs and Sectors 450 | etf_trace = go.Scatter( 451 | x=[], 452 | y=[], 453 | text=[], 454 | mode='markers', 455 | hoverinfo='text', 456 | marker=dict( 457 | showscale=True, 458 | colorscale='YlGnBu', 459 | color=[], 460 | size=[], 461 | colorbar=dict( 462 | thickness=15, 463 | title='ETF Node Weight', 464 | xanchor='left', 465 | titleside='right' 466 | ), 467 | line_width=2)) 468 | 469 | sector_trace = go.Scatter( 470 | x=[], 471 | y=[], 472 | text=[], 473 | mode='markers', 474 | hoverinfo='text', 475 | marker=dict( 476 | color='red', 477 | size=20, 478 | line_width=2)) 479 | 480 | # Populate node traces 481 | for node in G.nodes(): 482 | x, y = pos[node] 483 | node_data = G.nodes[node] 484 | node_type = node_data.get('type', '') 485 | if node_type == 'ETF': 486 | etf_trace['x'] += tuple([x]) 487 | etf_trace['y'] += tuple([y]) 488 | node_weight = node_data.get('node_weight', 0.0) 489 | etf_trace['text'] += tuple([f"{node}
{node_data.get('name', '')}
Score: {node_weight:.4f}"]) 490 | etf_trace['marker']['color'] += tuple([node_weight]) 491 | etf_trace['marker']['size'] += tuple([10]) 492 | elif node_type == 'Sector': 493 | sector_trace['x'] += tuple([x]) 494 | sector_trace['y'] += tuple([y]) 495 | node_weight = node_data.get('node_weight', 0.0) 496 | sector_trace['text'] += tuple([f"{node}
Performance: {node_weight:.2f}%"]) 497 | else: 498 | # Skip nodes without a valid 'type' 499 | continue 500 | 501 | # Create the figure 502 | fig = go.Figure(data=edge_trace + [etf_trace, sector_trace], 503 | layout=go.Layout( 504 | title='
ETF-Sector Graph', 505 | titlefont_size=16, 506 | showlegend=False, 507 | hovermode='closest', 508 | margin=dict(b=20, l=5, r=5, t=40), 509 | annotations=[dict( 510 | text="", 511 | showarrow=False, 512 | xref="paper", yref="paper")], 513 | xaxis=dict(showgrid=False, zeroline=False, showticklabels=False), 514 | yaxis=dict(showgrid=False, zeroline=False, showticklabels=False)) 515 | ) 516 | 517 | # Save the graph to an HTML file 518 | output_file = 'etf_sector_graph.html' 519 | plot(fig, filename=output_file, auto_open=True) 520 | logging.info(f"Graph saved to {output_file}") 521 | 522 | def main(): 523 | """ 524 | Main function to execute the ETF analysis and graph creation. 525 | """ 526 | # Read ETF list from 'etfs.txt' 527 | logging.info("Reading ETF list from 'etfs.txt'...") 528 | etf_symbols = get_etf_list_from_file() 529 | 530 | # Limit the number of ETFs to process to stay within rate limits 531 | max_etfs = 1000 # Adjust as needed 532 | etf_symbols = etf_symbols[:max_etfs] 533 | logging.info(f"Processing top {len(etf_symbols)} ETFs.") 534 | 535 | # Initialize data structures 536 | G = nx.Graph() 537 | etf_data_list = [] 538 | sector_nodes = set() 539 | sector_performance = get_sector_performance() 540 | # Create a dictionary mapping sector names to their performance 541 | sector_performance_dict = dict(zip(sector_performance['sector'], sector_performance['changesPercentage'])) 542 | 543 | # Process each ETF concurrently 544 | logging.info("Processing ETFs...") 545 | with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor: 546 | # Submit tasks to the executor 547 | future_to_symbol = {executor.submit(fetch_etf_data, symbol): symbol for symbol in etf_symbols} 548 | for future in concurrent.futures.as_completed(future_to_symbol): 549 | symbol = future_to_symbol[future] 550 | try: 551 | result = future.result() 552 | if result is None: 553 | continue 554 | symbol, etf_info, sector_weightings, historical_performance = result 555 | 556 | # Add ETF node with attributes 557 | aum = etf_info.get('aum', 0) 558 | avg_volume = etf_info.get('avgVolume', 0) 559 | expense_ratio = etf_info.get('expenseRatio', 0.0) 560 | holdings_count = etf_info.get('holdingsCount', 0) 561 | G.add_node(symbol, type='ETF', aum=aum, 562 | avg_volume=avg_volume, 563 | expense_ratio=expense_ratio, 564 | name=etf_info.get('name', ''), 565 | holdings_count=holdings_count, 566 | historical_performance=historical_performance) 567 | 568 | # Store ETF data 569 | etf_data_list.append({ 570 | 'symbol': symbol, 571 | 'name': etf_info.get('name', ''), 572 | 'aum': aum, 573 | 'avg_volume': avg_volume, 574 | 'expense_ratio': expense_ratio, 575 | 'historical_performance': historical_performance, 576 | 'holdings_count': holdings_count 577 | }) 578 | 579 | # Process sector weightings 580 | for sector in sector_weightings: 581 | sector_name = sector['sector'] 582 | weight_percentage = sector['weightPercentage'] 583 | 584 | # Add sector node if not already added 585 | if sector_name not in sector_nodes: 586 | sector_nodes.add(sector_name) 587 | # Get sector performance 588 | sector_perf = sector_performance_dict.get(sector_name, 0.0) 589 | G.add_node(sector_name, type='Sector', performance=sector_perf) 590 | 591 | # Add edge between ETF and sector with weight 592 | G.add_edge(symbol, sector_name, weight=weight_percentage) 593 | 594 | except Exception as exc: 595 | logging.error(f'ETF {symbol} generated an exception: {exc}') 596 | continue 597 | 598 | # Convert etf_data_list to DataFrame (optional, not used in further computations) 599 | etf_data = pd.DataFrame(etf_data_list) 600 | 601 | # Compute node weights 602 | compute_node_weights(G) 603 | 604 | # Compute centrality measures 605 | compute_centrality_measures(G) 606 | 607 | # Find the most central ETFs 608 | find_most_central_etfs(G) 609 | 610 | # Find the most important nodes 611 | find_most_important_nodes(G, top_n=10) 612 | 613 | # Find the best ETFs per sector 614 | find_best_etfs_per_sector(G) 615 | 616 | # Visualize the graph and save it to an HTML file 617 | visualize_graph(G) 618 | 619 | def fetch_etf_data(symbol): 620 | """ 621 | Fetches ETF info, sector weightings, and historical performance for a given symbol. 622 | 623 | Args: 624 | symbol (str): ETF ticker symbol. 625 | 626 | Returns: 627 | tuple: (symbol, etf_info, sector_weightings, historical_performance) or None if failed. 628 | """ 629 | etf_info = get_etf_info(symbol) 630 | if etf_info is None: 631 | return None 632 | 633 | sector_weightings = get_etf_sector_weightings(symbol) 634 | if sector_weightings is None: 635 | return None 636 | 637 | historical_performance = get_etf_historical_performance(symbol, period='3months') 638 | if historical_performance is None: 639 | historical_performance = 0.0 640 | 641 | # Ensure numerical fields are properly typed and not None 642 | def safe_float(value): 643 | try: 644 | return float(value) 645 | except (TypeError, ValueError): 646 | return 0.0 647 | 648 | def safe_int(value): 649 | try: 650 | return int(value) 651 | except (TypeError, ValueError): 652 | return 0 653 | 654 | aum = safe_float(etf_info.get('aum')) 655 | avg_volume = safe_float(etf_info.get('avgVolume')) 656 | expense_ratio = safe_float(etf_info.get('expenseRatio')) 657 | holdings_count = safe_int(etf_info.get('holdingsCount')) 658 | 659 | etf_info['aum'] = aum 660 | etf_info['avgVolume'] = avg_volume 661 | etf_info['expenseRatio'] = expense_ratio 662 | etf_info['holdingsCount'] = holdings_count 663 | 664 | # Ensure that sector weightings are properly formatted 665 | for sector in sector_weightings: 666 | weight_str = sector.get('weightPercentage', '0%').replace('%', '').strip() 667 | try: 668 | weight_percentage = float(weight_str) / 100 669 | except ValueError: 670 | weight_percentage = 0.0 671 | # Ensure weight percentage is between 0 and 1 672 | if weight_percentage < 0: 673 | logging.warning(f"Negative sector weight detected for ETF: {symbol}, Sector: {sector.get('sector', '')}. Setting to 0.") 674 | weight_percentage = 0.0 675 | elif weight_percentage > 1: 676 | logging.warning(f"Sector weight exceeds 100% for ETF: {symbol}, Sector: {sector.get('sector', '')}. Normalizing.") 677 | weight_percentage = 1.0 678 | sector['weightPercentage'] = weight_percentage 679 | 680 | return (symbol, etf_info, sector_weightings, historical_performance) 681 | 682 | if __name__ == "__main__": 683 | main() 684 | -------------------------------------------------------------------------------- /stock_research/etfs.txt: -------------------------------------------------------------------------------- 1 | SPY 2 | IVV 3 | VOO 4 | VTI 5 | QQQ 6 | VUG 7 | VTV 8 | AGG 9 | BND 10 | IWF 11 | IJH 12 | VIG 13 | IJR 14 | VGT 15 | XLK 16 | VO 17 | IWM 18 | RSP 19 | SCHD 20 | ITOT 21 | IWD 22 | VB 23 | VYM 24 | TLT 25 | IVW 26 | QUAL 27 | SCHX 28 | SPLG 29 | XLF 30 | XLV 31 | MUB 32 | VV 33 | IWB 34 | XLE 35 | VNQ 36 | IWR 37 | JEPI 38 | DIA 39 | IVE 40 | QQQM 41 | VTEB 42 | BSV 43 | BIL 44 | MBB 45 | IEF 46 | SCHG 47 | IUSB 48 | SCHB 49 | DFAC 50 | VGIT 51 | VBR 52 | DGRO 53 | SPYG 54 | LQD 55 | GOVT 56 | JPST 57 | SGOV 58 | COWZ 59 | SPYV 60 | SMH 61 | TQQQ 62 | USMV 63 | MGK 64 | MDY 65 | VONG 66 | SHY 67 | SDY 68 | IGSB 69 | XLY 70 | VGSH 71 | IUSG 72 | VXF 73 | DVY 74 | USHY 75 | XLC 76 | SHV 77 | VHT 78 | XLU 79 | VBK 80 | VMBS 81 | SCHA 82 | VOE 83 | XLP 84 | FNDX 85 | JEPQ 86 | USFR 87 | MOAT 88 | PFF 89 | SOXX 90 | IWP 91 | IWV 92 | DGRW 93 | IEI 94 | HYG 95 | VCLT 96 | VOT 97 | VGLT 98 | OEF 99 | AVUV 100 | IWS 101 | ESGU 102 | VOOG 103 | GSLC 104 | NOBL 105 | DYNF 106 | IWN 107 | FTEC 108 | RDVY 109 | USIG 110 | IWY 111 | IWO 112 | SCHV 113 | SCHM 114 | VTIP 115 | SPSM 116 | SPHQ 117 | VTWO 118 | SPMD 119 | DFUV 120 | CGDV 121 | HDV 122 | SCHO 123 | SCHP 124 | DFUS 125 | SPTL 126 | DFAT 127 | MTUM 128 | VFH 129 | SCHR 130 | FVD 131 | SPIB 132 | ESGV 133 | VONV 134 | IJK 135 | SPTM 136 | CALF 137 | FNDA 138 | FTCS 139 | AMLP 140 | DFAS 141 | SUB 142 | MGV 143 | PAVE 144 | SPAB 145 | SCHZ 146 | JNK 147 | QYLD 148 | VDE 149 | SPSB 150 | XLRE 151 | SCHH 152 | STIP 153 | CGGR 154 | IJJ 155 | TLH 156 | SPLV 157 | SCHI 158 | PRF 159 | AVUS 160 | IBB 161 | QLD 162 | DUHP 163 | VDC 164 | VLUE 165 | BKLN 166 | TFLO 167 | XBI 168 | IJS 169 | IGV 170 | ONEQ 171 | CIBR 172 | XLG 173 | SPYD 174 | SPTI 175 | VPU 176 | DFAU 177 | IJT 178 | ITA 179 | IOO 180 | MGC 181 | FTSM 182 | SDVY 183 | TMF 184 | FDN 185 | SHYG 186 | BLV 187 | XMHQ 188 | VCR 189 | XLB 190 | SPTS 191 | FNGU 192 | SPHY 193 | PBUS 194 | GBIL 195 | FPE 196 | VIS 197 | NVDL 198 | ARKK 199 | SPMB 200 | IGM 201 | ICSH 202 | FIXD 203 | OMFL 204 | BUFR 205 | VOOV 206 | SSO 207 | SPXL 208 | VONE 209 | JQUA 210 | IYR 211 | BOND 212 | IHI 213 | SJNK 214 | DSI 215 | JMBS 216 | AVLV 217 | LMBS 218 | VUSB 219 | PGX 220 | PPA 221 | FDL 222 | DLN 223 | SPGP 224 | IXJ 225 | TBIL 226 | VOX 227 | ISTB 228 | UPRO 229 | BOXX 230 | EDV 231 | JHMM 232 | BSCP 233 | QTEC 234 | BBUS 235 | BSCQ 236 | REET 237 | SLYV 238 | RWL 239 | SCHK 240 | DFSV 241 | FEZ 242 | SHM 243 | FDVV 244 | SUSA 245 | DON 246 | CWB 247 | CGUS 248 | DIVO 249 | EAGG 250 | TFI 251 | SLYG 252 | TECL 253 | ITB 254 | XT 255 | RSPT 256 | HYLB 257 | CGCP 258 | IYH 259 | GVI 260 | SPHD 261 | KNG 262 | KRE 263 | CMF 264 | IWX 265 | TOTL 266 | BILS 267 | IYF 268 | PTLC 269 | HYD 270 | ANGL 271 | SKYY 272 | VAW 273 | JGRO 274 | FHLC 275 | TDIV 276 | PZA 277 | VIOO 278 | BKLC 279 | XYLD 280 | IFRA 281 | IBDR 282 | IGLB 283 | NUGO 284 | IBDQ 285 | USRT 286 | HYMB 287 | EMLP 288 | BSCO 289 | MDYG 290 | VTHR 291 | SPMO 292 | DFLV 293 | MDYV 294 | XOP 295 | USMC 296 | SQQQ 297 | IBDS 298 | PRFZ 299 | XMMO 300 | PFFD 301 | FAS 302 | GSUS 303 | XAR 304 | ILCG 305 | TNA 306 | UITB 307 | XHB 308 | IBDP 309 | PHO 310 | IVOO 311 | IBDT 312 | IYY 313 | VNLA 314 | BSCR 315 | ICF 316 | IMCG 317 | LRGF 318 | FTSL 319 | AOR 320 | ICVT 321 | TSLL 322 | SLQD 323 | IBTF 324 | DSTL 325 | SPYI 326 | FMB 327 | PABU 328 | KOMP 329 | DES 330 | FXR 331 | MLPX 332 | BKAG 333 | KBE 334 | BSCS 335 | RPV 336 | EUFN 337 | SPYX 338 | PFXF 339 | QQEW 340 | TBLL 341 | IBTE 342 | SECT 343 | QDF 344 | ITM 345 | IBDU -------------------------------------------------------------------------------- /stock_research/individuals.txt: -------------------------------------------------------------------------------- 1 | A 2 | AA 3 | AACG 4 | AACT 5 | AADI 6 | AAL 7 | AAM 8 | AAME 9 | AAOI 10 | AAON 11 | AAP 12 | AAPL 13 | AAT 14 | AB 15 | ABAT 16 | ABBV 17 | ABCB 18 | ABCL 19 | ABEO 20 | ABEV 21 | ABG 22 | ABL 23 | ABLLL 24 | ABLLW 25 | ABLV 26 | ABLVW 27 | ABM 28 | ABNB 29 | ABOS 30 | ABR 31 | ABSI 32 | ABT 33 | ABTS 34 | ABUS 35 | ABVC 36 | ABVE 37 | ABVEW 38 | ABVX 39 | AC 40 | ACA 41 | ACAB 42 | ACABU 43 | ACABW 44 | ACAD 45 | ACB 46 | ACCD 47 | ACCO 48 | ACDC 49 | ACEL 50 | ACET 51 | ACGL 52 | ACGLN 53 | ACGLO 54 | ACHC 55 | ACHL 56 | ACHR 57 | ACHV 58 | ACI 59 | ACIC 60 | ACIU 61 | ACIW 62 | ACLS 63 | ACLX 64 | ACM 65 | ACMR 66 | ACN 67 | ACNB 68 | ACNT 69 | ACON 70 | ACONW 71 | ACP 72 | ACR 73 | ACRE 74 | ACRS 75 | ACRV 76 | ACST 77 | ACT 78 | ACTG 79 | ACTU 80 | ACU 81 | ACV 82 | ACVA 83 | ACXP 84 | ADAG 85 | ADAP 86 | ADBE 87 | ADC 88 | ADCT 89 | ADD 90 | ADEA 91 | ADGM 92 | ADI 93 | ADIL 94 | ADM 95 | ADMA 96 | ADN 97 | ADNT 98 | ADNWW 99 | ADP 100 | ADPT 101 | ADSE 102 | ADSEW 103 | ADSK 104 | ADT 105 | ADTN 106 | ADTX 107 | ADUS 108 | ADV 109 | ADVM 110 | ADVWW 111 | ADX 112 | ADXN 113 | AE 114 | AEAE 115 | AEAEU 116 | AEAEW 117 | AEE 118 | AEF 119 | AEFC 120 | AEG 121 | AEHL 122 | AEHR 123 | AEI 124 | AEIS 125 | AEM 126 | AEMD 127 | AENT 128 | AENTW 129 | AEO 130 | AEON 131 | AEP 132 | AER 133 | AERT 134 | AERTW 135 | AES 136 | AESI 137 | AEVA 138 | AEYE 139 | AFB 140 | AFBI 141 | AFCG 142 | AFG 143 | AFGB 144 | AFGC 145 | AFGD 146 | AFGE 147 | AFJK 148 | AFJKR 149 | AFJKU 150 | AFL 151 | AFMD 152 | AFRI 153 | AFRIW 154 | AFRM 155 | AFYA 156 | AG 157 | AGAE 158 | AGCO 159 | AGD 160 | AGEN 161 | AGFY 162 | AGI 163 | AGIO 164 | AGL 165 | AGM 166 | AGMH 167 | AGNC 168 | AGNCL 169 | AGNCM 170 | AGNCN 171 | AGNCO 172 | AGNCP 173 | AGO 174 | AGR 175 | AGRI 176 | AGRO 177 | AGS 178 | AGX 179 | AGYS 180 | AHCO 181 | AHG 182 | AHH 183 | AHL 184 | AHR 185 | AHT 186 | AI 187 | AIEV 188 | AIFF 189 | AIG 190 | AIHS 191 | AILE 192 | AILEW 193 | AIM 194 | AIMAU 195 | AIMAW 196 | AIMBU 197 | AIMD 198 | AIN 199 | AIO 200 | AIOT 201 | AIP 202 | AIR 203 | AIRE 204 | AIRG 205 | AIRI 206 | AIRJ 207 | AIRJW 208 | AIRS 209 | AIRT 210 | AIRTP 211 | AISP 212 | AISPW 213 | AIT 214 | AITR 215 | AITRU 216 | AIV 217 | AIXI 218 | AIZ 219 | AIZN 220 | AJG 221 | AJX 222 | AKA 223 | AKAM 224 | AKAN 225 | AKBA 226 | AKO 227 | AKR 228 | AKRO 229 | AKTS 230 | AKTX 231 | AKYA 232 | AL 233 | ALAB 234 | ALAR 235 | ALB 236 | ALBT 237 | ALC 238 | ALCE 239 | ALCO 240 | ALCY 241 | ALCYU 242 | ALCYW 243 | ALDX 244 | ALE 245 | ALEC 246 | ALEX 247 | ALF 248 | ALFUU 249 | ALFUW 250 | ALG 251 | ALGM 252 | ALGN 253 | ALGS 254 | ALGT 255 | ALHC 256 | ALIT 257 | ALK 258 | ALKS 259 | ALKT 260 | ALL 261 | ALLE 262 | ALLK 263 | ALLO 264 | ALLR 265 | ALLT 266 | ALLY 267 | ALMS 268 | ALNT 269 | ALNY 270 | ALOT 271 | ALPP 272 | ALRM 273 | ALRN 274 | ALRS 275 | ALSA 276 | ALSAW 277 | ALSN 278 | ALT 279 | ALTG 280 | ALTI 281 | ALTM 282 | ALTO 283 | ALTR 284 | ALTS 285 | ALUR 286 | ALV 287 | ALVO 288 | ALVOW 289 | ALVR 290 | ALX 291 | ALXO 292 | ALZN 293 | AM 294 | AMAL 295 | AMAT 296 | AMBA 297 | AMBC 298 | AMBI 299 | AMBO 300 | AMBP 301 | AMC 302 | AMCR 303 | AMCX 304 | AMD 305 | AME 306 | AMED 307 | AMG 308 | AMGN 309 | AMH 310 | AMIX 311 | AMKR 312 | AMLI 313 | AMLX 314 | AMN 315 | AMP 316 | AMPG 317 | AMPGW 318 | AMPH 319 | AMPL 320 | AMPS 321 | AMPX 322 | AMPY 323 | AMR 324 | AMRC 325 | AMRK 326 | AMRN 327 | AMRX 328 | AMS 329 | AMSC 330 | AMSF 331 | AMST 332 | AMT 333 | AMTB 334 | AMTD 335 | AMTM 336 | AMTX 337 | AMWD 338 | AMWL 339 | AMX 340 | AMZN 341 | AN 342 | ANAB 343 | ANDE 344 | ANEB 345 | ANET 346 | ANF 347 | ANG 348 | ANGH 349 | ANGI 350 | ANGO 351 | ANIK 352 | ANIP 353 | ANIX 354 | ANL 355 | ANNX 356 | ANRO 357 | ANSC 358 | ANSCW 359 | ANSS 360 | ANTE 361 | ANTX 362 | ANVS 363 | ANY 364 | AOD 365 | AOMN 366 | AOMR 367 | AON 368 | AORT 369 | AOS 370 | AOSL 371 | AOUT 372 | AP 373 | APA 374 | APAM 375 | APCX 376 | APCXW 377 | APD 378 | APDN 379 | APEI 380 | APG 381 | APGE 382 | APH 383 | API 384 | APLD 385 | APLE 386 | APLM 387 | APLMW 388 | APLS 389 | APLT 390 | APM 391 | APO 392 | APOG 393 | APOS 394 | APP 395 | APPF 396 | APPN 397 | APPS 398 | APRE 399 | APT 400 | APTO 401 | APTV 402 | APVO 403 | APWC 404 | APXI 405 | APYX 406 | AQB 407 | AQMS 408 | AQN 409 | AQNB 410 | AQST 411 | AQU 412 | AR 413 | ARAY 414 | ARBB 415 | ARBE 416 | ARBEW 417 | ARBK 418 | ARBKL 419 | ARC 420 | ARCB 421 | ARCC 422 | ARCH 423 | ARCO 424 | ARCT 425 | ARDC 426 | ARDT 427 | ARDX 428 | ARE 429 | AREB 430 | AREBW 431 | AREC 432 | AREN 433 | ARES 434 | ARGD 435 | ARGO 436 | ARGX 437 | ARHS 438 | ARI 439 | ARIS 440 | ARKO 441 | ARKOW 442 | ARKR 443 | ARL 444 | ARLO 445 | ARLP 446 | ARM 447 | ARMK 448 | ARMN 449 | ARMP 450 | AROC 451 | AROW 452 | ARQ 453 | ARQQ 454 | ARQQW 455 | ARQT 456 | ARR 457 | ARRY 458 | ARTL 459 | ARTNA 460 | ARTV 461 | ARTW 462 | ARVN 463 | ARW 464 | ARWR 465 | AS 466 | ASA 467 | ASAI 468 | ASAN 469 | ASB 470 | ASBA 471 | ASC 472 | ASG 473 | ASGI 474 | ASGN 475 | ASH 476 | ASIX 477 | ASLE 478 | ASM 479 | ASMB 480 | ASML 481 | ASND 482 | ASNS 483 | ASO 484 | ASPI 485 | ASPN 486 | ASPS 487 | ASR 488 | ASRT 489 | ASRV 490 | ASST 491 | ASTC 492 | ASTE 493 | ASTH 494 | ASTI 495 | ASTL 496 | ASTLW 497 | ASTS 498 | ASUR 499 | ASX 500 | ASYS 501 | ATAI 502 | ATAT 503 | ATCH 504 | ATCO 505 | ATCOL 506 | ATEC 507 | ATEK 508 | ATEN 509 | ATER 510 | ATEX 511 | ATGE 512 | ATGL 513 | ATH 514 | ATHA 515 | ATHE 516 | ATHM 517 | ATHS 518 | ATI 519 | ATIF 520 | ATIP 521 | ATKR 522 | ATLC 523 | ATLCL 524 | ATLCP 525 | ATLCZ 526 | ATLO 527 | ATLX 528 | ATMC 529 | ATMCR 530 | ATMCW 531 | ATMU 532 | ATMV 533 | ATMVR 534 | ATNF 535 | ATNFW 536 | ATNI 537 | ATNM 538 | ATO 539 | ATOM 540 | ATOS 541 | ATPC 542 | ATR 543 | ATRA 544 | ATRC 545 | ATRO 546 | ATS 547 | ATSG 548 | ATUS 549 | ATXG 550 | ATXI 551 | ATXS 552 | ATYR 553 | AU 554 | AUB 555 | AUBN 556 | AUDC 557 | AUID 558 | AUMN 559 | AUNA 560 | AUPH 561 | AUR 562 | AURA 563 | AUROW 564 | AUST 565 | AUTL 566 | AUUD 567 | AUUDW 568 | AVA 569 | AVAH 570 | AVAL 571 | AVAV 572 | AVB 573 | AVBP 574 | AVD 575 | AVDL 576 | AVDX 577 | AVGO 578 | AVGR 579 | AVIR 580 | AVK 581 | AVNS 582 | AVNT 583 | AVNW 584 | AVO 585 | AVPT 586 | AVPTW 587 | AVT 588 | AVTE 589 | AVTR 590 | AVTX 591 | AVXL 592 | AVY 593 | AWF 594 | AWH 595 | AWI 596 | AWK 597 | AWP 598 | AWR 599 | AWRE 600 | AWX 601 | AX 602 | AXDX 603 | AXGN 604 | AXIL 605 | AXL 606 | AXNX 607 | AXON 608 | AXP 609 | AXR 610 | AXS 611 | AXSM 612 | AXTA 613 | AXTI 614 | AY 615 | AYI 616 | AYRO 617 | AYTU 618 | AZ 619 | AZEK 620 | AZI 621 | AZN 622 | AZO 623 | AZPN 624 | AZTA 625 | AZTR 626 | AZUL 627 | AZZ 628 | B 629 | BA 630 | BABA 631 | BAC 632 | BACK 633 | BAER 634 | BAERW 635 | BAFN 636 | BAH 637 | BAK 638 | BALL 639 | BALY 640 | BAM 641 | BANC 642 | BAND 643 | BANF 644 | BANFP 645 | BANL 646 | BANR 647 | BANX 648 | BAOS 649 | BAP 650 | BARK 651 | BASE 652 | BATL 653 | BATRA 654 | BATRK 655 | BAX 656 | BAYA 657 | BAYAR 658 | BAYAU 659 | BB 660 | BBAI 661 | BBAR 662 | BBCP 663 | BBD 664 | BBDC 665 | BBDO 666 | BBGI 667 | BBIO 668 | BBLG 669 | BBN 670 | BBSI 671 | BBU 672 | BBUC 673 | BBVA 674 | BBW 675 | BBWI 676 | BBY 677 | BC 678 | BCAB 679 | BCAL 680 | BCAN 681 | BCAT 682 | BCAX 683 | BCBP 684 | BCC 685 | BCDA 686 | BCE 687 | BCG 688 | BCGWW 689 | BCH 690 | BCLI 691 | BCML 692 | BCO 693 | BCOV 694 | BCOW 695 | BCPC 696 | BCRX 697 | BCS 698 | BCSA 699 | BCSAU 700 | BCSAW 701 | BCSF 702 | BCTX 703 | BCTXW 704 | BCV 705 | BCX 706 | BCYC 707 | BDC 708 | BDJ 709 | BDL 710 | BDMD 711 | BDMDW 712 | BDN 713 | BDRX 714 | BDSX 715 | BDTX 716 | BDX 717 | BE 718 | BEAM 719 | BEAT 720 | BEATW 721 | BECN 722 | BEDU 723 | BEEM 724 | BEEP 725 | BEKE 726 | BELFA 727 | BELFB 728 | BEN 729 | BENF 730 | BENFW 731 | BEP 732 | BEPC 733 | BEPH 734 | BEPI 735 | BEPJ 736 | BERY 737 | BEST 738 | BETR 739 | BETRW 740 | BF 741 | BFAC 742 | BFAM 743 | BFC 744 | BFH 745 | BFIN 746 | BFK 747 | BFLY 748 | BFRG 749 | BFRGW 750 | BFRI 751 | BFRIW 752 | BFS 753 | BFST 754 | BFZ 755 | BG 756 | BGB 757 | BGC 758 | BGFV 759 | BGH 760 | BGI 761 | BGLC 762 | BGM 763 | BGNE 764 | BGR 765 | BGS 766 | BGSF 767 | BGT 768 | BGX 769 | BGY 770 | BH 771 | BHAT 772 | BHB 773 | BHC 774 | BHE 775 | BHF 776 | BHFAL 777 | BHFAM 778 | BHFAN 779 | BHFAO 780 | BHFAP 781 | BHIL 782 | BHK 783 | BHLB 784 | BHM 785 | BHP 786 | BHR 787 | BHRB 788 | BHV 789 | BHVN 790 | BIAF 791 | BIAFW 792 | BIDU 793 | BIGC 794 | BIGZ 795 | BIIB 796 | BILI 797 | BILL 798 | BIO 799 | BIOA 800 | BIOR 801 | BIOX 802 | BIP 803 | BIPC 804 | BIPH 805 | BIPI 806 | BIPJ 807 | BIRD 808 | BIRK 809 | BIT 810 | BITF 811 | BIVI 812 | BJ 813 | BJDX 814 | BJRI 815 | BK 816 | BKD 817 | BKDT 818 | BKE 819 | BKH 820 | BKHA 821 | BKHAR 822 | BKHAU 823 | BKKT 824 | BKN 825 | BKNG 826 | BKR 827 | BKSY 828 | BKT 829 | BKTI 830 | BKU 831 | BKV 832 | BKYI 833 | BL 834 | BLAC 835 | BLBD 836 | BLBX 837 | BLCO 838 | BLD 839 | BLDE 840 | BLDEW 841 | BLDP 842 | BLDR 843 | BLE 844 | BLEUR 845 | BLEUW 846 | BLFS 847 | BLFY 848 | BLIN 849 | BLK 850 | BLKB 851 | BLMN 852 | BLMZ 853 | BLND 854 | BLNK 855 | BLRX 856 | BLTE 857 | BLUE 858 | BLW 859 | BLX 860 | BLZE 861 | BMA 862 | BMBL 863 | BME 864 | BMEA 865 | BMEZ 866 | BMI 867 | BML 868 | BMN 869 | BMO 870 | BMR 871 | BMRA 872 | BMRC 873 | BMRN 874 | BMTX 875 | BMY 876 | BN 877 | BNAI 878 | BNAIW 879 | BNED 880 | BNGO 881 | BNH 882 | BNIX 883 | BNIXR 884 | BNIXW 885 | BNJ 886 | BNL 887 | BNOX 888 | BNR 889 | BNRG 890 | BNS 891 | BNT 892 | BNTC 893 | BNTX 894 | BNY 895 | BNZI 896 | BNZIW 897 | BOC 898 | BOCN 899 | BOCNU 900 | BOCNW 901 | BODI 902 | BOE 903 | BOF 904 | BOH 905 | BOKF 906 | BOLD 907 | BOLT 908 | BON 909 | BOOM 910 | BOOT 911 | BORR 912 | BOSC 913 | BOTJ 914 | BOW 915 | BOWL 916 | BOWN 917 | BOWNR 918 | BOWNU 919 | BOX 920 | BOXL 921 | BP 922 | BPMC 923 | BPOP 924 | BPOPM 925 | BPRN 926 | BPT 927 | BPTH 928 | BPYPM 929 | BPYPN 930 | BPYPO 931 | BPYPP 932 | BQ 933 | BR 934 | BRAC 935 | BRAG 936 | BRBR 937 | BRBS 938 | BRC 939 | BRCC 940 | BRDG 941 | BREA 942 | BRFH 943 | BRFS 944 | BRID 945 | BRK 946 | BRKH 947 | BRKHU 948 | BRKHW 949 | BRKL 950 | BRKR 951 | BRLS 952 | BRLSW 953 | BRLT 954 | BRN 955 | BRNS 956 | BRO 957 | BROG 958 | BROGW 959 | BROS 960 | BRSP 961 | BRT 962 | BRTX 963 | BRW 964 | BRX 965 | BRY 966 | BRZE 967 | BSAC 968 | BSBK 969 | BSBR 970 | BSET 971 | BSFC 972 | BSIG 973 | BSII 974 | BSIIU 975 | BSIIW 976 | BSL 977 | BSLK 978 | BSLKW 979 | BSM 980 | BSRR 981 | BST 982 | BSTZ 983 | BSVN 984 | BSX 985 | BSY 986 | BTA 987 | BTAI 988 | BTBD 989 | BTBDW 990 | BTBT 991 | BTCM 992 | BTCS 993 | BTCT 994 | BTCTW 995 | BTDR 996 | BTE 997 | BTG 998 | BTI 999 | BTM 1000 | BTMD 1001 | BTMWW 1002 | BTO 1003 | BTOC 1004 | BTOG 1005 | BTSG 1006 | BTSGU 1007 | BTT 1008 | BTTR 1009 | BTU 1010 | BTZ 1011 | BUD 1012 | BUI 1013 | BUJA 1014 | BUR 1015 | BURL 1016 | BURU 1017 | BUSE 1018 | BV 1019 | BVFL 1020 | BVN 1021 | BVS 1022 | BW 1023 | BWA 1024 | BWAY 1025 | BWB 1026 | BWBBP 1027 | BWEN 1028 | BWFG 1029 | BWG 1030 | BWIN 1031 | BWLP 1032 | BWMN 1033 | BWMX 1034 | BWNB 1035 | BWSN 1036 | BWXT 1037 | BX 1038 | BXC 1039 | BXMT 1040 | BXMX 1041 | BXP 1042 | BXSL 1043 | BY 1044 | BYD 1045 | BYFC 1046 | BYM 1047 | BYND 1048 | BYNO 1049 | BYNOW 1050 | BYON 1051 | BYRN 1052 | BYSI 1053 | BYU 1054 | BZ 1055 | BZFD 1056 | BZFDW 1057 | BZH 1058 | BZUN 1059 | C 1060 | CAAP 1061 | CAAS 1062 | CABA 1063 | CABO 1064 | CAC 1065 | CACC 1066 | CACI 1067 | CADE 1068 | CADL 1069 | CAE 1070 | CAF 1071 | CAG 1072 | CAH 1073 | CAKE 1074 | CAL 1075 | CALC 1076 | CALM 1077 | CALX 1078 | CAMP 1079 | CAMT 1080 | CAN 1081 | CANF 1082 | CANG 1083 | CAPL 1084 | CAPNU 1085 | CAPR 1086 | CAPT 1087 | CAPTW 1088 | CAR 1089 | CARA 1090 | CARE 1091 | CARG 1092 | CARM 1093 | CARR 1094 | CARS 1095 | CART 1096 | CARV 1097 | CASH 1098 | CASI 1099 | CASS 1100 | CASY 1101 | CAT 1102 | CATO 1103 | CATX 1104 | CATY 1105 | CAVA 1106 | CB 1107 | CBAN 1108 | CBAT 1109 | CBFV 1110 | CBL 1111 | CBLL 1112 | CBNA 1113 | CBNK 1114 | CBRE 1115 | CBRG 1116 | CBRL 1117 | CBSH 1118 | CBT 1119 | CBU 1120 | CBUS 1121 | CBZ 1122 | CC 1123 | CCAP 1124 | CCB 1125 | CCBG 1126 | CCCC 1127 | CCCS 1128 | CCD 1129 | CCEC 1130 | CCEL 1131 | CCEP 1132 | CCG 1133 | CCI 1134 | CCIA 1135 | CCIF 1136 | CCIRU 1137 | CCIX 1138 | CCIXU 1139 | CCIXW 1140 | CCJ 1141 | CCK 1142 | CCL 1143 | CCLD 1144 | CCLDO 1145 | CCLDP 1146 | CCM 1147 | CCNE 1148 | CCNEP 1149 | CCO 1150 | CCOI 1151 | CCRD 1152 | CCRN 1153 | CCS 1154 | CCSI 1155 | CCTG 1156 | CCTS 1157 | CCTSU 1158 | CCTSW 1159 | CCU 1160 | CCZ 1161 | CDAQ 1162 | CDAQU 1163 | CDE 1164 | CDIO 1165 | CDIOW 1166 | CDLR 1167 | CDLX 1168 | CDMO 1169 | CDNA 1170 | CDNS 1171 | CDP 1172 | CDR 1173 | CDRE 1174 | CDRO 1175 | CDROW 1176 | CDT 1177 | CDTG 1178 | CDTTW 1179 | CDTX 1180 | CDW 1181 | CDXC 1182 | CDXS 1183 | CDZI 1184 | CDZIP 1185 | CE 1186 | CEAD 1187 | CEADW 1188 | CECO 1189 | CEE 1190 | CEG 1191 | CEIX 1192 | CELC 1193 | CELH 1194 | CELU 1195 | CELUW 1196 | CELZ 1197 | CENN 1198 | CENT 1199 | CENTA 1200 | CENX 1201 | CEP 1202 | CEPU 1203 | CERO 1204 | CEROW 1205 | CERS 1206 | CERT 1207 | CET 1208 | CETX 1209 | CETY 1210 | CEV 1211 | CEVA 1212 | CF 1213 | CFB 1214 | CFBK 1215 | CFFI 1216 | CFFN 1217 | CFFS 1218 | CFFSW 1219 | CFG 1220 | CFLT 1221 | CFR 1222 | CFSB 1223 | CG 1224 | CGA 1225 | CGABL 1226 | CGAU 1227 | CGBD 1228 | CGBDL 1229 | CGBS 1230 | CGBSW 1231 | CGC 1232 | CGEM 1233 | CGEN 1234 | CGNT 1235 | CGNX 1236 | CGO 1237 | CGON 1238 | CGTX 1239 | CHCI 1240 | CHCO 1241 | CHCT 1242 | CHD 1243 | CHDN 1244 | CHE 1245 | CHEB 1246 | CHEF 1247 | CHEK 1248 | CHGG 1249 | CHH 1250 | CHI 1251 | CHKP 1252 | CHMG 1253 | CHMI 1254 | CHN 1255 | CHNR 1256 | CHPT 1257 | CHR 1258 | CHRD 1259 | CHRO 1260 | CHRS 1261 | CHRW 1262 | CHSCL 1263 | CHSCM 1264 | CHSCN 1265 | CHSCO 1266 | CHSCP 1267 | CHT 1268 | CHTR 1269 | CHW 1270 | CHWY 1271 | CHX 1272 | CHY 1273 | CI 1274 | CIA 1275 | CIB 1276 | CICB 1277 | CIEN 1278 | CIF 1279 | CIFR 1280 | CIFRW 1281 | CIG 1282 | CIGI 1283 | CII 1284 | CIK 1285 | CIM 1286 | CIMN 1287 | CIMO 1288 | CINF 1289 | CING 1290 | CINGW 1291 | CINT 1292 | CIO 1293 | CION 1294 | CISO 1295 | CISS 1296 | CITE 1297 | CITEW 1298 | CIVB 1299 | CIVI 1300 | CIX 1301 | CJET 1302 | CJJD 1303 | CKPT 1304 | CKX 1305 | CL 1306 | CLAR 1307 | CLB 1308 | CLBK 1309 | CLBR 1310 | CLBT 1311 | CLCO 1312 | CLDI 1313 | CLDT 1314 | CLDX 1315 | CLEU 1316 | CLF 1317 | CLFD 1318 | CLGN 1319 | CLH 1320 | CLIK 1321 | CLIR 1322 | CLLS 1323 | CLM 1324 | CLMB 1325 | CLMT 1326 | CLNE 1327 | CLNN 1328 | CLNNW 1329 | CLOV 1330 | CLPR 1331 | CLPS 1332 | CLPT 1333 | CLRB 1334 | CLRC 1335 | CLRCW 1336 | CLRO 1337 | CLS 1338 | CLSD 1339 | CLSK 1340 | CLST 1341 | CLVT 1342 | CLW 1343 | CLWT 1344 | CLX 1345 | CLYM 1346 | CM 1347 | CMA 1348 | CMAX 1349 | CMAXW 1350 | CMBM 1351 | CMBT 1352 | CMC 1353 | CMCL 1354 | CMCM 1355 | CMCO 1356 | CMCSA 1357 | CMCT 1358 | CME 1359 | CMG 1360 | CMI 1361 | CMLS 1362 | CMMB 1363 | CMND 1364 | CMP 1365 | CMPO 1366 | CMPOW 1367 | CMPR 1368 | CMPS 1369 | CMPX 1370 | CMRE 1371 | CMRX 1372 | CMS 1373 | CMSA 1374 | CMSC 1375 | CMSD 1376 | CMT 1377 | CMTG 1378 | CMTL 1379 | CMU 1380 | CNA 1381 | CNC 1382 | CNDT 1383 | CNET 1384 | CNEY 1385 | CNF 1386 | CNFR 1387 | CNFRZ 1388 | CNH 1389 | CNI 1390 | CNK 1391 | CNL 1392 | CNM 1393 | CNMD 1394 | CNNE 1395 | CNO 1396 | CNOB 1397 | CNOBP 1398 | CNP 1399 | CNQ 1400 | CNS 1401 | CNSL 1402 | CNSP 1403 | CNTA 1404 | CNTB 1405 | CNTM 1406 | CNTX 1407 | CNTY 1408 | CNVS 1409 | CNX 1410 | CNXC 1411 | CNXN 1412 | COCH 1413 | COCHW 1414 | COCO 1415 | COCP 1416 | CODA 1417 | CODI 1418 | CODX 1419 | COE 1420 | COEP 1421 | COEPW 1422 | COF 1423 | COFS 1424 | COGT 1425 | COHN 1426 | COHR 1427 | COHU 1428 | COIN 1429 | COKE 1430 | COLB 1431 | COLD 1432 | COLL 1433 | COLM 1434 | COMM 1435 | COMP 1436 | CON 1437 | COO 1438 | COOK 1439 | COOP 1440 | COOT 1441 | COOTW 1442 | COP 1443 | COR 1444 | CORT 1445 | CORZ 1446 | CORZW 1447 | CORZZ 1448 | COSM 1449 | COST 1450 | COTY 1451 | COUR 1452 | COYA 1453 | CP 1454 | CPA 1455 | CPAC 1456 | CPAY 1457 | CPB 1458 | CPBI 1459 | CPF 1460 | CPHC 1461 | CPHI 1462 | CPIX 1463 | CPK 1464 | CPNG 1465 | CPOP 1466 | CPRI 1467 | CPRT 1468 | CPRX 1469 | CPS 1470 | CPSH 1471 | CPSS 1472 | CPT 1473 | CPTN 1474 | CPTNW 1475 | CPZ 1476 | CQP 1477 | CR 1478 | CRAI 1479 | CRBG 1480 | CRBP 1481 | CRBU 1482 | CRC 1483 | CRCT 1484 | CRD 1485 | CRDF 1486 | CRDL 1487 | CRDO 1488 | CREG 1489 | CRESW 1490 | CRESY 1491 | CREV 1492 | CREVW 1493 | CREX 1494 | CRF 1495 | CRGO 1496 | CRGOW 1497 | CRGX 1498 | CRGY 1499 | CRH 1500 | CRI 1501 | CRIS 1502 | CRK 1503 | CRKN 1504 | CRL 1505 | CRM 1506 | CRMD 1507 | CRML 1508 | CRMLW 1509 | CRMT 1510 | CRNC 1511 | CRNT 1512 | CRNX 1513 | CRON 1514 | CROX 1515 | CRS 1516 | CRSP 1517 | CRSR 1518 | CRT 1519 | CRTO 1520 | CRUS 1521 | CRVL 1522 | CRVO 1523 | CRVS 1524 | CRWD 1525 | CRWS 1526 | CSAN 1527 | CSBR 1528 | CSCI 1529 | CSCO 1530 | CSGP 1531 | CSGS 1532 | CSIQ 1533 | CSL 1534 | CSLM 1535 | CSLMR 1536 | CSLMW 1537 | CSLR 1538 | CSLRW 1539 | CSPI 1540 | CSQ 1541 | CSR 1542 | CSTE 1543 | CSTL 1544 | CSTM 1545 | CSV 1546 | CSWC 1547 | CSWCZ 1548 | CSWI 1549 | CSX 1550 | CTA 1551 | CTAS 1552 | CTBB 1553 | CTBI 1554 | CTCX 1555 | CTCXW 1556 | CTDD 1557 | CTGO 1558 | CTHR 1559 | CTKB 1560 | CTLP 1561 | CTLT 1562 | CTM 1563 | CTMX 1564 | CTNM 1565 | CTNT 1566 | CTO 1567 | CTOR 1568 | CTOS 1569 | CTRA 1570 | CTRE 1571 | CTRI 1572 | CTRM 1573 | CTRN 1574 | CTS 1575 | CTSH 1576 | CTSO 1577 | CTV 1578 | CTVA 1579 | CTXR 1580 | CUB 1581 | CUBA 1582 | CUBB 1583 | CUBE 1584 | CUBI 1585 | CUBWU 1586 | CUBWW 1587 | CUE 1588 | CUK 1589 | CULP 1590 | CURB 1591 | CURI 1592 | CURIW 1593 | CURR 1594 | CURV 1595 | CUTR 1596 | CUZ 1597 | CVAC 1598 | CVBF 1599 | CVCO 1600 | CVE 1601 | CVEO 1602 | CVGI 1603 | CVGW 1604 | CVI 1605 | CVKD 1606 | CVLG 1607 | CVLT 1608 | CVM 1609 | CVNA 1610 | CVR 1611 | CVRX 1612 | CVS 1613 | CVU 1614 | CVV 1615 | CVX 1616 | CW 1617 | CWAN 1618 | CWBC 1619 | CWCO 1620 | CWD 1621 | CWEN 1622 | CWH 1623 | CWK 1624 | CWST 1625 | CWT 1626 | CX 1627 | CXAI 1628 | CXAIW 1629 | CXDO 1630 | CXE 1631 | CXH 1632 | CXM 1633 | CXT 1634 | CXW 1635 | CYBN 1636 | CYBR 1637 | CYCC 1638 | CYCCP 1639 | CYCN 1640 | CYD 1641 | CYH 1642 | CYN 1643 | CYRX 1644 | CYTH 1645 | CYTHW 1646 | CYTK 1647 | CYTO 1648 | CZFS 1649 | CZNC 1650 | CZR 1651 | CZWI 1652 | D 1653 | DAC 1654 | DADA 1655 | DAIO 1656 | DAKT 1657 | DAL 1658 | DALN 1659 | DAN 1660 | DAO 1661 | DAR 1662 | DARE 1663 | DASH 1664 | DATS 1665 | DATSW 1666 | DAVA 1667 | DAVE 1668 | DAVEW 1669 | DAWN 1670 | DAY 1671 | DB 1672 | DBD 1673 | DBGI 1674 | DBGIW 1675 | DBI 1676 | DBL 1677 | DBRG 1678 | DBVT 1679 | DBX 1680 | DC 1681 | DCBO 1682 | DCF 1683 | DCGO 1684 | DCI 1685 | DCO 1686 | DCOM 1687 | DCOMG 1688 | DCOMP 1689 | DCTH 1690 | DD 1691 | DDC 1692 | DDD 1693 | DDI 1694 | DDL 1695 | DDOG 1696 | DDS 1697 | DDT 1698 | DE 1699 | DEA 1700 | DEC 1701 | DECA 1702 | DECAU 1703 | DECAW 1704 | DECK 1705 | DEI 1706 | DELL 1707 | DENN 1708 | DEO 1709 | DERM 1710 | DESP 1711 | DFH 1712 | DFIN 1713 | DFLI 1714 | DFLIW 1715 | DFP 1716 | DFS 1717 | DG 1718 | DGHI 1719 | DGICA 1720 | DGICB 1721 | DGII 1722 | DGLY 1723 | DGX 1724 | DH 1725 | DHAI 1726 | DHAIW 1727 | DHC 1728 | DHCNI 1729 | DHCNL 1730 | DHF 1731 | DHI 1732 | DHIL 1733 | DHR 1734 | DHT 1735 | DHX 1736 | DHY 1737 | DIAX 1738 | DIBS 1739 | DIN 1740 | DINO 1741 | DIOD 1742 | DIS 1743 | DIST 1744 | DIT 1745 | DJCO 1746 | DJT 1747 | DJTWW 1748 | DK 1749 | DKL 1750 | DKNG 1751 | DKS 1752 | DLB 1753 | DLHC 1754 | DLNG 1755 | DLO 1756 | DLPN 1757 | DLR 1758 | DLTH 1759 | DLTR 1760 | DLX 1761 | DLY 1762 | DM 1763 | DMA 1764 | DMAC 1765 | DMB 1766 | DMF 1767 | DMLP 1768 | DMO 1769 | DMRC 1770 | DNA 1771 | DNB 1772 | DNLI 1773 | DNMR 1774 | DNN 1775 | DNOW 1776 | DNP 1777 | DNTH 1778 | DNUT 1779 | DOC 1780 | DOCN 1781 | DOCS 1782 | DOCU 1783 | DOGZ 1784 | DOLE 1785 | DOMH 1786 | DOMO 1787 | DOOO 1788 | DORM 1789 | DOUG 1790 | DOV 1791 | DOW 1792 | DOX 1793 | DOYU 1794 | DPCS 1795 | DPCSW 1796 | DPG 1797 | DPRO 1798 | DPZ 1799 | DQ 1800 | DRCT 1801 | DRD 1802 | DRH 1803 | DRI 1804 | DRIO 1805 | DRMA 1806 | DRMAW 1807 | DRRX 1808 | DRS 1809 | DRTS 1810 | DRTSW 1811 | DRUG 1812 | DRVN 1813 | DSGN 1814 | DSGR 1815 | DSGX 1816 | DSL 1817 | DSM 1818 | DSP 1819 | DSS 1820 | DSU 1821 | DSWL 1822 | DSX 1823 | DSY 1824 | DSYWW 1825 | DT 1826 | DTB 1827 | DTC 1828 | DTCK 1829 | DTE 1830 | DTF 1831 | DTG 1832 | DTI 1833 | DTIL 1834 | DTM 1835 | DTSQ 1836 | DTSQR 1837 | DTSQU 1838 | DTSS 1839 | DTST 1840 | DTSTW 1841 | DTW 1842 | DUET 1843 | DUK 1844 | DUKB 1845 | DUO 1846 | DUOL 1847 | DUOT 1848 | DV 1849 | DVA 1850 | DVAX 1851 | DVN 1852 | DWSN 1853 | DWTX 1854 | DX 1855 | DXC 1856 | DXCM 1857 | DXLG 1858 | DXPE 1859 | DXR 1860 | DXYZ 1861 | DY 1862 | DYAI 1863 | DYCQ 1864 | DYCQR 1865 | DYCQU 1866 | DYN 1867 | E 1868 | EA 1869 | EAD 1870 | EAF 1871 | EAI 1872 | EARN 1873 | EAST 1874 | EAT 1875 | EB 1876 | EBAY 1877 | EBC 1878 | EBF 1879 | EBMT 1880 | EBON 1881 | EBR 1882 | EBS 1883 | EBTC 1884 | EC 1885 | ECAT 1886 | ECBK 1887 | ECC 1888 | ECCC 1889 | ECCF 1890 | ECCV 1891 | ECCW 1892 | ECCX 1893 | ECDA 1894 | ECDAW 1895 | ECF 1896 | ECL 1897 | ECO 1898 | ECOR 1899 | ECPG 1900 | ECVT 1901 | ECX 1902 | ECXWW 1903 | ED 1904 | EDAP 1905 | EDBL 1906 | EDBLW 1907 | EDD 1908 | EDF 1909 | EDIT 1910 | EDN 1911 | EDR 1912 | EDRY 1913 | EDSA 1914 | EDTK 1915 | EDU 1916 | EDUC 1917 | EE 1918 | EEA 1919 | EEFT 1920 | EEIQ 1921 | EEX 1922 | EFC 1923 | EFOI 1924 | EFR 1925 | EFSC 1926 | EFSCP 1927 | EFSH 1928 | EFT 1929 | EFX 1930 | EFXT 1931 | EG 1932 | EGAN 1933 | EGBN 1934 | EGF 1935 | EGY 1936 | EH 1937 | EHAB 1938 | EHC 1939 | EHGO 1940 | EHI 1941 | EHTH 1942 | EIC 1943 | EICA 1944 | EICB 1945 | EICC 1946 | EIG 1947 | EIM 1948 | EIX 1949 | EJH 1950 | EKSO 1951 | EL 1952 | ELA 1953 | ELAB 1954 | ELAN 1955 | ELBM 1956 | ELC 1957 | ELDN 1958 | ELEV 1959 | ELF 1960 | ELLO 1961 | ELMD 1962 | ELME 1963 | ELP 1964 | ELPC 1965 | ELS 1966 | ELSE 1967 | ELTK 1968 | ELTX 1969 | ELUT 1970 | ELV 1971 | ELVA 1972 | ELVN 1973 | ELWS 1974 | EM 1975 | EMBC 1976 | EMCG 1977 | EMD 1978 | EME 1979 | EMF 1980 | EMKR 1981 | EML 1982 | EMN 1983 | EMO 1984 | EMP 1985 | EMR 1986 | EMX 1987 | ENB 1988 | ENFN 1989 | ENG 1990 | ENGN 1991 | ENGNW 1992 | ENIC 1993 | ENJ 1994 | ENLC 1995 | ENLT 1996 | ENLV 1997 | ENO 1998 | ENOV 1999 | ENPH 2000 | ENR 2001 | ENS 2002 | ENSC 2003 | ENSG 2004 | ENSV 2005 | ENTA 2006 | ENTG 2007 | ENTO 2008 | ENTX 2009 | ENV 2010 | ENVA 2011 | ENVB 2012 | ENVX 2013 | ENX 2014 | ENZ 2015 | EOD 2016 | EOG 2017 | EOI 2018 | EOLS 2019 | EONR 2020 | EOS 2021 | EOSE 2022 | EOSEW 2023 | EOT 2024 | EP 2025 | EPAC 2026 | EPAM 2027 | EPC 2028 | EPD 2029 | EPIX 2030 | EPM 2031 | EPOW 2032 | EPR 2033 | EPRT 2034 | EPRX 2035 | EPSN 2036 | EQ 2037 | EQBK 2038 | EQC 2039 | EQH 2040 | EQIX 2041 | EQNR 2042 | EQR 2043 | EQS 2044 | EQT 2045 | EQV 2046 | EQX 2047 | ERAS 2048 | ERC 2049 | ERH 2050 | ERIC 2051 | ERIE 2052 | ERII 2053 | ERJ 2054 | ERNA 2055 | ERO 2056 | ES 2057 | ESAB 2058 | ESCA 2059 | ESE 2060 | ESEA 2061 | ESGL 2062 | ESGLW 2063 | ESGR 2064 | ESGRO 2065 | ESGRP 2066 | ESHA 2067 | ESHAR 2068 | ESI 2069 | ESLA 2070 | ESLT 2071 | ESNT 2072 | ESOA 2073 | ESP 2074 | ESPR 2075 | ESQ 2076 | ESRT 2077 | ESS 2078 | ESSA 2079 | ESTA 2080 | ESTC 2081 | ET 2082 | ETB 2083 | ETD 2084 | ETG 2085 | ETI 2086 | ETJ 2087 | ETN 2088 | ETNB 2089 | ETO 2090 | ETON 2091 | ETR 2092 | ETSY 2093 | ETV 2094 | ETW 2095 | ETWO 2096 | ETX 2097 | ETY 2098 | EU 2099 | EUDA 2100 | EUDAW 2101 | EURK 2102 | EURKR 2103 | EVAX 2104 | EVBN 2105 | EVC 2106 | EVCM 2107 | EVE 2108 | EVER 2109 | EVEX 2110 | EVF 2111 | EVG 2112 | EVGN 2113 | EVGO 2114 | EVGOW 2115 | EVGR 2116 | EVGRW 2117 | EVH 2118 | EVI 2119 | EVLV 2120 | EVLVW 2121 | EVM 2122 | EVN 2123 | EVO 2124 | EVOK 2125 | EVR 2126 | EVRG 2127 | EVRI 2128 | EVT 2129 | EVTC 2130 | EVTL 2131 | EVTV 2132 | EVV 2133 | EW 2134 | EWBC 2135 | EWCZ 2136 | EWTX 2137 | EXAI 2138 | EXAS 2139 | EXC 2140 | EXE 2141 | EXEEL 2142 | EXEEW 2143 | EXEL 2144 | EXFY 2145 | EXG 2146 | EXK 2147 | EXLS 2148 | EXP 2149 | EXPD 2150 | EXPE 2151 | EXPI 2152 | EXPO 2153 | EXR 2154 | EXTO 2155 | EXTR 2156 | EYE 2157 | EYEN 2158 | EYPT 2159 | EZFL 2160 | EZGO 2161 | EZPW 2162 | F 2163 | FA 2164 | FAAS 2165 | FAASW 2166 | FAF 2167 | FAMI 2168 | FANG 2169 | FANH 2170 | FARM 2171 | FARO 2172 | FAST 2173 | FAT 2174 | FATBB 2175 | FATBP 2176 | FATE 2177 | FAX 2178 | FBIN 2179 | FBIO 2180 | FBIOP 2181 | FBIZ 2182 | FBK 2183 | FBLG 2184 | FBMS 2185 | FBNC 2186 | FBP 2187 | FBRT 2188 | FBRX 2189 | FBYD 2190 | FBYDW 2191 | FC 2192 | FCAP 2193 | FCBC 2194 | FCCO 2195 | FCEL 2196 | FCF 2197 | FCFS 2198 | FCN 2199 | FCNCA 2200 | FCNCO 2201 | FCNCP 2202 | FCO 2203 | FCPT 2204 | FCRX 2205 | FCT 2206 | FCUV 2207 | FCX 2208 | FDBC 2209 | FDMT 2210 | FDP 2211 | FDSB 2212 | FDUS 2213 | FDX 2214 | FE 2215 | FEAM 2216 | FEBO 2217 | FEDU 2218 | FEIM 2219 | FELE 2220 | FEMY 2221 | FENC 2222 | FENG 2223 | FER 2224 | FERG 2225 | FET 2226 | FF 2227 | FFA 2228 | FFBC 2229 | FFC 2230 | FFIC 2231 | FFIE 2232 | FFIEW 2233 | FFIN 2234 | FFIV 2235 | FFNW 2236 | FFWM 2237 | FG 2238 | FGB 2239 | FGBI 2240 | FGBIP 2241 | FGEN 2242 | FGF 2243 | FGFPP 2244 | FGI 2245 | FGIWW 2246 | FGN 2247 | FHB 2248 | FHI 2249 | FHN 2250 | FHTX 2251 | FI 2252 | FIAC 2253 | FIACU 2254 | FIACW 2255 | FIBK 2256 | FICO 2257 | FIGS 2258 | FIHL 2259 | FINS 2260 | FINV 2261 | FINW 2262 | FIP 2263 | FIS 2264 | FISI 2265 | FITB 2266 | FITBI 2267 | FITBO 2268 | FITBP 2269 | FIVE 2270 | FIVN 2271 | FIX 2272 | FIZZ 2273 | FKWL 2274 | FL 2275 | FLC 2276 | FLD 2277 | FLDDW 2278 | FLEX 2279 | FLGC 2280 | FLGT 2281 | FLIC 2282 | FLL 2283 | FLNC 2284 | FLNG 2285 | FLNT 2286 | FLO 2287 | FLR 2288 | FLS 2289 | FLUT 2290 | FLUX 2291 | FLWS 2292 | FLX 2293 | FLXS 2294 | FLYE 2295 | FLYW 2296 | FLYX 2297 | FMAO 2298 | FMBH 2299 | FMC 2300 | FMN 2301 | FMNB 2302 | FMS 2303 | FMST 2304 | FMSTW 2305 | FMX 2306 | FMY 2307 | FN 2308 | FNA 2309 | FNB 2310 | FND 2311 | FNF 2312 | FNGR 2313 | FNKO 2314 | FNLC 2315 | FNV 2316 | FNVT 2317 | FNVTW 2318 | FNWB 2319 | FNWD 2320 | FOA 2321 | FOF 2322 | FOLD 2323 | FONR 2324 | FOR 2325 | FORA 2326 | FORD 2327 | FORL 2328 | FORLW 2329 | FORM 2330 | FORR 2331 | FORTY 2332 | FOSL 2333 | FOSLL 2334 | FOUR 2335 | FOX 2336 | FOXA 2337 | FOXF 2338 | FOXO 2339 | FOXX 2340 | FOXXW 2341 | FPAY 2342 | FPF 2343 | FPH 2344 | FPI 2345 | FR 2346 | FRA 2347 | FRAF 2348 | FRBA 2349 | FRD 2350 | FRES 2351 | FREY 2352 | FRGE 2353 | FRGT 2354 | FRHC 2355 | FRLA 2356 | FRLAW 2357 | FRME 2358 | FRMEP 2359 | FRO 2360 | FROG 2361 | FRPH 2362 | FRPT 2363 | FRSH 2364 | FRST 2365 | FRSX 2366 | FRT 2367 | FSBC 2368 | FSBW 2369 | FSCO 2370 | FSEA 2371 | FSFG 2372 | FSHP 2373 | FSHPR 2374 | FSHPU 2375 | FSI 2376 | FSK 2377 | FSLR 2378 | FSLY 2379 | FSM 2380 | FSP 2381 | FSS 2382 | FSTR 2383 | FSUN 2384 | FSV 2385 | FT 2386 | FTAI 2387 | FTAIM 2388 | FTAIN 2389 | FTAIO 2390 | FTAIP 2391 | FTCI 2392 | FTDR 2393 | FTEK 2394 | FTEL 2395 | FTF 2396 | FTFT 2397 | FTHM 2398 | FTHY 2399 | FTI 2400 | FTK 2401 | FTLF 2402 | FTNT 2403 | FTRE 2404 | FTS 2405 | FTV 2406 | FUBO 2407 | FUFU 2408 | FUFUW 2409 | FUL 2410 | FULC 2411 | FULT 2412 | FULTP 2413 | FUN 2414 | FUNC 2415 | FUND 2416 | FURY 2417 | FUSB 2418 | FUTU 2419 | FVCB 2420 | FVNNU 2421 | FVR 2422 | FVRR 2423 | FWONA 2424 | FWONK 2425 | FWRD 2426 | FWRG 2427 | FXNC 2428 | FYBR 2429 | G 2430 | GAB 2431 | GABC 2432 | GAIA 2433 | GAIN 2434 | GAINL 2435 | GAINN 2436 | GAINZ 2437 | GALT 2438 | GAM 2439 | GAMB 2440 | GAME 2441 | GAN 2442 | GANX 2443 | GAP 2444 | GAQ 2445 | GASS 2446 | GATE 2447 | GATEU 2448 | GATO 2449 | GATX 2450 | GAU 2451 | GAUZ 2452 | GB 2453 | GBAB 2454 | GBBK 2455 | GBBKR 2456 | GBBKW 2457 | GBCI 2458 | GBDC 2459 | GBIO 2460 | GBLI 2461 | GBR 2462 | GBTG 2463 | GBX 2464 | GCBC 2465 | GCI 2466 | GCMG 2467 | GCMGW 2468 | GCO 2469 | GCT 2470 | GCTK 2471 | GCTS 2472 | GCV 2473 | GD 2474 | GDC 2475 | GDDY 2476 | GDEN 2477 | GDEV 2478 | GDEVW 2479 | GDHG 2480 | GDL 2481 | GDO 2482 | GDOT 2483 | GDRX 2484 | GDS 2485 | GDTC 2486 | GDV 2487 | GDYN 2488 | GE 2489 | GECC 2490 | GECCH 2491 | GECCI 2492 | GECCO 2493 | GECCZ 2494 | GEF 2495 | GEG 2496 | GEGGL 2497 | GEHC 2498 | GEL 2499 | GEN 2500 | GENC 2501 | GENE 2502 | GENI 2503 | GENK 2504 | GEO 2505 | GEOS 2506 | GERN 2507 | GES 2508 | GETY 2509 | GEV 2510 | GEVO 2511 | GF 2512 | GFAI 2513 | GFAIW 2514 | GFF 2515 | GFI 2516 | GFL 2517 | GFR 2518 | GFS 2519 | GGAL 2520 | GGB 2521 | GGG 2522 | GGN 2523 | GGR 2524 | GGROW 2525 | GGT 2526 | GGZ 2527 | GH 2528 | GHC 2529 | GHG 2530 | GHI 2531 | GHIX 2532 | GHLD 2533 | GHM 2534 | GHRS 2535 | GHY 2536 | GIB 2537 | GIC 2538 | GIFI 2539 | GIFT 2540 | GIG 2541 | GIGGU 2542 | GIGGW 2543 | GIGM 2544 | GIII 2545 | GIL 2546 | GILD 2547 | GILT 2548 | GIPR 2549 | GIPRW 2550 | GIS 2551 | GJH 2552 | GJO 2553 | GJP 2554 | GJR 2555 | GJS 2556 | GJT 2557 | GKOS 2558 | GL 2559 | GLAC 2560 | GLAD 2561 | GLADZ 2562 | GLBE 2563 | GLBS 2564 | GLBZ 2565 | GLDD 2566 | GLDG 2567 | GLE 2568 | GLLI 2569 | GLLIU 2570 | GLMD 2571 | GLNG 2572 | GLO 2573 | GLOB 2574 | GLOP 2575 | GLP 2576 | GLPG 2577 | GLPI 2578 | GLQ 2579 | GLRE 2580 | GLSI 2581 | GLST 2582 | GLT 2583 | GLTO 2584 | GLU 2585 | GLUE 2586 | GLV 2587 | GLW 2588 | GLXG 2589 | GLYC 2590 | GM 2591 | GMAB 2592 | GME 2593 | GMED 2594 | GMGI 2595 | GMM 2596 | GMRE 2597 | GMS 2598 | GNE 2599 | GNFT 2600 | GNK 2601 | GNL 2602 | GNLN 2603 | GNLX 2604 | GNPX 2605 | GNRC 2606 | GNS 2607 | GNSS 2608 | GNT 2609 | GNTA 2610 | GNTX 2611 | GNTY 2612 | GNW 2613 | GO 2614 | GOCO 2615 | GODN 2616 | GOEV 2617 | GOEVW 2618 | GOF 2619 | GOGL 2620 | GOGO 2621 | GOLD 2622 | GOLF 2623 | GOOD 2624 | GOODN 2625 | GOODO 2626 | GOOG 2627 | GOOGL 2628 | GOOS 2629 | GORO 2630 | GORV 2631 | GOSS 2632 | GOTU 2633 | GOVX 2634 | GOVXW 2635 | GP 2636 | GPAT 2637 | GPATU 2638 | GPATW 2639 | GPC 2640 | GPCR 2641 | GPI 2642 | GPJA 2643 | GPK 2644 | GPMT 2645 | GPN 2646 | GPOR 2647 | GPRE 2648 | GPRK 2649 | GPRO 2650 | GPUS 2651 | GRAB 2652 | GRABW 2653 | GRAF 2654 | GRAL 2655 | GRBK 2656 | GRC 2657 | GRDI 2658 | GRDIW 2659 | GRDN 2660 | GREE 2661 | GREEL 2662 | GRF 2663 | GRFS 2664 | GRFX 2665 | GRI 2666 | GRMN 2667 | GRND 2668 | GRNQ 2669 | GRNT 2670 | GROV 2671 | GROW 2672 | GROY 2673 | GRPN 2674 | GRRR 2675 | GRRRW 2676 | GRTS 2677 | GRVY 2678 | GRWG 2679 | GRX 2680 | GRYP 2681 | GS 2682 | GSAT 2683 | GSBC 2684 | GSBD 2685 | GSHD 2686 | GSIT 2687 | GSIW 2688 | GSK 2689 | GSL 2690 | GSM 2691 | GSMGW 2692 | GSUN 2693 | GT 2694 | GTAC 2695 | GTACU 2696 | GTACW 2697 | GTBP 2698 | GTE 2699 | GTEC 2700 | GTES 2701 | GTI 2702 | GTIM 2703 | GTLB 2704 | GTLS 2705 | GTN 2706 | GTX 2707 | GTY 2708 | GUG 2709 | GURE 2710 | GUT 2711 | GUTS 2712 | GV 2713 | GVA 2714 | GVH 2715 | GVP 2716 | GWAV 2717 | GWH 2718 | GWRE 2719 | GWRS 2720 | GWW 2721 | GXAI 2722 | GXO 2723 | GYRE 2724 | GYRO 2725 | H 2726 | HAE 2727 | HAFC 2728 | HAFN 2729 | HAIA 2730 | HAIAU 2731 | HAIAW 2732 | HAIN 2733 | HAL 2734 | HALO 2735 | HAO 2736 | HAS 2737 | HASI 2738 | HAYN 2739 | HAYW 2740 | HBAN 2741 | HBANL 2742 | HBANM 2743 | HBANP 2744 | HBB 2745 | HBCP 2746 | HBI 2747 | HBIO 2748 | HBM 2749 | HBNC 2750 | HBT 2751 | HCA 2752 | HCAT 2753 | HCC 2754 | HCI 2755 | HCKT 2756 | HCM 2757 | HCP 2758 | HCSG 2759 | HCTI 2760 | HCVIU 2761 | HCVIW 2762 | HCWB 2763 | HCWC 2764 | HCXY 2765 | HD 2766 | HDB 2767 | HDL 2768 | HDSN 2769 | HE 2770 | HEAR 2771 | HEES 2772 | HEI 2773 | HELE 2774 | HEPA 2775 | HEPS 2776 | HEQ 2777 | HES 2778 | HESM 2779 | HFBL 2780 | HFFG 2781 | HFRO 2782 | HFWA 2783 | HG 2784 | HGBL 2785 | HGLB 2786 | HGTY 2787 | HGV 2788 | HHH 2789 | HHS 2790 | HI 2791 | HIE 2792 | HIFS 2793 | HIG 2794 | HIHO 2795 | HII 2796 | HIMS 2797 | HIMX 2798 | HIO 2799 | HIPO 2800 | HITI 2801 | HIVE 2802 | HIW 2803 | HIX 2804 | HKD 2805 | HKIT 2806 | HL 2807 | HLF 2808 | HLI 2809 | HLIO 2810 | HLIT 2811 | HLLY 2812 | HLMN 2813 | HLN 2814 | HLNE 2815 | HLP 2816 | HLT 2817 | HLVX 2818 | HLX 2819 | HLXB 2820 | HMC 2821 | HMN 2822 | HMST 2823 | HMY 2824 | HNI 2825 | HNNA 2826 | HNNAZ 2827 | HNRG 2828 | HNST 2829 | HNVR 2830 | HNW 2831 | HOFT 2832 | HOFV 2833 | HOFVW 2834 | HOG 2835 | HOLO 2836 | HOLOW 2837 | HOLX 2838 | HOMB 2839 | HON 2840 | HOND 2841 | HONDU 2842 | HONDW 2843 | HONE 2844 | HOOD 2845 | HOOK 2846 | HOPE 2847 | HOTH 2848 | HOUR 2849 | HOUS 2850 | HOV 2851 | HOVNP 2852 | HOVR 2853 | HOVRW 2854 | HOWL 2855 | HP 2856 | HPAI 2857 | HPAIW 2858 | HPE 2859 | HPF 2860 | HPH 2861 | HPI 2862 | HPK 2863 | HPKEW 2864 | HPP 2865 | HPQ 2866 | HPS 2867 | HQH 2868 | HQI 2869 | HQL 2870 | HQY 2871 | HR 2872 | HRB 2873 | HRI 2874 | HRL 2875 | HRMY 2876 | HROW 2877 | HROWL 2878 | HROWM 2879 | HRTG 2880 | HRTX 2881 | HRYU 2882 | HRZN 2883 | HSAI 2884 | HSBC 2885 | HSCS 2886 | HSCSW 2887 | HSDT 2888 | HSHP 2889 | HSIC 2890 | HSII 2891 | HSON 2892 | HSPO 2893 | HSPOU 2894 | HSPOW 2895 | HST 2896 | HSTM 2897 | HSY 2898 | HTBI 2899 | HTBK 2900 | HTCO 2901 | HTCR 2902 | HTD 2903 | HTFB 2904 | HTFC 2905 | HTGC 2906 | HTH 2907 | HTHT 2908 | HTIA 2909 | HTIBP 2910 | HTLD 2911 | HTLF 2912 | HTLFP 2913 | HTLM 2914 | HTOO 2915 | HTOOW 2916 | HTZ 2917 | HTZWW 2918 | HUBB 2919 | HUBC 2920 | HUBCW 2921 | HUBCZ 2922 | HUBG 2923 | HUBS 2924 | HUDI 2925 | HUIZ 2926 | HUM 2927 | HUMA 2928 | HUMAW 2929 | HUN 2930 | HURC 2931 | HURN 2932 | HUSA 2933 | HUT 2934 | HUYA 2935 | HVT 2936 | HWBK 2937 | HWC 2938 | HWCPZ 2939 | HWH 2940 | HWKN 2941 | HWM 2942 | HXL 2943 | HY 2944 | HYAC 2945 | HYB 2946 | HYFM 2947 | HYI 2948 | HYLN 2949 | HYMC 2950 | HYMCL 2951 | HYMCW 2952 | HYPR 2953 | HYT 2954 | HYZN 2955 | HYZNW 2956 | HZO 2957 | I 2958 | IAC 2959 | IAE 2960 | IAF 2961 | IAG 2962 | IART 2963 | IAS 2964 | IAUX 2965 | IBAC 2966 | IBACR 2967 | IBCP 2968 | IBEX 2969 | IBG 2970 | IBIO 2971 | IBKR 2972 | IBM 2973 | IBN 2974 | IBO 2975 | IBOC 2976 | IBP 2977 | IBRX 2978 | IBTA 2979 | IBTX 2980 | ICAD 2981 | ICCC 2982 | ICCH 2983 | ICCM 2984 | ICCT 2985 | ICE 2986 | ICFI 2987 | ICG 2988 | ICHR 2989 | ICL 2990 | ICLK 2991 | ICLR 2992 | ICMB 2993 | ICON 2994 | ICR 2995 | ICU 2996 | ICUCW 2997 | ICUI 2998 | IDA 2999 | IDAI 3000 | IDCC 3001 | IDE 3002 | IDN 3003 | IDR 3004 | IDT 3005 | IDXX 3006 | IDYA 3007 | IE 3008 | IEP 3009 | IESC 3010 | IEX 3011 | IFBD 3012 | IFF 3013 | IFN 3014 | IFRX 3015 | IFS 3016 | IGA 3017 | IGC 3018 | IGD 3019 | IGI 3020 | IGIC 3021 | IGMS 3022 | IGR 3023 | IGT 3024 | IGTA 3025 | IGTAU 3026 | IGTAW 3027 | IH 3028 | IHD 3029 | IHG 3030 | IHRT 3031 | IHS 3032 | IHT 3033 | IHTA 3034 | IIF 3035 | III 3036 | IIIN 3037 | IIIV 3038 | IIM 3039 | IINN 3040 | IINNW 3041 | IIPR 3042 | IKNA 3043 | IKT 3044 | ILAG 3045 | ILLR 3046 | ILLRW 3047 | ILMN 3048 | ILPT 3049 | IMAB 3050 | IMAX 3051 | IMCC 3052 | IMCR 3053 | IMKTA 3054 | IMMP 3055 | IMMR 3056 | IMMX 3057 | IMNM 3058 | IMNN 3059 | IMO 3060 | IMOS 3061 | IMPP 3062 | IMPPP 3063 | IMRN 3064 | IMRX 3065 | IMTE 3066 | IMTX 3067 | IMTXW 3068 | IMUX 3069 | IMVT 3070 | IMXI 3071 | INAB 3072 | INAQ 3073 | INAQW 3074 | INBK 3075 | INBKZ 3076 | INBS 3077 | INBX 3078 | INCR 3079 | INCY 3080 | INDB 3081 | INDI 3082 | INDO 3083 | INDP 3084 | INDV 3085 | INFA 3086 | INFN 3087 | INFU 3088 | INFY 3089 | ING 3090 | INGN 3091 | INGR 3092 | INHD 3093 | INKT 3094 | INLX 3095 | INM 3096 | INMB 3097 | INMD 3098 | INN 3099 | INNV 3100 | INO 3101 | INOD 3102 | INSE 3103 | INSG 3104 | INSI 3105 | INSM 3106 | INSP 3107 | INST 3108 | INSW 3109 | INTA 3110 | INTC 3111 | INTE 3112 | INTEU 3113 | INTEW 3114 | INTG 3115 | INTJ 3116 | INTR 3117 | INTS 3118 | INTT 3119 | INTU 3120 | INTZ 3121 | INUV 3122 | INV 3123 | INVA 3124 | INVE 3125 | INVH 3126 | INVO 3127 | INVX 3128 | INVZ 3129 | INVZW 3130 | INZY 3131 | IOBT 3132 | IONQ 3133 | IONR 3134 | IONS 3135 | IOR 3136 | IOSP 3137 | IOT 3138 | IOVA 3139 | IP 3140 | IPA 3141 | IPAR 3142 | IPDN 3143 | IPG 3144 | IPGP 3145 | IPHA 3146 | IPI 3147 | IPSC 3148 | IPW 3149 | IPWR 3150 | IPX 3151 | IPXX 3152 | IPXXW 3153 | IQ 3154 | IQI 3155 | IQV 3156 | IR 3157 | IRBT 3158 | IRDM 3159 | IREN 3160 | IRIX 3161 | IRM 3162 | IRMD 3163 | IROH 3164 | IROHR 3165 | IROHW 3166 | IRON 3167 | IROQ 3168 | IRS 3169 | IRT 3170 | IRTC 3171 | IRWD 3172 | ISD 3173 | ISDR 3174 | ISPC 3175 | ISPO 3176 | ISPOW 3177 | ISPR 3178 | ISRG 3179 | ISRL 3180 | ISRLU 3181 | ISRLW 3182 | ISSC 3183 | ISTR 3184 | IT 3185 | ITCI 3186 | ITGR 3187 | ITI 3188 | ITIC 3189 | ITOS 3190 | ITP 3191 | ITRG 3192 | ITRI 3193 | ITRM 3194 | ITRN 3195 | ITT 3196 | ITUB 3197 | ITW 3198 | IVA 3199 | IVAC 3200 | IVCA 3201 | IVCAU 3202 | IVCAW 3203 | IVCB 3204 | IVCP 3205 | IVCPU 3206 | IVCPW 3207 | IVDA 3208 | IVP 3209 | IVR 3210 | IVT 3211 | IVVD 3212 | IVZ 3213 | IX 3214 | IXHL 3215 | IZEA 3216 | IZM 3217 | J 3218 | JACK 3219 | JAGX 3220 | JAKK 3221 | JAMF 3222 | JANX 3223 | JAZZ 3224 | JBDI 3225 | JBGS 3226 | JBHT 3227 | JBI 3228 | JBK 3229 | JBL 3230 | JBLU 3231 | JBSS 3232 | JBT 3233 | JCE 3234 | JCI 3235 | JCSE 3236 | JCTC 3237 | JD 3238 | JDZG 3239 | JEF 3240 | JELD 3241 | JEQ 3242 | JFBR 3243 | JFBRW 3244 | JFIN 3245 | JFR 3246 | JFU 3247 | JG 3248 | JGH 3249 | JHG 3250 | JHI 3251 | JHS 3252 | JHX 3253 | JILL 3254 | JJSF 3255 | JKHY 3256 | JKS 3257 | JL 3258 | JLL 3259 | JLS 3260 | JMIA 3261 | JMM 3262 | JMSB 3263 | JNJ 3264 | JNPR 3265 | JNVR 3266 | JOB 3267 | JOBY 3268 | JOE 3269 | JOF 3270 | JOUT 3271 | JPC 3272 | JPI 3273 | JPM 3274 | JQC 3275 | JRI 3276 | JRS 3277 | JRSH 3278 | JRVR 3279 | JSM 3280 | JSPR 3281 | JSPRW 3282 | JTAI 3283 | JUNE 3284 | JVA 3285 | JVSA 3286 | JVSAR 3287 | JWEL 3288 | JWN 3289 | JWSM 3290 | JXJT 3291 | JXN 3292 | JYD 3293 | JYNT 3294 | JZ 3295 | JZXN 3296 | K 3297 | KACL 3298 | KACLR 3299 | KACLU 3300 | KACLW 3301 | KAI 3302 | KALA 3303 | KALU 3304 | KALV 3305 | KAPA 3306 | KAR 3307 | KARO 3308 | KAVL 3309 | KB 3310 | KBDC 3311 | KBH 3312 | KBR 3313 | KC 3314 | KD 3315 | KDLY 3316 | KDLYW 3317 | KDP 3318 | KE 3319 | KELYA 3320 | KELYB 3321 | KEN 3322 | KEP 3323 | KEQU 3324 | KEX 3325 | KEY 3326 | KEYS 3327 | KF 3328 | KFFB 3329 | KFRC 3330 | KFS 3331 | KFY 3332 | KGC 3333 | KGEI 3334 | KGS 3335 | KHC 3336 | KIDS 3337 | KIM 3338 | KIND 3339 | KINS 3340 | KIO 3341 | KIRK 3342 | KITT 3343 | KITTW 3344 | KKR 3345 | KKRS 3346 | KLAC 3347 | KLC 3348 | KLG 3349 | KLIC 3350 | KLTO 3351 | KLTOW 3352 | KLTR 3353 | KLXE 3354 | KMB 3355 | KMDA 3356 | KMI 3357 | KMPB 3358 | KMPR 3359 | KMT 3360 | KMX 3361 | KN 3362 | KNDI 3363 | KNF 3364 | KNOP 3365 | KNSA 3366 | KNSL 3367 | KNTK 3368 | KNW 3369 | KNX 3370 | KO 3371 | KOD 3372 | KODK 3373 | KOF 3374 | KOP 3375 | KOPN 3376 | KORE 3377 | KOS 3378 | KOSS 3379 | KPLT 3380 | KPLTW 3381 | KPRX 3382 | KPTI 3383 | KR 3384 | KRC 3385 | KREF 3386 | KRG 3387 | KRKR 3388 | KRMD 3389 | KRNT 3390 | KRNY 3391 | KRO 3392 | KRON 3393 | KROS 3394 | KRP 3395 | KRRO 3396 | KRT 3397 | KRUS 3398 | KRYS 3399 | KSCP 3400 | KSM 3401 | KSPI 3402 | KSS 3403 | KT 3404 | KTB 3405 | KTCC 3406 | KTF 3407 | KTH 3408 | KTN 3409 | KTOS 3410 | KTRA 3411 | KTTA 3412 | KUKE 3413 | KULR 3414 | KURA 3415 | KVAC 3416 | KVACU 3417 | KVACW 3418 | KVHI 3419 | KVUE 3420 | KVYO 3421 | KW 3422 | KWE 3423 | KWESW 3424 | KWR 3425 | KXIN 3426 | KYMR 3427 | KYN 3428 | KYTX 3429 | KZIA 3430 | KZR 3431 | L 3432 | LAAC 3433 | LAB 3434 | LAC 3435 | LAD 3436 | LADR 3437 | LAES 3438 | LAKE 3439 | LAMR 3440 | LANC 3441 | LAND 3442 | LANDM 3443 | LANDO 3444 | LANDP 3445 | LANV 3446 | LARK 3447 | LASE 3448 | LASR 3449 | LATG 3450 | LAUR 3451 | LAW 3452 | LAZ 3453 | LAZR 3454 | LB 3455 | LBPH 3456 | LBRDA 3457 | LBRDK 3458 | LBRDP 3459 | LBRT 3460 | LBTYA 3461 | LBTYB 3462 | LBTYK 3463 | LC 3464 | LCFY 3465 | LCFYW 3466 | LCID 3467 | LCII 3468 | LCNB 3469 | LCTX 3470 | LCUT 3471 | LDI 3472 | LDOS 3473 | LDP 3474 | LDTC 3475 | LDTCW 3476 | LDWY 3477 | LE 3478 | LEA 3479 | LECO 3480 | LEDS 3481 | LEE 3482 | LEG 3483 | LEGH 3484 | LEGN 3485 | LEGT 3486 | LEN 3487 | LENZ 3488 | LEO 3489 | LESL 3490 | LEU 3491 | LEV 3492 | LEVI 3493 | LEXX 3494 | LEXXW 3495 | LFCR 3496 | LFLY 3497 | LFLYW 3498 | LFMD 3499 | LFMDP 3500 | LFST 3501 | LFT 3502 | LFUS 3503 | LFVN 3504 | LFWD 3505 | LGCB 3506 | LGCL 3507 | LGCY 3508 | LGHL 3509 | LGHLW 3510 | LGI 3511 | LGIH 3512 | LGL 3513 | LGMK 3514 | LGND 3515 | LGO 3516 | LGTY 3517 | LGVN 3518 | LH 3519 | LHX 3520 | LI 3521 | LICN 3522 | LICY 3523 | LIDR 3524 | LIDRW 3525 | LIEN 3526 | LIF 3527 | LIFW 3528 | LIFWW 3529 | LII 3530 | LILA 3531 | LILAK 3532 | LILM 3533 | LILMW 3534 | LIN 3535 | LINC 3536 | LIND 3537 | LINE 3538 | LINK 3539 | LION 3540 | LIPO 3541 | LIQT 3542 | LITB 3543 | LITE 3544 | LITM 3545 | LIVE 3546 | LIVN 3547 | LIXT 3548 | LKCO 3549 | LKFN 3550 | LKQ 3551 | LLAP 3552 | LLY 3553 | LLYVA 3554 | LLYVK 3555 | LMAT 3556 | LMB 3557 | LMFA 3558 | LMND 3559 | LMNR 3560 | LMT 3561 | LNC 3562 | LND 3563 | LNG 3564 | LNKB 3565 | LNN 3566 | LNSR 3567 | LNT 3568 | LNTH 3569 | LNW 3570 | LNZA 3571 | LNZAW 3572 | LOAN 3573 | LOAR 3574 | LOB 3575 | LOBO 3576 | LOCL 3577 | LOCO 3578 | LODE 3579 | LOGC 3580 | LOGI 3581 | LOMA 3582 | LOOP 3583 | LOPE 3584 | LOT 3585 | LOTWW 3586 | LOVE 3587 | LOW 3588 | LPA 3589 | LPAA 3590 | LPAAW 3591 | LPBBU 3592 | LPCN 3593 | LPG 3594 | LPL 3595 | LPLA 3596 | LPRO 3597 | LPSN 3598 | LPTH 3599 | LPTX 3600 | LPX 3601 | LQDA 3602 | LQDT 3603 | LQR 3604 | LRCX 3605 | LRE 3606 | LRFC 3607 | LRHC 3608 | LRMR 3609 | LRN 3610 | LSAK 3611 | LSB 3612 | LSBK 3613 | LSBPW 3614 | LSCC 3615 | LSEA 3616 | LSEAW 3617 | LSF 3618 | LSH 3619 | LSPD 3620 | LSTA 3621 | LSTR 3622 | LTBR 3623 | LTC 3624 | LTH 3625 | LTM 3626 | LTRN 3627 | LTRX 3628 | LTRY 3629 | LTRYW 3630 | LU 3631 | LUCD 3632 | LUCY 3633 | LUCYW 3634 | LULU 3635 | LUMN 3636 | LUMO 3637 | LUNA 3638 | LUNG 3639 | LUNR 3640 | LUNRW 3641 | LUV 3642 | LUXH 3643 | LUXHP 3644 | LVLU 3645 | LVO 3646 | LVRO 3647 | LVROW 3648 | LVS 3649 | LVTX 3650 | LVWR 3651 | LW 3652 | LWAY 3653 | LWLG 3654 | LX 3655 | LXEH 3656 | LXEO 3657 | LXFR 3658 | LXP 3659 | LXRX 3660 | LXU 3661 | LYB 3662 | LYEL 3663 | LYFT 3664 | LYG 3665 | LYRA 3666 | LYT 3667 | LYTS 3668 | LYV 3669 | LZ 3670 | LZB 3671 | LZM 3672 | M 3673 | MA 3674 | MAA 3675 | MAC 3676 | MACI 3677 | MACIU 3678 | MACIW 3679 | MAG 3680 | MAIA 3681 | MAIN 3682 | MAMA 3683 | MAMO 3684 | MAN 3685 | MANH 3686 | MANU 3687 | MAPS 3688 | MAPSW 3689 | MAR 3690 | MARA 3691 | MARPS 3692 | MARX 3693 | MARXU 3694 | MAS 3695 | MASI 3696 | MASS 3697 | MAT 3698 | MATH 3699 | MATV 3700 | MATW 3701 | MATX 3702 | MAV 3703 | MAX 3704 | MAXN 3705 | MAYS 3706 | MBAV 3707 | MBAVU 3708 | MBAVW 3709 | MBC 3710 | MBCN 3711 | MBI 3712 | MBIN 3713 | MBINM 3714 | MBINN 3715 | MBINO 3716 | MBIO 3717 | MBLY 3718 | MBNKP 3719 | MBOT 3720 | MBRX 3721 | MBUU 3722 | MBWM 3723 | MBX 3724 | MC 3725 | MCAA 3726 | MCAAU 3727 | MCAAW 3728 | MCAG 3729 | MCB 3730 | MCBS 3731 | MCD 3732 | MCFT 3733 | MCHP 3734 | MCHX 3735 | MCI 3736 | MCK 3737 | MCN 3738 | MCO 3739 | MCR 3740 | MCRB 3741 | MCRI 3742 | MCS 3743 | MCVT 3744 | MCW 3745 | MCY 3746 | MD 3747 | MDAI 3748 | MDAIW 3749 | MDB 3750 | MDBH 3751 | MDGL 3752 | MDIA 3753 | MDJH 3754 | MDLZ 3755 | MDRR 3756 | MDRRP 3757 | MDT 3758 | MDU 3759 | MDV 3760 | MDWD 3761 | MDXG 3762 | MDXH 3763 | ME 3764 | MEC 3765 | MED 3766 | MEDP 3767 | MEG 3768 | MEGI 3769 | MEGL 3770 | MEI 3771 | MEIP 3772 | MELI 3773 | MEOH 3774 | MER 3775 | MERC 3776 | MESA 3777 | MESO 3778 | MET 3779 | META 3780 | METC 3781 | METCB 3782 | METCL 3783 | MFA 3784 | MFAN 3785 | MFAO 3786 | MFC 3787 | MFG 3788 | MFH 3789 | MFI 3790 | MFIC 3791 | MFICL 3792 | MFIN 3793 | MFM 3794 | MG 3795 | MGA 3796 | MGEE 3797 | MGF 3798 | MGIC 3799 | MGIH 3800 | MGLD 3801 | MGM 3802 | MGNI 3803 | MGNX 3804 | MGOL 3805 | MGPI 3806 | MGR 3807 | MGRB 3808 | MGRC 3809 | MGRD 3810 | MGRE 3811 | MGRM 3812 | MGRX 3813 | MGTX 3814 | MGX 3815 | MGY 3816 | MGYR 3817 | MHD 3818 | MHF 3819 | MHH 3820 | MHI 3821 | MHK 3822 | MHLA 3823 | MHLD 3824 | MHN 3825 | MHNC 3826 | MHO 3827 | MHUA 3828 | MI 3829 | MIDD 3830 | MIGI 3831 | MIN 3832 | MIND 3833 | MIO 3834 | MIR 3835 | MIRA 3836 | MIRM 3837 | MIST 3838 | MITA 3839 | MITAU 3840 | MITK 3841 | MITN 3842 | MITP 3843 | MITQ 3844 | MITT 3845 | MIY 3846 | MKC 3847 | MKDW 3848 | MKFG 3849 | MKL 3850 | MKSI 3851 | MKTW 3852 | MKTX 3853 | ML 3854 | MLAB 3855 | MLCO 3856 | MLEC 3857 | MLECW 3858 | MLGO 3859 | MLI 3860 | MLKN 3861 | MLM 3862 | MLNK 3863 | MLP 3864 | MLR 3865 | MLSS 3866 | MLTX 3867 | MLYS 3868 | MMA 3869 | MMC 3870 | MMD 3871 | MMI 3872 | MMLP 3873 | MMM 3874 | MMS 3875 | MMSI 3876 | MMT 3877 | MMU 3878 | MMV 3879 | MMVWW 3880 | MMYT 3881 | MNDO 3882 | MNDR 3883 | MNDY 3884 | MNKD 3885 | MNMD 3886 | MNOV 3887 | MNPR 3888 | MNR 3889 | MNRO 3890 | MNSB 3891 | MNSBP 3892 | MNSO 3893 | MNST 3894 | MNTK 3895 | MNTN 3896 | MNTS 3897 | MNTSW 3898 | MNTX 3899 | MNY 3900 | MNYWW 3901 | MO 3902 | MOB 3903 | MOBBW 3904 | MOBX 3905 | MOD 3906 | MODD 3907 | MODG 3908 | MODV 3909 | MOFG 3910 | MOGO 3911 | MOGU 3912 | MOH 3913 | MOLN 3914 | MOMO 3915 | MOND 3916 | MORN 3917 | MOS 3918 | MOV 3919 | MOVE 3920 | MP 3921 | MPA 3922 | MPAA 3923 | MPB 3924 | MPC 3925 | MPLN 3926 | MPLX 3927 | MPTI 3928 | MPU 3929 | MPV 3930 | MPW 3931 | MPWR 3932 | MPX 3933 | MQ 3934 | MQT 3935 | MQY 3936 | MRAM 3937 | MRBK 3938 | MRC 3939 | MRCC 3940 | MRCY 3941 | MREO 3942 | MRIN 3943 | MRK 3944 | MRKR 3945 | MRM 3946 | MRNA 3947 | MRNO 3948 | MRNOW 3949 | MRNS 3950 | MRO 3951 | MRSN 3952 | MRT 3953 | MRTN 3954 | MRUS 3955 | MRVI 3956 | MRVL 3957 | MRX 3958 | MS 3959 | MSA 3960 | MSAI 3961 | MSAIW 3962 | MSB 3963 | MSBI 3964 | MSBIP 3965 | MSC 3966 | MSCI 3967 | MSD 3968 | MSDL 3969 | MSEX 3970 | MSFT 3971 | MSGE 3972 | MSGM 3973 | MSGS 3974 | MSI 3975 | MSM 3976 | MSN 3977 | MSS 3978 | MSSA 3979 | MSSAW 3980 | MSTR 3981 | MT 3982 | MTA 3983 | MTAL 3984 | MTB 3985 | MTC 3986 | MTCH 3987 | MTD 3988 | MTDR 3989 | MTEK 3990 | MTEKW 3991 | MTEM 3992 | MTEN 3993 | MTEX 3994 | MTG 3995 | MTH 3996 | MTLS 3997 | MTN 3998 | MTNB 3999 | MTR 4000 | MTRN 4001 | MTRX 4002 | MTSI 4003 | MTTR 4004 | MTUS 4005 | MTW 4006 | MTX 4007 | MTZ 4008 | MU 4009 | MUA 4010 | MUC 4011 | MUE 4012 | MUFG 4013 | MUI 4014 | MUJ 4015 | MULN 4016 | MUR 4017 | MURA 4018 | MUSA 4019 | MUX 4020 | MVBF 4021 | MVF 4022 | MVIS 4023 | MVO 4024 | MVST 4025 | MVSTW 4026 | MVT 4027 | MWA 4028 | MWG 4029 | MX 4030 | MXC 4031 | MXCT 4032 | MXE 4033 | MXF 4034 | MXL 4035 | MYD 4036 | MYE 4037 | MYFW 4038 | MYGN 4039 | MYI 4040 | MYN 4041 | MYNA 4042 | MYND 4043 | MYNZ 4044 | MYO 4045 | MYPS 4046 | MYPSW 4047 | MYRG 4048 | MYSZ 4049 | MYTE 4050 | N 4051 | NA 4052 | NAAS 4053 | NABL 4054 | NAC 4055 | NAD 4056 | NAII 4057 | NAK 4058 | NAMS 4059 | NAMSW 4060 | NAN 4061 | NAOV 4062 | NAPA 4063 | NARI 4064 | NAT 4065 | NATH 4066 | NATL 4067 | NATR 4068 | NAUT 4069 | NAVI 4070 | NAZ 4071 | NB 4072 | NBB 4073 | NBBK 4074 | NBH 4075 | NBHC 4076 | NBIX 4077 | NBN 4078 | NBR 4079 | NBTB 4080 | NBTX 4081 | NBXG 4082 | NBY 4083 | NC 4084 | NCA 4085 | NCDL 4086 | NCI 4087 | NCL 4088 | NCLH 4089 | NCMI 4090 | NCNA 4091 | NCNC 4092 | NCNCW 4093 | NCNO 4094 | NCPL 4095 | NCPLW 4096 | NCRA 4097 | NCSM 4098 | NCTY 4099 | NCV 4100 | NCZ 4101 | NDAQ 4102 | NDLS 4103 | NDMO 4104 | NDP 4105 | NDRA 4106 | NDSN 4107 | NE 4108 | NEA 4109 | NECB 4110 | NEE 4111 | NEGG 4112 | NEM 4113 | NEN 4114 | NEO 4115 | NEOG 4116 | NEON 4117 | NEOV 4118 | NEOVW 4119 | NEP 4120 | NEPH 4121 | NERV 4122 | NET 4123 | NETD 4124 | NETDU 4125 | NETDW 4126 | NEU 4127 | NEUE 4128 | NEWP 4129 | NEWT 4130 | NEWTG 4131 | NEWTH 4132 | NEWTI 4133 | NEWTZ 4134 | NEXA 4135 | NEXN 4136 | NEXT 4137 | NFBK 4138 | NFE 4139 | NFG 4140 | NFGC 4141 | NFJ 4142 | NFLX 4143 | NG 4144 | NGD 4145 | NGG 4146 | NGL 4147 | NGNE 4148 | NGS 4149 | NGVC 4150 | NGVT 4151 | NHC 4152 | NHI 4153 | NHS 4154 | NHTC 4155 | NI 4156 | NIC 4157 | NICE 4158 | NIE 4159 | NIM 4160 | NINE 4161 | NIO 4162 | NIOBW 4163 | NIPG 4164 | NISN 4165 | NITO 4166 | NIU 4167 | NIVF 4168 | NIVFW 4169 | NIXX 4170 | NIXXW 4171 | NJR 4172 | NKE 4173 | NKGN 4174 | NKGNW 4175 | NKLA 4176 | NKSH 4177 | NKTR 4178 | NKTX 4179 | NKX 4180 | NL 4181 | NLOP 4182 | NLSP 4183 | NLSPW 4184 | NLY 4185 | NMAI 4186 | NMCO 4187 | NMFC 4188 | NMFCZ 4189 | NMG 4190 | NMHI 4191 | NMHIW 4192 | NMI 4193 | NMIH 4194 | NML 4195 | NMM 4196 | NMR 4197 | NMRA 4198 | NMRK 4199 | NMS 4200 | NMT 4201 | NMTC 4202 | NMZ 4203 | NN 4204 | NNAVW 4205 | NNBR 4206 | NNDM 4207 | NNE 4208 | NNI 4209 | NNN 4210 | NNOX 4211 | NNVC 4212 | NNY 4213 | NOA 4214 | NOAH 4215 | NOC 4216 | NODK 4217 | NOG 4218 | NOK 4219 | NOM 4220 | NOMD 4221 | NOTE 4222 | NOTV 4223 | NOV 4224 | NOVA 4225 | NOVT 4226 | NOW 4227 | NPAB 4228 | NPABW 4229 | NPCE 4230 | NPCT 4231 | NPFD 4232 | NPK 4233 | NPO 4234 | NPV 4235 | NPWR 4236 | NQP 4237 | NR 4238 | NRBO 4239 | NRC 4240 | NRDS 4241 | NRDY 4242 | NREF 4243 | NRG 4244 | NRGV 4245 | NRIM 4246 | NRIX 4247 | NRK 4248 | NRO 4249 | NRP 4250 | NRSN 4251 | NRSNW 4252 | NRT 4253 | NRUC 4254 | NRXP 4255 | NRXPW 4256 | NRXS 4257 | NSA 4258 | NSC 4259 | NSIT 4260 | NSP 4261 | NSPR 4262 | NSSC 4263 | NSTS 4264 | NSYS 4265 | NTAP 4266 | NTB 4267 | NTBL 4268 | NTCT 4269 | NTES 4270 | NTG 4271 | NTGR 4272 | NTIC 4273 | NTIP 4274 | NTLA 4275 | NTNX 4276 | NTR 4277 | NTRA 4278 | NTRB 4279 | NTRBW 4280 | NTRP 4281 | NTRS 4282 | NTRSO 4283 | NTST 4284 | NTWK 4285 | NTZ 4286 | NU 4287 | NUE 4288 | NUKK 4289 | NUKKW 4290 | NURO 4291 | NUS 4292 | NUTX 4293 | NUV 4294 | NUVB 4295 | NUVL 4296 | NUW 4297 | NUWE 4298 | NUZE 4299 | NVA 4300 | NVAC 4301 | NVACR 4302 | NVAWW 4303 | NVAX 4304 | NVCR 4305 | NVCT 4306 | NVDA 4307 | NVEC 4308 | NVEE 4309 | NVEI 4310 | NVFY 4311 | NVG 4312 | NVGS 4313 | NVMI 4314 | NVNI 4315 | NVNIW 4316 | NVNO 4317 | NVO 4318 | NVOS 4319 | NVR 4320 | NVRI 4321 | NVRO 4322 | NVS 4323 | NVST 4324 | NVT 4325 | NVTS 4326 | NVVE 4327 | NVVEW 4328 | NVX 4329 | NWBI 4330 | NWE 4331 | NWFL 4332 | NWG 4333 | NWGL 4334 | NWL 4335 | NWN 4336 | NWPX 4337 | NWS 4338 | NWSA 4339 | NWTN 4340 | NWTNW 4341 | NX 4342 | NXC 4343 | NXDT 4344 | NXE 4345 | NXG 4346 | NXGL 4347 | NXGLW 4348 | NXJ 4349 | NXL 4350 | NXLIW 4351 | NXN 4352 | NXP 4353 | NXPI 4354 | NXPL 4355 | NXPLW 4356 | NXRT 4357 | NXST 4358 | NXT 4359 | NXTC 4360 | NXTT 4361 | NXU 4362 | NYAX 4363 | NYC 4364 | NYCB 4365 | NYMT 4366 | NYMTI 4367 | NYMTL 4368 | NYMTM 4369 | NYMTN 4370 | NYMTZ 4371 | NYT 4372 | NYXH 4373 | NZF 4374 | O 4375 | OABI 4376 | OABIW 4377 | OAK 4378 | OAKU 4379 | OAKUR 4380 | OAKUU 4381 | OAKUW 4382 | OB 4383 | OBDC 4384 | OBDE 4385 | OBE 4386 | OBIO 4387 | OBK 4388 | OBLG 4389 | OBT 4390 | OC 4391 | OCC 4392 | OCCI 4393 | OCCIM 4394 | OCCIN 4395 | OCCIO 4396 | OCEA 4397 | OCEAW 4398 | OCFC 4399 | OCFCP 4400 | OCFT 4401 | OCG 4402 | OCGN 4403 | OCS 4404 | OCSAW 4405 | OCSL 4406 | OCTO 4407 | OCUL 4408 | OCUP 4409 | OCX 4410 | ODC 4411 | ODD 4412 | ODFL 4413 | ODP 4414 | ODV 4415 | OEC 4416 | OESX 4417 | OFG 4418 | OFIX 4419 | OFLX 4420 | OFS 4421 | OFSSH 4422 | OGE 4423 | OGEN 4424 | OGI 4425 | OGN 4426 | OGS 4427 | OHI 4428 | OI 4429 | OIA 4430 | OII 4431 | OIS 4432 | OKE 4433 | OKLO 4434 | OKTA 4435 | OKUR 4436 | OKYO 4437 | OLB 4438 | OLED 4439 | OLLI 4440 | OLMA 4441 | OLN 4442 | OLO 4443 | OLP 4444 | OLPX 4445 | OM 4446 | OMAB 4447 | OMC 4448 | OMCC 4449 | OMCL 4450 | OMER 4451 | OMEX 4452 | OMF 4453 | OMGA 4454 | OMH 4455 | OMI 4456 | OMIC 4457 | ON 4458 | ONB 4459 | ONBPO 4460 | ONBPP 4461 | ONCO 4462 | ONCT 4463 | ONCY 4464 | ONDS 4465 | ONEW 4466 | ONFO 4467 | ONFOW 4468 | ONIT 4469 | ONL 4470 | ONMD 4471 | ONMDW 4472 | ONON 4473 | ONTF 4474 | ONTO 4475 | ONVO 4476 | ONYX 4477 | OOMA 4478 | OP 4479 | OPAD 4480 | OPAL 4481 | OPBK 4482 | OPCH 4483 | OPEN 4484 | OPFI 4485 | OPHC 4486 | OPI 4487 | OPINL 4488 | OPK 4489 | OPOF 4490 | OPP 4491 | OPRA 4492 | OPRT 4493 | OPRX 4494 | OPT 4495 | OPTN 4496 | OPTT 4497 | OPTX 4498 | OPTXW 4499 | OPXS 4500 | OPY 4501 | OR 4502 | ORA 4503 | ORAN 4504 | ORC 4505 | ORCL 4506 | ORGN 4507 | ORGNW 4508 | ORGO 4509 | ORGS 4510 | ORI 4511 | ORIC 4512 | ORKA 4513 | ORKT 4514 | ORLA 4515 | ORLY 4516 | ORMP 4517 | ORN 4518 | ORRF 4519 | OS 4520 | OSBC 4521 | OSCR 4522 | OSIS 4523 | OSK 4524 | OSPN 4525 | OSS 4526 | OST 4527 | OSTX 4528 | OSUR 4529 | OSW 4530 | OTEX 4531 | OTIS 4532 | OTLK 4533 | OTLY 4534 | OTRK 4535 | OTTR 4536 | OUST 4537 | OUT 4538 | OVBC 4539 | OVID 4540 | OVLY 4541 | OVV 4542 | OWL 4543 | OWLT 4544 | OXBR 4545 | OXBRW 4546 | OXLC 4547 | OXLCI 4548 | OXLCL 4549 | OXLCN 4550 | OXLCO 4551 | OXLCP 4552 | OXLCZ 4553 | OXM 4554 | OXSQ 4555 | OXSQG 4556 | OXSQZ 4557 | OXY 4558 | OZ 4559 | OZK 4560 | OZKAP 4561 | P 4562 | PAA 4563 | PAAS 4564 | PAC 4565 | PACB 4566 | PACK 4567 | PACS 4568 | PAG 4569 | PAGP 4570 | PAGS 4571 | PAHC 4572 | PAI 4573 | PAL 4574 | PALI 4575 | PALT 4576 | PAM 4577 | PANL 4578 | PANW 4579 | PAPL 4580 | PAR 4581 | PARA 4582 | PARAA 4583 | PARR 4584 | PASG 4585 | PATH 4586 | PATK 4587 | PAVM 4588 | PAVMZ 4589 | PAVS 4590 | PAX 4591 | PAXS 4592 | PAY 4593 | PAYC 4594 | PAYO 4595 | PAYS 4596 | PAYX 4597 | PB 4598 | PBA 4599 | PBBK 4600 | PBF 4601 | PBFS 4602 | PBH 4603 | PBHC 4604 | PBI 4605 | PBM 4606 | PBMWW 4607 | PBPB 4608 | PBR 4609 | PBT 4610 | PBYI 4611 | PC 4612 | PCAR 4613 | PCB 4614 | PCF 4615 | PCG 4616 | PCH 4617 | PCK 4618 | PCM 4619 | PCN 4620 | PCOR 4621 | PCQ 4622 | PCRX 4623 | PCSA 4624 | PCSC 4625 | PCT 4626 | PCTTU 4627 | PCTTW 4628 | PCTY 4629 | PCVX 4630 | PCYO 4631 | PD 4632 | PDCC 4633 | PDCO 4634 | PDD 4635 | PDEX 4636 | PDFS 4637 | PDI 4638 | PDLB 4639 | PDM 4640 | PDO 4641 | PDS 4642 | PDSB 4643 | PDT 4644 | PDX 4645 | PDYN 4646 | PDYNW 4647 | PEB 4648 | PEBK 4649 | PEBO 4650 | PECO 4651 | PED 4652 | PEG 4653 | PEGA 4654 | PEGY 4655 | PEN 4656 | PENG 4657 | PENN 4658 | PEO 4659 | PEP 4660 | PEPG 4661 | PERF 4662 | PERI 4663 | PESI 4664 | PET 4665 | PETQ 4666 | PETS 4667 | PETWW 4668 | PETZ 4669 | PEV 4670 | PFBC 4671 | PFC 4672 | PFD 4673 | PFE 4674 | PFG 4675 | PFGC 4676 | PFH 4677 | PFIE 4678 | PFIS 4679 | PFL 4680 | PFLT 4681 | PFMT 4682 | PFN 4683 | PFO 4684 | PFS 4685 | PFSI 4686 | PFTA 4687 | PFTAU 4688 | PFTAW 4689 | PFX 4690 | PFXNZ 4691 | PG 4692 | PGC 4693 | PGEN 4694 | PGHL 4695 | PGNY 4696 | PGP 4697 | PGR 4698 | PGRE 4699 | PGRU 4700 | PGY 4701 | PGYWW 4702 | PGZ 4703 | PH 4704 | PHAR 4705 | PHAT 4706 | PHD 4707 | PHG 4708 | PHGE 4709 | PHI 4710 | PHIN 4711 | PHIO 4712 | PHK 4713 | PHM 4714 | PHR 4715 | PHT 4716 | PHUN 4717 | PHVS 4718 | PHX 4719 | PI 4720 | PII 4721 | PIII 4722 | PIIIW 4723 | PIK 4724 | PIM 4725 | PINC 4726 | PINE 4727 | PINS 4728 | PIPR 4729 | PIRS 4730 | PITA 4731 | PITAW 4732 | PIXY 4733 | PJT 4734 | PK 4735 | PKBK 4736 | PKE 4737 | PKG 4738 | PKOH 4739 | PKST 4740 | PKX 4741 | PL 4742 | PLAB 4743 | PLAG 4744 | PLAO 4745 | PLAOW 4746 | PLAY 4747 | PLBC 4748 | PLBY 4749 | PLCE 4750 | PLD 4751 | PLG 4752 | PLL 4753 | PLMJ 4754 | PLMJU 4755 | PLMJW 4756 | PLMR 4757 | PLNT 4758 | PLOW 4759 | PLPC 4760 | PLRX 4761 | PLSE 4762 | PLTK 4763 | PLTR 4764 | PLUG 4765 | PLUR 4766 | PLUS 4767 | PLX 4768 | PLXS 4769 | PLYA 4770 | PLYM 4771 | PM 4772 | PMAX 4773 | PMCB 4774 | PMD 4775 | PMEC 4776 | PMF 4777 | PML 4778 | PMM 4779 | PMN 4780 | PMNT 4781 | PMO 4782 | PMT 4783 | PMTS 4784 | PMTU 4785 | PMVP 4786 | PMX 4787 | PNBK 4788 | PNC 4789 | PNF 4790 | PNFP 4791 | PNFPP 4792 | PNI 4793 | PNNT 4794 | PNR 4795 | PNRG 4796 | PNST 4797 | PNTG 4798 | PNW 4799 | POAI 4800 | POCI 4801 | PODC 4802 | PODD 4803 | POET 4804 | POLA 4805 | POLEU 4806 | POOL 4807 | POR 4808 | POST 4809 | POWI 4810 | POWL 4811 | POWW 4812 | POWWP 4813 | PPBI 4814 | PPBT 4815 | PPC 4816 | PPG 4817 | PPIH 4818 | PPL 4819 | PPSI 4820 | PPT 4821 | PPTA 4822 | PPYA 4823 | PPYAU 4824 | PPYAW 4825 | PR 4826 | PRA 4827 | PRAA 4828 | PRAX 4829 | PRCH 4830 | PRCT 4831 | PRDO 4832 | PRE 4833 | PRENW 4834 | PRFX 4835 | PRG 4836 | PRGO 4837 | PRGS 4838 | PRH 4839 | PRI 4840 | PRIF 4841 | PRIM 4842 | PRK 4843 | PRKS 4844 | PRLB 4845 | PRLD 4846 | PRLH 4847 | PRLHU 4848 | PRM 4849 | PRME 4850 | PRMW 4851 | PRO 4852 | PROC 4853 | PROCW 4854 | PROF 4855 | PROK 4856 | PROP 4857 | PROV 4858 | PRPH 4859 | PRPL 4860 | PRPO 4861 | PRQR 4862 | PRS 4863 | PRSO 4864 | PRT 4865 | PRTA 4866 | PRTC 4867 | PRTG 4868 | PRTH 4869 | PRTS 4870 | PRU 4871 | PRVA 4872 | PRZO 4873 | PSA 4874 | PSBD 4875 | PSEC 4876 | PSF 4877 | PSFE 4878 | PSHG 4879 | PSIG 4880 | PSMT 4881 | PSN 4882 | PSNL 4883 | PSNY 4884 | PSNYW 4885 | PSO 4886 | PSQH 4887 | PSTG 4888 | PSTL 4889 | PSTV 4890 | PSTX 4891 | PSX 4892 | PT 4893 | PTA 4894 | PTC 4895 | PTCT 4896 | PTEN 4897 | PTGX 4898 | PTHL 4899 | PTIX 4900 | PTLE 4901 | PTLO 4902 | PTMN 4903 | PTN 4904 | PTON 4905 | PTPI 4906 | PTSI 4907 | PTVE 4908 | PTY 4909 | PUBM 4910 | PUK 4911 | PULM 4912 | PUMP 4913 | PVBC 4914 | PVH 4915 | PVL 4916 | PW 4917 | PWM 4918 | PWOD 4919 | PWP 4920 | PWR 4921 | PWUP 4922 | PWUPU 4923 | PX 4924 | PXDT 4925 | PXLW 4926 | PXS 4927 | PXSAP 4928 | PXSAW 4929 | PYCR 4930 | PYN 4931 | PYPD 4932 | PYPL 4933 | PYXS 4934 | PZC 4935 | PZG 4936 | PZZA 4937 | Q 4938 | QBTS 4939 | QCOM 4940 | QCRH 4941 | QD 4942 | QDEL 4943 | QETA 4944 | QETAR 4945 | QETAU 4946 | QFIN 4947 | QGEN 4948 | QH 4949 | QIPT 4950 | QLGN 4951 | QLYS 4952 | QMCO 4953 | QMMM 4954 | QNCX 4955 | QNRX 4956 | QNST 4957 | QNTM 4958 | QOMO 4959 | QOMOU 4960 | QQQX 4961 | QRHC 4962 | QRTEA 4963 | QRTEB 4964 | QRTEP 4965 | QRVO 4966 | QS 4967 | QSG 4968 | QSI 4969 | QSIAW 4970 | QSR 4971 | QTI 4972 | QTRX 4973 | QTTB 4974 | QTWO 4975 | QUAD 4976 | QUBT 4977 | QUIK 4978 | QURE 4979 | QVCC 4980 | QVCD 4981 | QXO 4982 | R 4983 | RA 4984 | RACE 4985 | RAIL 4986 | RAMP 4987 | RAND 4988 | RANI 4989 | RAPP 4990 | RAPT 4991 | RARE 4992 | RAVE 4993 | RAY 4994 | RAYA 4995 | RBA 4996 | RBB 4997 | RBBN 4998 | RBC 4999 | RBCAA 5000 | RBKB 5001 | RBLX 5002 | RBOT 5003 | RBRK 5004 | RC 5005 | RCAT 5006 | RCB 5007 | RCC 5008 | RCEL 5009 | RCFA 5010 | RCG 5011 | RCI 5012 | RCKT 5013 | RCKTW 5014 | RCKY 5015 | RCL 5016 | RCM 5017 | RCMT 5018 | RCON 5019 | RCS 5020 | RCUS 5021 | RDACU 5022 | RDCM 5023 | RDDT 5024 | RDFN 5025 | RDHL 5026 | RDI 5027 | RDIB 5028 | RDN 5029 | RDNT 5030 | RDUS 5031 | RDVT 5032 | RDW 5033 | RDWR 5034 | RDY 5035 | RDZN 5036 | RDZNW 5037 | REAL 5038 | REAX 5039 | REBN 5040 | RECT 5041 | REE 5042 | REFI 5043 | REFR 5044 | REG 5045 | REGCO 5046 | REGCP 5047 | REGN 5048 | REI 5049 | REKR 5050 | RELI 5051 | RELIW 5052 | RELL 5053 | RELX 5054 | RELY 5055 | RENB 5056 | RENE 5057 | RENEW 5058 | RENT 5059 | REPL 5060 | REPX 5061 | RERE 5062 | RES 5063 | RETO 5064 | REVB 5065 | REVBW 5066 | REVG 5067 | REX 5068 | REXR 5069 | REYN 5070 | REZI 5071 | RF 5072 | RFAI 5073 | RFAIR 5074 | RFAIU 5075 | RFI 5076 | RFIL 5077 | RFL 5078 | RFM 5079 | RFMZ 5080 | RGA 5081 | RGC 5082 | RGCO 5083 | RGEN 5084 | RGF 5085 | RGLD 5086 | RGLS 5087 | RGNX 5088 | RGP 5089 | RGR 5090 | RGS 5091 | RGT 5092 | RGTI 5093 | RGTIW 5094 | RH 5095 | RHE 5096 | RHI 5097 | RHP 5098 | RICK 5099 | RIG 5100 | RIGL 5101 | RILY 5102 | RILYG 5103 | RILYK 5104 | RILYL 5105 | RILYM 5106 | RILYN 5107 | RILYP 5108 | RILYT 5109 | RILYZ 5110 | RIME 5111 | RIO 5112 | RIOT 5113 | RITM 5114 | RITR 5115 | RIV 5116 | RIVN 5117 | RJF 5118 | RKDA 5119 | RKLB 5120 | RKT 5121 | RL 5122 | RLAY 5123 | RLGT 5124 | RLI 5125 | RLJ 5126 | RLMD 5127 | RLTY 5128 | RLX 5129 | RLYB 5130 | RM 5131 | RMAX 5132 | RMBI 5133 | RMBL 5134 | RMBS 5135 | RMCF 5136 | RMCO 5137 | RMD 5138 | RMI 5139 | RMM 5140 | RMMZ 5141 | RMNI 5142 | RMPL 5143 | RMR 5144 | RMT 5145 | RMTI 5146 | RNA 5147 | RNAC 5148 | RNAZ 5149 | RNG 5150 | RNGR 5151 | RNP 5152 | RNR 5153 | RNST 5154 | RNW 5155 | RNWWW 5156 | RNXT 5157 | ROAD 5158 | ROCK 5159 | ROCL 5160 | ROCLU 5161 | ROCLW 5162 | ROG 5163 | ROIC 5164 | ROIV 5165 | ROK 5166 | ROKU 5167 | ROL 5168 | ROMA 5169 | ROOT 5170 | ROP 5171 | ROST 5172 | RPAY 5173 | RPD 5174 | RPID 5175 | RPM 5176 | RPRX 5177 | RPTX 5178 | RQI 5179 | RR 5180 | RRAC 5181 | RRBI 5182 | RRC 5183 | RRGB 5184 | RRR 5185 | RRX 5186 | RS 5187 | RSF 5188 | RSG 5189 | RSI 5190 | RSKD 5191 | RSLS 5192 | RSSS 5193 | RSVR 5194 | RSVRW 5195 | RTC 5196 | RTO 5197 | RTX 5198 | RUM 5199 | RUMBW 5200 | RUN 5201 | RUSHA 5202 | RUSHB 5203 | RVLV 5204 | RVMD 5205 | RVMDW 5206 | RVNC 5207 | RVP 5208 | RVPH 5209 | RVPHW 5210 | RVSB 5211 | RVSN 5212 | RVSNW 5213 | RVT 5214 | RVTY 5215 | RVYL 5216 | RWAY 5217 | RWAYL 5218 | RWAYZ 5219 | RWT 5220 | RWTN 5221 | RWTO 5222 | RXO 5223 | RXRX 5224 | RXST 5225 | RXT 5226 | RY 5227 | RYAAY 5228 | RYAM 5229 | RYAN 5230 | RYDE 5231 | RYI 5232 | RYN 5233 | RYTM 5234 | RZB 5235 | RZC 5236 | RZLT 5237 | RZLV 5238 | RZLVW 5239 | S 5240 | SA 5241 | SABA 5242 | SABR 5243 | SABS 5244 | SABSW 5245 | SACC 5246 | SACH 5247 | SAFE 5248 | SAFT 5249 | SAGE 5250 | SAH 5251 | SAIA 5252 | SAIC 5253 | SAIH 5254 | SAIHW 5255 | SAJ 5256 | SAM 5257 | SAMG 5258 | SAN 5259 | SANA 5260 | SAND 5261 | SANG 5262 | SANM 5263 | SANW 5264 | SAP 5265 | SAR 5266 | SARO 5267 | SASR 5268 | SAT 5269 | SATL 5270 | SATLW 5271 | SATS 5272 | SATX 5273 | SAVA 5274 | SAVE 5275 | SAY 5276 | SAZ 5277 | SB 5278 | SBAC 5279 | SBBA 5280 | SBC 5281 | SBCF 5282 | SBCWW 5283 | SBET 5284 | SBEV 5285 | SBFG 5286 | SBFM 5287 | SBFMW 5288 | SBGI 5289 | SBH 5290 | SBI 5291 | SBLK 5292 | SBR 5293 | SBRA 5294 | SBS 5295 | SBSI 5296 | SBSW 5297 | SBT 5298 | SBUX 5299 | SBXC 5300 | SBXD 5301 | SCCC 5302 | SCCD 5303 | SCCE 5304 | SCCF 5305 | SCCG 5306 | SCCO 5307 | SCD 5308 | SCE 5309 | SCHL 5310 | SCHW 5311 | SCI 5312 | SCKT 5313 | SCL 5314 | SCLX 5315 | SCLXW 5316 | SCM 5317 | SCNI 5318 | SCNX 5319 | SCOR 5320 | SCPH 5321 | SCPX 5322 | SCS 5323 | SCSC 5324 | SCVL 5325 | SCWO 5326 | SCWX 5327 | SCYX 5328 | SD 5329 | SDA 5330 | SDAWW 5331 | SDGR 5332 | SDHC 5333 | SDHY 5334 | SDIG 5335 | SDOT 5336 | SDRL 5337 | SDST 5338 | SDSTW 5339 | SE 5340 | SEAL 5341 | SEAT 5342 | SEB 5343 | SEDA 5344 | SEDG 5345 | SEE 5346 | SEED 5347 | SEER 5348 | SEG 5349 | SEI 5350 | SEIC 5351 | SELF 5352 | SELX 5353 | SEM 5354 | SEMR 5355 | SENEA 5356 | SENEB 5357 | SENS 5358 | SER 5359 | SERA 5360 | SERV 5361 | SES 5362 | SEVN 5363 | SEZL 5364 | SF 5365 | SFB 5366 | SFBC 5367 | SFBS 5368 | SFHG 5369 | SFIX 5370 | SFL 5371 | SFM 5372 | SFNC 5373 | SFST 5374 | SFWL 5375 | SG 5376 | SGA 5377 | SGBX 5378 | SGC 5379 | SGD 5380 | SGHC 5381 | SGHT 5382 | SGLY 5383 | SGMA 5384 | SGML 5385 | SGMO 5386 | SGMT 5387 | SGN 5388 | SGRP 5389 | SGRY 5390 | SGU 5391 | SHAK 5392 | SHBI 5393 | SHC 5394 | SHCO 5395 | SHCR 5396 | SHEL 5397 | SHEN 5398 | SHFS 5399 | SHFSW 5400 | SHG 5401 | SHIM 5402 | SHIP 5403 | SHLS 5404 | SHLT 5405 | SHMD 5406 | SHMDW 5407 | SHO 5408 | SHOO 5409 | SHOP 5410 | SHOT 5411 | SHOTW 5412 | SHPH 5413 | SHW 5414 | SHYF 5415 | SIBN 5416 | SID 5417 | SIDU 5418 | SIEB 5419 | SIF 5420 | SIFY 5421 | SIG 5422 | SIGA 5423 | SIGI 5424 | SIGIP 5425 | SII 5426 | SILA 5427 | SILC 5428 | SILO 5429 | SILV 5430 | SIM 5431 | SIMA 5432 | SIMAW 5433 | SIMO 5434 | SINT 5435 | SIRI 5436 | SISI 5437 | SITC 5438 | SITE 5439 | SITM 5440 | SJ 5441 | SJM 5442 | SJT 5443 | SJW 5444 | SKE 5445 | SKGR 5446 | SKGRU 5447 | SKGRW 5448 | SKIL 5449 | SKIN 5450 | SKK 5451 | SKLZ 5452 | SKM 5453 | SKT 5454 | SKWD 5455 | SKX 5456 | SKY 5457 | SKYE 5458 | SKYH 5459 | SKYQ 5460 | SKYT 5461 | SKYW 5462 | SKYX 5463 | SLAB 5464 | SLB 5465 | SLDB 5466 | SLDP 5467 | SLDPW 5468 | SLE 5469 | SLF 5470 | SLG 5471 | SLGL 5472 | SLGN 5473 | SLI 5474 | SLM 5475 | SLMBP 5476 | SLN 5477 | SLND 5478 | SLNG 5479 | SLNH 5480 | SLNHP 5481 | SLNO 5482 | SLP 5483 | SLQT 5484 | SLRC 5485 | SLRN 5486 | SLRX 5487 | SLS 5488 | SLSR 5489 | SLVM 5490 | SLXN 5491 | SLXNW 5492 | SM 5493 | SMAR 5494 | SMBC 5495 | SMBK 5496 | SMC 5497 | SMCI 5498 | SMFG 5499 | SMG 5500 | SMHI 5501 | SMID 5502 | SMLR 5503 | SMMT 5504 | SMP 5505 | SMPL 5506 | SMR 5507 | SMRT 5508 | SMSI 5509 | SMTC 5510 | SMTI 5511 | SMTK 5512 | SMWB 5513 | SMX 5514 | SMXT 5515 | SMXWW 5516 | SN 5517 | SNA 5518 | SNAL 5519 | SNAP 5520 | SNAX 5521 | SNAXW 5522 | SNBR 5523 | SNCR 5524 | SNCRL 5525 | SNCY 5526 | SND 5527 | SNDA 5528 | SNDL 5529 | SNDR 5530 | SNDX 5531 | SNES 5532 | SNEX 5533 | SNFCA 5534 | SNGX 5535 | SNN 5536 | SNOA 5537 | SNOW 5538 | SNPS 5539 | SNPX 5540 | SNSE 5541 | SNT 5542 | SNTG 5543 | SNTI 5544 | SNV 5545 | SNX 5546 | SNY 5547 | SO 5548 | SOAR 5549 | SOBO 5550 | SOBR 5551 | SOC 5552 | SOFI 5553 | SOGP 5554 | SOHO 5555 | SOHOB 5556 | SOHON 5557 | SOHOO 5558 | SOHU 5559 | SOJC 5560 | SOJD 5561 | SOJE 5562 | SOL 5563 | SOLV 5564 | SON 5565 | SOND 5566 | SONDW 5567 | SONM 5568 | SONN 5569 | SONO 5570 | SONY 5571 | SOPA 5572 | SOPH 5573 | SOR 5574 | SOS 5575 | SOTK 5576 | SOUN 5577 | SOUNW 5578 | SOWG 5579 | SPAI 5580 | SPB 5581 | SPCB 5582 | SPCE 5583 | SPE 5584 | SPFI 5585 | SPG 5586 | SPGC 5587 | SPGI 5588 | SPH 5589 | SPHR 5590 | SPI 5591 | SPIR 5592 | SPKL 5593 | SPKLU 5594 | SPLP 5595 | SPMC 5596 | SPNS 5597 | SPNT 5598 | SPOK 5599 | SPOT 5600 | SPPL 5601 | SPR 5602 | SPRB 5603 | SPRC 5604 | SPRO 5605 | SPRU 5606 | SPRY 5607 | SPSC 5608 | SPT 5609 | SPTN 5610 | SPWH 5611 | SPXC 5612 | SPXX 5613 | SQ 5614 | SQFT 5615 | SQFTP 5616 | SQFTW 5617 | SQM 5618 | SQNS 5619 | SQSP 5620 | SR 5621 | SRAD 5622 | SRBK 5623 | SRCE 5624 | SRCL 5625 | SRDX 5626 | SRE 5627 | SREA 5628 | SRFM 5629 | SRG 5630 | SRI 5631 | SRL 5632 | SRM 5633 | SRPT 5634 | SRRK 5635 | SRTS 5636 | SRV 5637 | SRZN 5638 | SSB 5639 | SSBI 5640 | SSBK 5641 | SSD 5642 | SSKN 5643 | SSL 5644 | SSNC 5645 | SSP 5646 | SSRM 5647 | SSSS 5648 | SSSSL 5649 | SST 5650 | SSTI 5651 | SSTK 5652 | SSY 5653 | SSYS 5654 | ST 5655 | STAA 5656 | STAF 5657 | STAG 5658 | STBA 5659 | STBX 5660 | STC 5661 | STCN 5662 | STE 5663 | STEC 5664 | STEL 5665 | STEM 5666 | STEP 5667 | STER 5668 | STEW 5669 | STFS 5670 | STG 5671 | STGW 5672 | STHO 5673 | STI 5674 | STIM 5675 | STK 5676 | STKH 5677 | STKL 5678 | STKS 5679 | STLA 5680 | STLD 5681 | STM 5682 | STN 5683 | STNE 5684 | STNG 5685 | STOK 5686 | STR 5687 | STRA 5688 | STRL 5689 | STRM 5690 | STRO 5691 | STRR 5692 | STRRP 5693 | STRS 5694 | STRT 5695 | STRW 5696 | STSS 5697 | STSSW 5698 | STT 5699 | STTK 5700 | STVN 5701 | STWD 5702 | STX 5703 | STXS 5704 | STZ 5705 | SU 5706 | SUGP 5707 | SUI 5708 | SUM 5709 | SUN 5710 | SUNS 5711 | SUP 5712 | SUPN 5713 | SUPV 5714 | SURG 5715 | SURGW 5716 | SUUN 5717 | SUZ 5718 | SVC 5719 | SVCO 5720 | SVII 5721 | SVIIR 5722 | SVIIW 5723 | SVM 5724 | SVMH 5725 | SVMHW 5726 | SVRA 5727 | SVRE 5728 | SVREW 5729 | SVT 5730 | SVV 5731 | SW 5732 | SWAG 5733 | SWAGW 5734 | SWBI 5735 | SWI 5736 | SWIM 5737 | SWIN 5738 | SWK 5739 | SWKH 5740 | SWKHL 5741 | SWKS 5742 | SWTX 5743 | SWVL 5744 | SWVLW 5745 | SWX 5746 | SWZ 5747 | SXC 5748 | SXI 5749 | SXT 5750 | SXTC 5751 | SXTP 5752 | SXTPW 5753 | SY 5754 | SYBT 5755 | SYBX 5756 | SYF 5757 | SYK 5758 | SYM 5759 | SYNA 5760 | SYNX 5761 | SYPR 5762 | SYRA 5763 | SYRE 5764 | SYRS 5765 | SYT 5766 | SYTA 5767 | SYTAW 5768 | SYY 5769 | T 5770 | TAC 5771 | TACT 5772 | TAIT 5773 | TAK 5774 | TAL 5775 | TALK 5776 | TALKW 5777 | TALO 5778 | TANH 5779 | TAOP 5780 | TAP 5781 | TARA 5782 | TARS 5783 | TASK 5784 | TATT 5785 | TAYD 5786 | TBB 5787 | TBBB 5788 | TBBK 5789 | TBC 5790 | TBI 5791 | TBLA 5792 | TBLAW 5793 | TBLD 5794 | TBMC 5795 | TBMCR 5796 | TBN 5797 | TBNK 5798 | TBPH 5799 | TBRG 5800 | TC 5801 | TCBI 5802 | TCBIO 5803 | TCBK 5804 | TCBP 5805 | TCBPW 5806 | TCBS 5807 | TCBX 5808 | TCI 5809 | TCJH 5810 | TCMD 5811 | TCOM 5812 | TCPC 5813 | TCRT 5814 | TCRX 5815 | TCS 5816 | TCTM 5817 | TCX 5818 | TD 5819 | TDC 5820 | TDF 5821 | TDG 5822 | TDOC 5823 | TDS 5824 | TDTH 5825 | TDUP 5826 | TDW 5827 | TDY 5828 | TEAF 5829 | TEAM 5830 | TECH 5831 | TECK 5832 | TECTP 5833 | TECX 5834 | TEF 5835 | TEI 5836 | TEL 5837 | TELA 5838 | TELO 5839 | TELZ 5840 | TEM 5841 | TEN 5842 | TENB 5843 | TENX 5844 | TEO 5845 | TER 5846 | TERN 5847 | TETE 5848 | TETEU 5849 | TETEW 5850 | TEVA 5851 | TEX 5852 | TFC 5853 | TFFP 5854 | TFII 5855 | TFIN 5856 | TFINP 5857 | TFPM 5858 | TFSA 5859 | TFSL 5860 | TFX 5861 | TG 5862 | TGAA 5863 | TGB 5864 | TGI 5865 | TGL 5866 | TGLS 5867 | TGNA 5868 | TGS 5869 | TGT 5870 | TGTX 5871 | TH 5872 | THAR 5873 | THC 5874 | THCH 5875 | THCP 5876 | THCPW 5877 | THFF 5878 | THG 5879 | THM 5880 | THO 5881 | THQ 5882 | THR 5883 | THRD 5884 | THRM 5885 | THRY 5886 | THS 5887 | THTX 5888 | THW 5889 | TIGO 5890 | TIGR 5891 | TIL 5892 | TILE 5893 | TIMB 5894 | TIPT 5895 | TIRX 5896 | TISI 5897 | TITN 5898 | TIVC 5899 | TIXT 5900 | TJX 5901 | TK 5902 | TKC 5903 | TKLF 5904 | TKNO 5905 | TKO 5906 | TKR 5907 | TLF 5908 | TLGY 5909 | TLK 5910 | TLN 5911 | TLPH 5912 | TLRY 5913 | TLS 5914 | TLSA 5915 | TLSI 5916 | TLSIW 5917 | TLYS 5918 | TM 5919 | TMC 5920 | TMCI 5921 | TMCWW 5922 | TMDX 5923 | TME 5924 | TMHC 5925 | TMO 5926 | TMP 5927 | TMQ 5928 | TMTC 5929 | TMTCR 5930 | TMTCU 5931 | TMUS 5932 | TNC 5933 | TNDM 5934 | TNET 5935 | TNFA 5936 | TNGX 5937 | TNK 5938 | TNL 5939 | TNON 5940 | TNONW 5941 | TNXP 5942 | TNYA 5943 | TOI 5944 | TOIIW 5945 | TOL 5946 | TOMZ 5947 | TOON 5948 | TOP 5949 | TOPS 5950 | TORO 5951 | TOST 5952 | TOUR 5953 | TOVX 5954 | TOWN 5955 | TOYO 5956 | TPB 5957 | TPC 5958 | TPCS 5959 | TPET 5960 | TPG 5961 | TPGXL 5962 | TPH 5963 | TPIC 5964 | TPL 5965 | TPR 5966 | TPST 5967 | TPTA 5968 | TPVG 5969 | TPX 5970 | TPZ 5971 | TR 5972 | TRAK 5973 | TRAW 5974 | TRC 5975 | TRDA 5976 | TREE 5977 | TREX 5978 | TRGP 5979 | TRI 5980 | TRIB 5981 | TRIN 5982 | TRINI 5983 | TRINL 5984 | TRINZ 5985 | TRIP 5986 | TRMB 5987 | TRMD 5988 | TRMK 5989 | TRML 5990 | TRN 5991 | TRNO 5992 | TRNR 5993 | TRNS 5994 | TROO 5995 | TROW 5996 | TROX 5997 | TRP 5998 | TRS 5999 | TRSG 6000 | TRST 6001 | TRT 6002 | TRTN 6003 | TRTX 6004 | TRU 6005 | TRUE 6006 | TRUG 6007 | TRUP 6008 | TRV 6009 | TRVG 6010 | TRVI 6011 | TRX 6012 | TS 6013 | TSAT 6014 | TSBK 6015 | TSBX 6016 | TSCO 6017 | TSE 6018 | TSEM 6019 | TSHA 6020 | TSI 6021 | TSLA 6022 | TSLX 6023 | TSM 6024 | TSN 6025 | TSQ 6026 | TSVT 6027 | TT 6028 | TTC 6029 | TTD 6030 | TTE 6031 | TTEC 6032 | TTEK 6033 | TTGT 6034 | TTI 6035 | TTMI 6036 | TTNP 6037 | TTOO 6038 | TTP 6039 | TTSH 6040 | TTWO 6041 | TU 6042 | TURB 6043 | TURN 6044 | TUSK 6045 | TUYA 6046 | TV 6047 | TVC 6048 | TVE 6049 | TVGN 6050 | TVGNW 6051 | TVTX 6052 | TW 6053 | TWFG 6054 | TWG 6055 | TWI 6056 | TWIN 6057 | TWKS 6058 | TWLO 6059 | TWN 6060 | TWO 6061 | TWST 6062 | TX 6063 | TXG 6064 | TXMD 6065 | TXN 6066 | TXNM 6067 | TXO 6068 | TXRH 6069 | TXT 6070 | TY 6071 | TYG 6072 | TYGO 6073 | TYL 6074 | TYRA 6075 | TZOO 6076 | U 6077 | UA 6078 | UAA 6079 | UAL 6080 | UAMY 6081 | UAN 6082 | UAVS 6083 | UBCP 6084 | UBER 6085 | UBFO 6086 | UBS 6087 | UBSI 6088 | UBX 6089 | UBXG 6090 | UCAR 6091 | UCB 6092 | UCL 6093 | UCTT 6094 | UDMY 6095 | UDR 6096 | UE 6097 | UEC 6098 | UEIC 6099 | UFCS 6100 | UFI 6101 | UFPI 6102 | UFPT 6103 | UG 6104 | UGI 6105 | UGP 6106 | UGRO 6107 | UHAL 6108 | UHG 6109 | UHGWW 6110 | UHS 6111 | UHT 6112 | UI 6113 | UIS 6114 | UK 6115 | UKOMW 6116 | UL 6117 | ULBI 6118 | ULCC 6119 | ULH 6120 | ULS 6121 | ULTA 6122 | ULY 6123 | UMAC 6124 | UMBF 6125 | UMC 6126 | UMH 6127 | UNB 6128 | UNCY 6129 | UNF 6130 | UNFI 6131 | UNH 6132 | UNIT 6133 | UNM 6134 | UNMA 6135 | UNP 6136 | UNTY 6137 | UONE 6138 | UONEK 6139 | UP 6140 | UPB 6141 | UPBD 6142 | UPC 6143 | UPLD 6144 | UPS 6145 | UPST 6146 | UPWK 6147 | UPXI 6148 | URBN 6149 | URG 6150 | URGN 6151 | URI 6152 | UROY 6153 | USA 6154 | USAC 6155 | USAP 6156 | USAS 6157 | USAU 6158 | USB 6159 | USCB 6160 | USEA 6161 | USEG 6162 | USFD 6163 | USGO 6164 | USGOW 6165 | USIO 6166 | USLM 6167 | USM 6168 | USNA 6169 | USPH 6170 | UTF 6171 | UTG 6172 | UTHR 6173 | UTI 6174 | UTL 6175 | UTMD 6176 | UTSI 6177 | UTZ 6178 | UUU 6179 | UUUU 6180 | UVE 6181 | UVSP 6182 | UVV 6183 | UWMC 6184 | UXIN 6185 | UZD 6186 | UZE 6187 | UZF 6188 | V 6189 | VABK 6190 | VAC 6191 | VACH 6192 | VACHU 6193 | VACHW 6194 | VAL 6195 | VALE 6196 | VALN 6197 | VALU 6198 | VANI 6199 | VATE 6200 | VBF 6201 | VBFC 6202 | VBNK 6203 | VBTX 6204 | VC 6205 | VCEL 6206 | VCICU 6207 | VCIG 6208 | VCNX 6209 | VCSA 6210 | VCTR 6211 | VCV 6212 | VCYT 6213 | VECO 6214 | VEEA 6215 | VEEAW 6216 | VEEE 6217 | VEEV 6218 | VEL 6219 | VEON 6220 | VERA 6221 | VERB 6222 | VERI 6223 | VERO 6224 | VERU 6225 | VERV 6226 | VERX 6227 | VET 6228 | VEV 6229 | VFC 6230 | VFF 6231 | VFL 6232 | VFS 6233 | VFSWW 6234 | VGAS 6235 | VGASW 6236 | VGI 6237 | VGM 6238 | VGZ 6239 | VHC 6240 | VHI 6241 | VIASP 6242 | VIAV 6243 | VICI 6244 | VICR 6245 | VIGL 6246 | VIK 6247 | VINC 6248 | VINE 6249 | VINO 6250 | VINP 6251 | VIOT 6252 | VIPS 6253 | VIR 6254 | VIRC 6255 | VIRT 6256 | VIRX 6257 | VISL 6258 | VIST 6259 | VITL 6260 | VIV 6261 | VIVK 6262 | VKI 6263 | VKQ 6264 | VKTX 6265 | VLCN 6266 | VLGEA 6267 | VLN 6268 | VLO 6269 | VLRS 6270 | VLT 6271 | VLTO 6272 | VLY 6273 | VLYPN 6274 | VLYPO 6275 | VLYPP 6276 | VMAR 6277 | VMC 6278 | VMCA 6279 | VMCAU 6280 | VMCAW 6281 | VMD 6282 | VMEO 6283 | VMI 6284 | VMO 6285 | VNCE 6286 | VNDA 6287 | VNET 6288 | VNO 6289 | VNOM 6290 | VNRX 6291 | VNT 6292 | VOC 6293 | VOD 6294 | VOR 6295 | VOXR 6296 | VOXX 6297 | VOYA 6298 | VPG 6299 | VPV 6300 | VRA 6301 | VRAR 6302 | VRAX 6303 | VRCA 6304 | VRDN 6305 | VRE 6306 | VREX 6307 | VRM 6308 | VRME 6309 | VRMEW 6310 | VRN 6311 | VRNA 6312 | VRNS 6313 | VRNT 6314 | VRPX 6315 | VRRM 6316 | VRSK 6317 | VRSN 6318 | VRT 6319 | VRTS 6320 | VRTX 6321 | VS 6322 | VSAC 6323 | VSACW 6324 | VSAT 6325 | VSCO 6326 | VSEC 6327 | VSEE 6328 | VSEEW 6329 | VSH 6330 | VSME 6331 | VSSYW 6332 | VST 6333 | VSTA 6334 | VSTE 6335 | VSTEW 6336 | VSTM 6337 | VSTO 6338 | VSTS 6339 | VTAK 6340 | VTEX 6341 | VTGN 6342 | VTLE 6343 | VTMX 6344 | VTN 6345 | VTOL 6346 | VTR 6347 | VTRS 6348 | VTS 6349 | VTSI 6350 | VTVT 6351 | VTYX 6352 | VUZI 6353 | VVI 6354 | VVOS 6355 | VVPR 6356 | VVR 6357 | VVV 6358 | VVX 6359 | VXRT 6360 | VYGR 6361 | VYNE 6362 | VYX 6363 | VZIO 6364 | VZLA 6365 | W 6366 | WAB 6367 | WABC 6368 | WAFD 6369 | WAFDP 6370 | WAFU 6371 | WAL 6372 | WALD 6373 | WALDW 6374 | WASH 6375 | WAT 6376 | WATT 6377 | WAVE 6378 | WAVS 6379 | WAVSU 6380 | WAY 6381 | WB 6382 | WBA 6383 | WBD 6384 | WBS 6385 | WBTN 6386 | WBUY 6387 | WBX 6388 | WCC 6389 | WCN 6390 | WCT 6391 | WD 6392 | WDAY 6393 | WDC 6394 | WDFC 6395 | WDH 6396 | WDI 6397 | WDS 6398 | WEA 6399 | WEAV 6400 | WEC 6401 | WEL 6402 | WELL 6403 | WEN 6404 | WERN 6405 | WES 6406 | WEST 6407 | WETH 6408 | WEX 6409 | WEYS 6410 | WF 6411 | WFC 6412 | WFCF 6413 | WFG 6414 | WFRD 6415 | WGO 6416 | WGS 6417 | WGSWW 6418 | WH 6419 | WHD 6420 | WHF 6421 | WHFCL 6422 | WHG 6423 | WHLM 6424 | WHLR 6425 | WHLRD 6426 | WHLRL 6427 | WHLRP 6428 | WHR 6429 | WIA 6430 | WILC 6431 | WIMI 6432 | WINA 6433 | WING 6434 | WINT 6435 | WINV 6436 | WINVR 6437 | WISA 6438 | WIT 6439 | WIW 6440 | WIX 6441 | WK 6442 | WKC 6443 | WKEY 6444 | WKHS 6445 | WKSP 6446 | WLDN 6447 | WLDS 6448 | WLDSW 6449 | WLFC 6450 | WLGS 6451 | WLK 6452 | WLKP 6453 | WLY 6454 | WLYB 6455 | WM 6456 | WMB 6457 | WMG 6458 | WMK 6459 | WMPN 6460 | WMS 6461 | WMT 6462 | WNC 6463 | WNEB 6464 | WNS 6465 | WNW 6466 | WOK 6467 | WOLF 6468 | WOOF 6469 | WOR 6470 | WORX 6471 | WOW 6472 | WPC 6473 | WPM 6474 | WPP 6475 | WPRT 6476 | WRAP 6477 | WRB 6478 | WRBY 6479 | WRLD 6480 | WRN 6481 | WS 6482 | WSBC 6483 | WSBCP 6484 | WSBF 6485 | WSC 6486 | WSFS 6487 | WSM 6488 | WSO 6489 | WSR 6490 | WST 6491 | WT 6492 | WTBA 6493 | WTFC 6494 | WTFCM 6495 | WTFCP 6496 | WTI 6497 | WTM 6498 | WTMA 6499 | WTO 6500 | WTRG 6501 | WTS 6502 | WTTR 6503 | WTW 6504 | WU 6505 | WULF 6506 | WVE 6507 | WVVI 6508 | WVVIP 6509 | WW 6510 | WWD 6511 | WWR 6512 | WWW 6513 | WY 6514 | WYNN 6515 | WYY 6516 | X 6517 | XAIR 6518 | XBIO 6519 | XBIT 6520 | XBP 6521 | XCH 6522 | XCUR 6523 | XEL 6524 | XELA 6525 | XELAP 6526 | XELB 6527 | XENE 6528 | XERS 6529 | XFLT 6530 | XFOR 6531 | XGN 6532 | XHG 6533 | XHR 6534 | XIN 6535 | XLO 6536 | XMTR 6537 | XNCR 6538 | XNET 6539 | XOM 6540 | XOMA 6541 | XOMAO 6542 | XOMAP 6543 | XOS 6544 | XOSWW 6545 | XP 6546 | XPEL 6547 | XPER 6548 | XPEV 6549 | XPL 6550 | XPO 6551 | XPOF 6552 | XPON 6553 | XPRO 6554 | XRAY 6555 | XRTX 6556 | XRX 6557 | XTIA 6558 | XTKG 6559 | XTLB 6560 | XTNT 6561 | XWEL 6562 | XXII 6563 | XYF 6564 | XYL 6565 | XYLO 6566 | Y 6567 | YALA 6568 | YCBD 6569 | YELP 6570 | YETI 6571 | YEXT 6572 | YGMZ 6573 | YHGJ 6574 | YHNAU 6575 | YI 6576 | YIBO 6577 | YJ 6578 | YMAB 6579 | YMM 6580 | YORW 6581 | YOSH 6582 | YOTA 6583 | YOTAW 6584 | YOU 6585 | YPF 6586 | YQ 6587 | YRD 6588 | YSG 6589 | YTRA 6590 | YUM 6591 | YUMC 6592 | YXT 6593 | YY 6594 | YYAI 6595 | YYGH 6596 | Z 6597 | ZAPP 6598 | ZAPPW 6599 | ZBAO 6600 | ZBH 6601 | ZBIO 6602 | ZBRA 6603 | ZCAR 6604 | ZCARW 6605 | ZCMD 6606 | ZD 6607 | ZDGE 6608 | ZENA 6609 | ZENV 6610 | ZEO 6611 | ZEPP 6612 | ZETA 6613 | ZEUS 6614 | ZG 6615 | ZGN 6616 | ZH 6617 | ZI 6618 | ZIM 6619 | ZIMV 6620 | ZION 6621 | ZIONL 6622 | ZIONO 6623 | ZIONP 6624 | ZIP 6625 | ZJK 6626 | ZJYL 6627 | ZK 6628 | ZKH 6629 | ZKIN 6630 | ZLAB 6631 | ZM 6632 | ZNTL 6633 | ZOM 6634 | ZONE 6635 | ZOOZ 6636 | ZOOZW 6637 | ZPTA 6638 | ZPTAW 6639 | ZS 6640 | ZTEK 6641 | ZTO 6642 | ZTR 6643 | ZTS 6644 | ZUMZ 6645 | ZUO 6646 | ZURA 6647 | ZVIA 6648 | ZVRA 6649 | ZVSA 6650 | ZWS 6651 | ZYME 6652 | ZYXI -------------------------------------------------------------------------------- /stock_research/insider_correlate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Script to analyze the correlation between insider trades and price movements 4 | for a list of stock symbols provided in symbols.txt. 5 | 6 | This script fetches insider trading data, historical price data, earnings dates, 7 | news, and social sentiment for each symbol concurrently. It performs both linear 8 | and non-linear (copula-based) correlation analyses to identify the 'skill' of 9 | specific insiders and general patterns that correlate to price movements. 10 | 11 | Interactive plots are generated to visualize the findings. 12 | 13 | Usage: 14 | python insider_trading_analysis.py 15 | 16 | Dependencies: 17 | - Python 3.x 18 | - pandas 19 | - numpy 20 | - scipy 21 | - statsmodels 22 | - requests 23 | - matplotlib 24 | - seaborn 25 | - plotly 26 | - python-dotenv 27 | - copulas 28 | - yfinance 29 | - aiohttp 30 | - asyncio 31 | - nest_asyncio 32 | """ 33 | 34 | import os 35 | import sys 36 | import requests 37 | import pandas as pd 38 | import numpy as np 39 | import datetime 40 | from scipy.stats import kendalltau, spearmanr, pearsonr 41 | import statsmodels.api as sm 42 | import matplotlib.pyplot as plt 43 | import seaborn as sns 44 | import plotly.express as px 45 | from copulas.multivariate import GaussianMultivariate 46 | from dateutil.parser import parse as date_parse 47 | from dotenv import load_dotenv 48 | import yfinance as yf 49 | import asyncio 50 | import aiohttp 51 | import nest_asyncio 52 | from concurrent.futures import ThreadPoolExecutor 53 | 54 | # Allow nested event loops (necessary when running in certain environments) 55 | nest_asyncio.apply() 56 | 57 | # Load API key from .env file 58 | load_dotenv() 59 | API_KEY = os.getenv('FMP_API_KEY') 60 | 61 | if not API_KEY: 62 | print("Error: FMP_API_KEY not found in .env file.") 63 | sys.exit(1) 64 | 65 | # Base URL for FinancialModelingPrep API 66 | BASE_URL_V4 = 'https://financialmodelingprep.com/api/v4' 67 | BASE_URL_V3 = 'https://financialmodelingprep.com/api/v3' 68 | 69 | # Maximum number of concurrent requests 70 | MAX_CONCURRENT_REQUESTS = 400 71 | 72 | 73 | def read_symbols(filename='test.txt'): 74 | """ 75 | Read stock symbols from a text file. 76 | 77 | Args: 78 | filename (str): Path to the file containing stock symbols. 79 | 80 | Returns: 81 | list: List of stock symbols. 82 | """ 83 | try: 84 | with open(filename, 'r') as file: 85 | symbols = [line.strip().upper() for line in file if line.strip()] 86 | return symbols 87 | except FileNotFoundError: 88 | print(f"Error: File {filename} not found.") 89 | sys.exit(1) 90 | 91 | 92 | async def fetch(session, url): 93 | """ 94 | Asynchronous function to fetch data from a URL. 95 | 96 | Args: 97 | session (aiohttp.ClientSession): The aiohttp session. 98 | url (str): The URL to fetch. 99 | 100 | Returns: 101 | dict or list: The JSON response. 102 | """ 103 | async with session.get(url) as response: 104 | if response.status == 200: 105 | try: 106 | data = await response.json() 107 | return data 108 | except Exception as e: 109 | print(f"Error parsing JSON response from {url}: {e}") 110 | return None 111 | else: 112 | print(f"Error fetching data from {url}: HTTP {response.status}") 113 | return None 114 | 115 | 116 | async def fetch_insider_trading_data(session, symbol): 117 | """ 118 | Asynchronously fetch insider trading data for a given symbol. 119 | 120 | Args: 121 | session (aiohttp.ClientSession): The aiohttp session. 122 | symbol (str): Stock symbol. 123 | 124 | Returns: 125 | pandas.DataFrame: Insider trading data. 126 | """ 127 | url = f"{BASE_URL_V4}/insider-trading?symbol={symbol}&apikey={API_KEY}&limit=1000" 128 | data = await fetch(session, url) 129 | if data: 130 | return pd.DataFrame(data) 131 | else: 132 | return pd.DataFrame() 133 | 134 | 135 | def fetch_historical_price_data(symbol, start_date, end_date): 136 | """ 137 | Fetch historical price data for a given symbol using yfinance. 138 | 139 | Args: 140 | symbol (str): Stock symbol. 141 | start_date (str): Start date in 'YYYY-MM-DD' format. 142 | end_date (str): End date in 'YYYY-MM-DD' format. 143 | 144 | Returns: 145 | pandas.DataFrame: Historical price data. 146 | """ 147 | try: 148 | print(f"Fetching historical price data for {symbol}, from {start_date} to {end_date}") 149 | # Ensure dates are strings 150 | start_date = start_date.strftime('%Y-%m-%d') if isinstance(start_date, datetime.datetime) else start_date 151 | end_date = end_date.strftime('%Y-%m-%d') if isinstance(end_date, datetime.datetime) else end_date 152 | 153 | # Fetch data using yfinance 154 | df = yf.download(symbol, start=start_date, end=end_date, progress=False, threads=False) 155 | if df.empty: 156 | print(f"No price data available for {symbol}.") 157 | return pd.DataFrame() 158 | df.reset_index(inplace=True) 159 | df.rename(columns={'Date': 'date', 'Close': 'close'}, inplace=True) 160 | return df[['date', 'close']] 161 | except Exception as e: 162 | print(f"Error fetching historical price data for {symbol}: {e}") 163 | return pd.DataFrame() 164 | 165 | 166 | async def fetch_earnings_dates(session, symbol): 167 | """ 168 | Asynchronously fetch earnings call dates for a given symbol. 169 | 170 | Args: 171 | session (aiohttp.ClientSession): The aiohttp session. 172 | symbol (str): Stock symbol. 173 | 174 | Returns: 175 | pandas.DataFrame: Earnings call dates. 176 | """ 177 | url = f"{BASE_URL_V4}/earning_call_transcript?symbol={symbol}&apikey={API_KEY}" 178 | data = await fetch(session, url) 179 | if data: 180 | df = pd.DataFrame(data) 181 | if not df.empty and 'Date' in df.columns: 182 | df['Date'] = pd.to_datetime(df['Date'], errors='coerce') 183 | df.dropna(subset=['Date'], inplace=True) 184 | return df[['Quarter', 'Year', 'Date']] 185 | else: 186 | return pd.DataFrame() 187 | else: 188 | return pd.DataFrame() 189 | 190 | 191 | async def fetch_social_sentiment(session, symbol): 192 | """ 193 | Asynchronously fetch historical social sentiment data for a given symbol. 194 | 195 | Args: 196 | session (aiohttp.ClientSession): The aiohttp session. 197 | symbol (str): Stock symbol. 198 | 199 | Returns: 200 | pandas.DataFrame: Social sentiment data. 201 | """ 202 | url = f"{BASE_URL_V4}/historical/social-sentiment?symbol={symbol}&apikey={API_KEY}&limit=1000" 203 | data = await fetch(session, url) 204 | if data: 205 | return pd.DataFrame(data) 206 | else: 207 | return pd.DataFrame() 208 | 209 | 210 | async def fetch_news(session, symbol, start_date, end_date): 211 | """ 212 | Asynchronously fetch stock news for a given symbol between specified dates. 213 | 214 | Args: 215 | session (aiohttp.ClientSession): The aiohttp session. 216 | symbol (str): Stock symbol. 217 | start_date (str): Start date in 'YYYY-MM-DD' format. 218 | end_date (str): End date in 'YYYY-MM-DD' format. 219 | 220 | Returns: 221 | pandas.DataFrame: Stock news data. 222 | """ 223 | url = f"{BASE_URL_V3}/stock_news?tickers={symbol}&from={start_date}&to={end_date}&apikey={API_KEY}&limit=1000" 224 | data = await fetch(session, url) 225 | if data: 226 | return pd.DataFrame(data) 227 | else: 228 | return pd.DataFrame() 229 | 230 | 231 | def process_insider_trades(insider_trades): 232 | """ 233 | Process insider trades data. 234 | 235 | Args: 236 | insider_trades (pandas.DataFrame): Insider trades data. 237 | 238 | Returns: 239 | pandas.DataFrame: Processed insider trades data. 240 | """ 241 | if insider_trades.empty: 242 | return insider_trades 243 | 244 | # Convert date columns to datetime 245 | insider_trades['transactionDate'] = pd.to_datetime(insider_trades['transactionDate'], errors='coerce') 246 | insider_trades['filingDate'] = pd.to_datetime(insider_trades['filingDate'], errors='coerce') 247 | 248 | # Drop rows with invalid dates 249 | insider_trades.dropna(subset=['transactionDate', 'filingDate'], inplace=True) 250 | 251 | # Remove trades with transactionDate in the future 252 | today = pd.Timestamp(datetime.datetime.today().date()) 253 | insider_trades = insider_trades[insider_trades['transactionDate'] <= today] 254 | 255 | # Sort by transaction date 256 | insider_trades.sort_values('transactionDate', inplace=True) 257 | 258 | return insider_trades 259 | 260 | 261 | def analyze_insider_skill(insider_trades, price_data): 262 | """ 263 | Analyze the 'skill' of insiders by correlating their trades with future price movements. 264 | 265 | Args: 266 | insider_trades (pandas.DataFrame): Insider trades data. 267 | price_data (pandas.DataFrame): Historical price data. 268 | 269 | Returns: 270 | pandas.DataFrame: Insider skill analysis results. 271 | """ 272 | results = [] 273 | insiders = insider_trades['reportingName'].unique() 274 | 275 | for insider in insiders: 276 | insider_data = insider_trades[insider_trades['reportingName'] == insider] 277 | correlations = [] 278 | for _, trade in insider_data.iterrows(): 279 | # Get the transaction date 280 | transaction_date = trade['transactionDate'] 281 | 282 | # Get price movement after the trade (next 30 days) 283 | future_prices = price_data[price_data['date'] > transaction_date].head(30) 284 | if not future_prices.empty: 285 | # Calculate price change percentage 286 | price_change = (future_prices['close'].values[-1] - future_prices['close'].values[0]) / future_prices['close'].values[0] 287 | 288 | # Assign +1 for buy, -1 for sell 289 | if trade['acquistionOrDisposition'] == 'A': 290 | trade_direction = 1 291 | elif trade['acquistionOrDisposition'] == 'D': 292 | trade_direction = -1 293 | else: 294 | trade_direction = 0 # Neutral or unknown 295 | 296 | # Correlate trade direction with price change 297 | correlations.append(trade_direction * price_change) 298 | 299 | if correlations: 300 | average_correlation = np.mean(correlations) 301 | results.append({ 302 | 'Insider': insider, 303 | 'AverageCorrelation': average_correlation, 304 | 'NumberOfTrades': len(correlations) 305 | }) 306 | 307 | return pd.DataFrame(results) 308 | 309 | 310 | def perform_correlation_analysis(insider_trades, price_data): 311 | """ 312 | Perform linear and non-linear correlation analysis between insider trades and price movements. 313 | 314 | Args: 315 | insider_trades (pandas.DataFrame): Insider trades data. 316 | price_data (pandas.DataFrame): Historical price data. 317 | 318 | Returns: 319 | dict: Correlation analysis results. 320 | """ 321 | if insider_trades.empty or price_data.empty: 322 | return {} 323 | 324 | # Prepare data 325 | insider_trades['transactionDate'] = pd.to_datetime(insider_trades['transactionDate'], errors='coerce') 326 | price_data = price_data.copy() 327 | price_data['date'] = pd.to_datetime(price_data['date'], errors='coerce') 328 | 329 | # Drop rows with invalid dates 330 | insider_trades.dropna(subset=['transactionDate'], inplace=True) 331 | price_data.dropna(subset=['date'], inplace=True) 332 | 333 | # Calculate daily returns 334 | price_data.set_index('date', inplace=True) 335 | price_data.sort_index(inplace=True) 336 | price_data['Return'] = price_data['close'].pct_change() 337 | 338 | # Aggregate insider trades per day 339 | daily_trades = insider_trades.groupby('transactionDate').agg({ 340 | 'securitiesTransacted': 'sum', 341 | 'price': 'mean' 342 | }).rename(columns={'price': 'AverageTradePrice'}) 343 | 344 | # Merge with price returns 345 | analysis_data = daily_trades.join(price_data['Return'], how='inner') 346 | 347 | # Drop NaN values 348 | analysis_data.dropna(inplace=True) 349 | 350 | if analysis_data.empty: 351 | return {} 352 | 353 | # Linear correlations 354 | pearson_corr, _ = pearsonr(analysis_data['securitiesTransacted'], analysis_data['Return']) 355 | spearman_corr, _ = spearmanr(analysis_data['securitiesTransacted'], analysis_data['Return']) 356 | kendall_corr, _ = kendalltau(analysis_data['securitiesTransacted'], analysis_data['Return']) 357 | 358 | # Non-linear (copula-based) correlation 359 | copula_data = analysis_data[['securitiesTransacted', 'Return']].dropna() 360 | if len(copula_data) < 2: 361 | copula_corr = None 362 | else: 363 | copula_model = GaussianMultivariate() 364 | copula_model.fit(copula_data) 365 | copula_corr = copula_model.correlation # Fixed here, use 'correlation' instead of 'copula.covariance' 366 | 367 | return { 368 | 'pearson_correlation': pearson_corr, 369 | 'spearman_correlation': spearman_corr, 370 | 'kendall_correlation': kendall_corr, 371 | 'copula_covariance_matrix': copula_corr, 372 | 'analysis_data': analysis_data # Return data for plotting 373 | } 374 | 375 | 376 | def analyze_trade_patterns(insider_trades): 377 | """ 378 | Analyze general patterns in insider trades. 379 | 380 | Args: 381 | insider_trades (pandas.DataFrame): Insider trades data. 382 | 383 | Returns: 384 | pandas.Series, pandas.Series: Trade size statistics and trade type counts. 385 | """ 386 | if insider_trades.empty: 387 | return pd.Series(dtype=float), pd.Series(dtype=int) 388 | 389 | # Distribution of trade sizes 390 | trade_sizes = insider_trades['securitiesTransacted'].abs() 391 | trade_types = insider_trades['transactionType'] 392 | 393 | # Summary statistics 394 | trade_size_stats = trade_sizes.describe() 395 | trade_type_counts = trade_types.value_counts() 396 | 397 | return trade_size_stats, trade_type_counts 398 | 399 | 400 | def correlate_with_events(insider_trades, earnings_dates, news_data): 401 | """ 402 | Analyze timing of insider trades relative to earnings events and news. 403 | 404 | Args: 405 | insider_trades (pandas.DataFrame): Insider trades data. 406 | earnings_dates (pandas.DataFrame): Earnings call dates. 407 | news_data (pandas.DataFrame): News articles data. 408 | 409 | Returns: 410 | pandas.DataFrame: Event correlation analysis results. 411 | """ 412 | if insider_trades.empty: 413 | return pd.DataFrame() 414 | 415 | # Convert dates 416 | insider_trades['transactionDate'] = pd.to_datetime(insider_trades['transactionDate'], errors='coerce') 417 | if not earnings_dates.empty: 418 | earnings_dates['Date'] = pd.to_datetime(earnings_dates['Date'], errors='coerce') 419 | if not news_data.empty: 420 | news_data['publishedDate'] = pd.to_datetime(news_data['publishedDate'], errors='coerce') 421 | 422 | # Drop rows with invalid dates 423 | insider_trades.dropna(subset=['transactionDate'], inplace=True) 424 | if not earnings_dates.empty: 425 | earnings_dates.dropna(subset=['Date'], inplace=True) 426 | if not news_data.empty: 427 | news_data.dropna(subset=['publishedDate'], inplace=True) 428 | 429 | # Calculate days to next earnings call 430 | if not earnings_dates.empty: 431 | earnings_dates_sorted = earnings_dates.sort_values('Date') 432 | insider_trades['DaysToNextEarnings'] = insider_trades['transactionDate'].apply( 433 | lambda x: (earnings_dates_sorted[earnings_dates_sorted['Date'] >= x]['Date'] - x).dt.days.min() 434 | ) 435 | else: 436 | insider_trades['DaysToNextEarnings'] = np.nan 437 | 438 | # Merge news data with insider trades 439 | if not news_data.empty: 440 | news_data['Date'] = news_data['publishedDate'].dt.date 441 | insider_trades['Date'] = insider_trades['transactionDate'].dt.date 442 | 443 | merged_data = pd.merge(insider_trades, news_data, on='Date', how='left', suffixes=('', '_news')) 444 | else: 445 | merged_data = insider_trades.copy() 446 | 447 | return merged_data 448 | 449 | 450 | def perform_sentiment_analysis(sentiment_data): 451 | """ 452 | Analyze social sentiment data. 453 | 454 | Args: 455 | sentiment_data (pandas.DataFrame): Social sentiment data. 456 | 457 | Returns: 458 | pandas.DataFrame: Sentiment analysis results. 459 | """ 460 | if sentiment_data.empty: 461 | return pd.DataFrame() 462 | 463 | sentiment_data['date'] = pd.to_datetime(sentiment_data['date'], errors='coerce') 464 | sentiment_data.dropna(subset=['date'], inplace=True) 465 | # Calculate average sentiment 466 | sentiment_data['AverageSentiment'] = (sentiment_data['stocktwitsSentiment'] + sentiment_data['twitterSentiment']) / 2 467 | 468 | return sentiment_data 469 | 470 | 471 | def generate_interactive_plots(symbol, insider_trades, insider_skill, correlation_results, trade_size_stats, trade_type_counts, sentiment_analysis): 472 | """ 473 | Generate interactive plots using Plotly. 474 | 475 | Args: 476 | symbol (str): Stock symbol. 477 | insider_trades (pandas.DataFrame): Insider trades data. 478 | insider_skill (pandas.DataFrame): Insider skill analysis results. 479 | correlation_results (dict): Correlation analysis results. 480 | trade_size_stats (pandas.Series): Trade size statistics. 481 | trade_type_counts (pandas.Series): Trade type counts. 482 | sentiment_analysis (pandas.DataFrame): Sentiment analysis results. 483 | """ 484 | # Plot insider skill 485 | if not insider_skill.empty: 486 | fig_skill = px.bar(insider_skill, x='Insider', y='AverageCorrelation', 487 | title=f'Insider Skill Analysis for {symbol}') 488 | fig_skill.show() 489 | 490 | # Plot correlation scatter 491 | if correlation_results and 'analysis_data' in correlation_results: 492 | analysis_data = correlation_results['analysis_data'] 493 | fig_corr = px.scatter(analysis_data, x='securitiesTransacted', y='Return', 494 | title=f'Correlation between Insider Trades and Returns for {symbol}', 495 | trendline='ols') 496 | fig_corr.show() 497 | 498 | # Plot trade size distribution 499 | if not insider_trades.empty: 500 | fig_trade_size = px.histogram(insider_trades, x='securitiesTransacted', 501 | title=f'Trade Size Distribution for {symbol}') 502 | fig_trade_size.show() 503 | 504 | # Plot trade type counts 505 | if not trade_type_counts.empty: 506 | fig_trade_type = px.bar(trade_type_counts, x=trade_type_counts.index, y=trade_type_counts.values, 507 | title=f'Trade Type Counts for {symbol}', 508 | labels={'x': 'Transaction Type', 'y': 'Count'}) 509 | fig_trade_type.show() 510 | 511 | # Plot sentiment over time 512 | if not sentiment_analysis.empty: 513 | fig_sentiment = px.line(sentiment_analysis, x='date', y='AverageSentiment', 514 | title=f'Social Sentiment Over Time for {symbol}') 515 | fig_sentiment.show() 516 | 517 | 518 | async def main(): 519 | """ 520 | Main function to orchestrate the analysis. 521 | """ 522 | # Read symbols from file 523 | symbols = read_symbols() 524 | 525 | # Create an aiohttp session 526 | async with aiohttp.ClientSession() as session: 527 | 528 | # Limit the number of concurrent tasks 529 | semaphore = asyncio.Semaphore(MAX_CONCURRENT_REQUESTS) 530 | 531 | # Define tasks for fetching data concurrently 532 | tasks = [] 533 | for symbol in symbols: 534 | tasks.append(process_symbol(session, semaphore, symbol)) 535 | 536 | # Run tasks concurrently 537 | await asyncio.gather(*tasks) 538 | 539 | print("Analysis completed for all symbols.") 540 | 541 | 542 | async def process_symbol(session, semaphore, symbol): 543 | """ 544 | Process data and analysis for a single symbol. 545 | 546 | Args: 547 | session (aiohttp.ClientSession): The aiohttp session. 548 | semaphore (asyncio.Semaphore): Semaphore to limit concurrent tasks. 549 | symbol (str): Stock symbol. 550 | """ 551 | async with semaphore: 552 | print(f"Processing symbol: {symbol}") 553 | 554 | # Fetch data concurrently 555 | insider_trades_task = fetch_insider_trading_data(session, symbol) 556 | earnings_dates_task = fetch_earnings_dates(session, symbol) 557 | sentiment_data_task = fetch_social_sentiment(session, symbol) 558 | 559 | # Fetch insider trades, earnings dates, and sentiment data 560 | insider_trades, earnings_dates, sentiment_data = await asyncio.gather( 561 | insider_trades_task, earnings_dates_task, sentiment_data_task 562 | ) 563 | 564 | # Process data 565 | insider_trades = process_insider_trades(insider_trades) 566 | 567 | if insider_trades.empty: 568 | print(f"No insider trading data for {symbol}. Skipping analysis.") 569 | return 570 | 571 | # Determine date range from insider trades 572 | min_transaction_date = insider_trades['transactionDate'].min() 573 | if pd.isnull(min_transaction_date): 574 | print(f"No valid transaction dates for {symbol}. Skipping analysis.") 575 | return 576 | start_date = min_transaction_date 577 | 578 | # Ensure start_date is not later than today 579 | today = datetime.datetime.today() 580 | if start_date > today: 581 | print(f"Start date {start_date} is after today for {symbol}. Skipping analysis.") 582 | return 583 | 584 | # For safety, set a maximum lookback period, e.g., 5 years 585 | earliest_date = today - datetime.timedelta(days=5*365) 586 | if start_date < earliest_date: 587 | start_date = earliest_date 588 | 589 | start_date_str = start_date.strftime('%Y-%m-%d') 590 | end_date_str = today.strftime('%Y-%m-%d') 591 | 592 | # Fetch news data concurrently 593 | news_data_task = fetch_news(session, symbol, start_date_str, end_date_str) 594 | 595 | # Fetch historical price data using ThreadPoolExecutor 596 | loop = asyncio.get_event_loop() 597 | with ThreadPoolExecutor() as executor: 598 | price_data_future = loop.run_in_executor(executor, fetch_historical_price_data, symbol, start_date_str, end_date_str) 599 | news_data = await news_data_task 600 | price_data = await price_data_future 601 | 602 | if price_data.empty: 603 | print(f"No price data for {symbol}. Skipping analysis.") 604 | return 605 | 606 | # Analyze insider skill 607 | insider_skill = analyze_insider_skill(insider_trades, price_data) 608 | print(f"Insider skill analysis for {symbol}:") 609 | print(insider_skill) 610 | 611 | # Perform correlation analysis 612 | correlation_results = perform_correlation_analysis(insider_trades, price_data) 613 | if correlation_results: 614 | print(f"Correlation analysis for {symbol}:") 615 | print({ 616 | 'pearson_correlation': correlation_results.get('pearson_correlation'), 617 | 'spearman_correlation': correlation_results.get('spearman_correlation'), 618 | 'kendall_correlation': correlation_results.get('kendall_correlation') 619 | }) 620 | else: 621 | print(f"Not enough data for correlation analysis for {symbol}.") 622 | 623 | # Analyze trade patterns 624 | trade_size_stats, trade_type_counts = analyze_trade_patterns(insider_trades) 625 | print(f"Trade size statistics for {symbol}:") 626 | print(trade_size_stats) 627 | print(f"Trade type counts for {symbol}:") 628 | print(trade_type_counts) 629 | 630 | # Correlate with events 631 | event_correlation = correlate_with_events(insider_trades, earnings_dates, news_data) 632 | print(f"Event correlation analysis for {symbol} completed.") 633 | 634 | # Perform sentiment analysis 635 | sentiment_analysis = perform_sentiment_analysis(sentiment_data) 636 | print(f"Sentiment analysis for {symbol} completed.") 637 | 638 | # Generate interactive plots 639 | generate_interactive_plots(symbol, insider_trades, insider_skill, correlation_results, trade_size_stats, 640 | trade_type_counts, sentiment_analysis) 641 | 642 | 643 | if __name__ == '__main__': 644 | # Run the main function using asyncio 645 | asyncio.run(main()) 646 | -------------------------------------------------------------------------------- /stock_research/test.txt: -------------------------------------------------------------------------------- 1 | AAPL 2 | NVDA 3 | LMT 4 | GOOG 5 | GOOGL 6 | PLTR 7 | AMZN 8 | META 9 | GM 10 | V -------------------------------------------------------------------------------- /stock_research/top_analysts.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import argparse 3 | 4 | def find_top_analysts(input_csv, top_n=10, min_predictions=5): 5 | # Read the CSV file into a DataFrame 6 | df = pd.read_csv(input_csv) 7 | 8 | # Handle infinite or NaN accuracy values (due to zero avg_error) 9 | df.replace([float('inf'), float('nan')], 0, inplace=True) 10 | 11 | # Filter out analysts with fewer than min_predictions 12 | df_filtered = df[df['total_predictions'] >= min_predictions] 13 | 14 | # Calculate the weighted score: accuracy multiplied by total predictions 15 | df_filtered['weighted_score'] = df_filtered['accuracy'] * df_filtered['total_predictions'] 16 | 17 | # Sort the DataFrame based on weighted_score in descending order 18 | df_sorted = df_filtered.sort_values(by='weighted_score', ascending=False) 19 | 20 | # Select the top N analysts 21 | top_analysts = df_sorted.head(top_n) 22 | 23 | # Print the top analysts 24 | print("\nTop Analysts based on accuracy and volume:") 25 | print(top_analysts[['analystName', 'analystCompany', 'publisher', 'accuracy', 'avg_error', 'total_predictions', 'diversity', 'weighted_score']]) 26 | -------------------------------------------------------------------------------- /stock_research/top_analysts.txt: -------------------------------------------------------------------------------- 1 | Keith Bachman 2 | Brent Thill 3 | Steve Powers 4 | Dana Telsey 5 | Anthony Crowdell 6 | Matthew Hedberg 7 | Brent Bracelin 8 | Raimo Lenschow 9 | John Eade 10 | Vijay Rakesh --------------------------------------------------------------------------------