Search for answers or browse our knowledge base.
N-PX Data (Institutional Votes)
We have processed all N-PX filings filed in 2024 since 6/1 – the date of the latest EDGAR update for these filings. This database has over 24 million recorded vote actions taken by institutional investors on shares for which they control the voting rights. The table below lists the fields in the database and a description of the content of the field. Below the table is an example Python script to more precisely filter and select relevant data.
Most of this data seems reasonable. However there are some clear anomalies. Please consider reading this blog post about how we handled the rows we identified as possibly reporting faulty data (Blog Post N-PX)
Path | S:/directEDGAR_DATA/npxdata.db |
Table Name | npxdata |
Field | Description |
FILER_CIK | Central Index Key of the entity that made the filing |
ACCESSION | ACCESSION number of the filing the data was pulled from - primarily used internally to allow us to identify data to be pulled from the db when an amended filing is made (N-PX/A) |
FORM | N-PX ot N-PX/A |
issuerName | The name of the subject company as reported by the filer - these have not been normalized |
cusip | The CUSIP number of the issuer as reported by the filer |
meetingDate | The date of the meeting when the proposal was put to a vote. |
voteDescription | The proposal as reported by the issuer - generally this should match the language used on the voting card - however, if for example the voting card combines the votes for directors into one item - the filer is to separately report on the votes for each individual director. |
sharesVoted | This represents the number of shares that were reported as voted on the proposal. This value is a real number. |
sharesVoted_ORG | The data is initially read as text - this is the original text string that was transformed to the sharesVoted. We use this value in conjunction with the real version (SharesVoted) for testing purposes to evaluate the quality of the source data. |
sharesOnLoan | The number of shares of this issuer the filer has loaned out - this is stored as a real number in the database. |
sharesOnLoan_ORG | sharesOnLoan - this is the original text value as parsed from the filing. |
voteSource | ISSUER/SECURITY HOLDER - the instigator/originator for the proposal |
directorElections | 1/0 - based on filer classification |
section14ASayOnPayVotes | 1/0 - based on filer classification |
auditRelated | 1/0 - based on filer classification |
investmentCompanyMatters | 1/0 - based on filer classification |
shareholderRightsAndDefenses | 1/0 - based on filer classification |
extraordinaryTransactions | 1/0 - based on filer classification |
capitalStructure | 1/0 - based on filer classification |
compensation | 1/0 - based on filer classification |
corporateGovernance | 1/0 - based on filer classification |
environmentOrClimate | 1/0 - based on filer classification |
humanRightsOrHumanCapitalWorkforce | 1/0 - based on filer classification |
diversityEquityandInclusion | 1/0 - based on filer classification |
otherSocialIssues | 1/0 - based on filer classification |
otherVoteDescription | Filer determined clarification of the voting issue |
voteRecord_howVoted | FOR/AGAINST/ABSTAIN |
voteRecord_sharesVoted | Number of shares in this tranche voted in the manner of howVoted - this value is a real number. |
voteRecord_sharesVoted_ORG | This is the as originally reported text version of the originally reported sharesVoted. |
voteRecord_managementRecommendation | FOR/AGAINST/NONE to reflect the position taken by the filer relative to the recommendation by management. A FOR value indicates that the vote by the filer (FOR/AGAINST) matched the recommendation of management. The SEC guidance explicitly states that the value should be NONE when management has not taken a position. |
This code sample selects all rows from the table where the vote was classified as relating to a Say-On-Pay issue and where the filer (institutional investor) voted against management. The results are saved in a csv file to then compress and download and explore as needed. There are over 200K rows in this file.
import sqlite3
import csv
# Define the database path and output CSV file
db_path = r"S:\directEDGAR_DATA\npxdata.db"
output_csv = r"D:\PhotonUser\My Files\Temporary Files\filtered_data.csv"
try:
# Connect to the SQLite database
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
# Execute the query to select rows with the specified conditions
query = """
SELECT * FROM npxdata
WHERE section14ASayOnPayVotes = 1
AND voteRecord_howVoted = 'AGAINST'
"""
cursor.execute(query)
# Fetch all matching rows
rows = cursor.fetchall()
# Get the column names from the cursor description
column_names = [description[0] for description in cursor.description]
# Open the CSV file for writing
with open(output_csv, mode='w', newline='', encoding='utf-8') as csvfile:
writer = csv.DictWriter(csvfile, fieldnames=column_names)
writer.writeheader()
for row in rows:
try:
# Create a dictionary mapping column names to row values
row_dict = dict(zip(column_names, row))
# Write the row to the CSV file
writer.writerow(row_dict)
except Exception as e:
print(f"Error writing row: {row_dict} - {e}")
print(f"Data successfully written to {output_csv}")
except sqlite3.Error as e:
print(f"Database error: {e}")
except Exception as e:
print(f"Error: {e}")
finally:
# Close the database connection
if conn:
conn.close()