├── 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
--------------------------------------------------------------------------------