Weighted Average Shares Outstanding Calculator
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #f8f9fa;
color: #333;
line-height: 1.6;
margin: 0;
padding: 0;
}
.container {
max-width: 1000px;
margin: 20px auto;
padding: 20px;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
display: flex;
flex-direction: column;
align-items: center;
}
header {
background-color: #004a99;
color: white;
padding: 20px 0;
width: 100%;
text-align: center;
margin-bottom: 20px;
border-radius: 8px 8px 0 0;
}
header h1 {
margin: 0;
font-size: 2.5em;
font-weight: 700;
}
h2, h3 {
color: #004a99;
margin-top: 1.5em;
margin-bottom: 0.5em;
font-weight: 600;
}
.loan-calc-container {
width: 100%;
background-color: #eef7ff;
padding: 30px;
border-radius: 8px;
margin-bottom: 30px;
box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.05);
}
.input-group {
margin-bottom: 25px;
width: 100%;
text-align: left;
}
.input-group label {
display: block;
margin-bottom: 8px;
font-weight: 600;
color: #004a99;
}
.input-group input[type="number"],
.input-group select {
width: calc(100% – 20px);
padding: 12px 10px;
border: 1px solid #ccc;
border-radius: 5px;
font-size: 1em;
box-sizing: border-box;
transition: border-color 0.3s ease;
}
.input-group input[type="number"]:focus,
.input-group select:focus {
outline: none;
border-color: #007bff;
}
.input-group .helper-text {
font-size: 0.85em;
color: #666;
margin-top: 5px;
display: block;
}
.error-message {
color: #dc3545;
font-size: 0.85em;
margin-top: 5px;
display: none; /* Hidden by default */
}
.error-message.visible {
display: block;
}
.button-group {
display: flex;
gap: 10px;
margin-top: 30px;
justify-content: center;
flex-wrap: wrap;
}
button {
padding: 12px 25px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 1em;
font-weight: 600;
transition: background-color 0.3s ease, transform 0.2s ease;
color: white;
}
button.calculate-btn {
background-color: #007bff;
}
button.calculate-btn:hover {
background-color: #0056b3;
transform: translateY(-1px);
}
button.reset-btn {
background-color: #6c757d;
}
button.reset-btn:hover {
background-color: #5a6268;
transform: translateY(-1px);
}
button.copy-btn {
background-color: #28a745;
}
button.copy-btn:hover {
background-color: #218838;
transform: translateY(-1px);
}
#results {
margin-top: 30px;
padding: 25px;
background-color: #d4edda;
border: 1px solid #c3e6cb;
border-radius: 5px;
text-align: center;
width: 100%;
box-sizing: border-box;
}
#results h3 {
margin-top: 0;
color: #155724;
}
#results .primary-result {
font-size: 2.2em;
font-weight: 700;
color: #004a99;
margin: 10px 0 15px 0;
padding: 10px;
background-color: #ffffff;
border-radius: 5px;
display: inline-block;
min-width: 200px;
}
#results .intermediate-results {
display: flex;
justify-content: space-around;
flex-wrap: wrap;
margin-top: 20px;
gap: 15px;
}
#results .intermediate-value {
text-align: center;
padding: 10px 15px;
background-color: #ffffff;
border-radius: 5px;
border: 1px solid #e0e0e0;
min-width: 150px;
flex-basis: 30%;
box-sizing: border-box;
}
#results .intermediate-value strong {
display: block;
font-size: 1.1em;
color: #007bff;
margin-bottom: 5px;
}
#results .formula-explanation {
font-size: 0.95em;
color: #555;
margin-top: 25px;
padding: 15px;
background-color: #f8f9fa;
border-left: 3px solid #004a99;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 30px;
}
th, td {
padding: 10px 12px;
border: 1px solid #ddd;
text-align: right;
}
thead th {
background-color: #004a99;
color: white;
font-weight: 600;
}
tbody tr:nth-child(even) {
background-color: #f2f2f2;
}
caption {
font-size: 1.1em;
font-weight: 600;
color: #004a99;
margin-bottom: 15px;
caption-side: top;
text-align: left;
}
#chartContainer {
width: 100%;
margin-top: 30px;
background-color: #ffffff;
padding: 20px;
border-radius: 5px;
border: 1px solid #e0e0e0;
box-sizing: border-box;
}
#chartContainer canvas {
width: 100% !important;
height: 300px !important;
}
.chart-caption {
font-size: 0.95em;
color: #555;
margin-top: 15px;
text-align: center;
display: block;
}
main {
width: 100%;
}
section {
margin-bottom: 30px;
padding: 20px;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 1px 5px rgba(0,0,0,0.05);
}
section h2 {
border-bottom: 2px solid #004a99;
padding-bottom: 10px;
margin-bottom: 20px;
}
article p, article ul, article ol {
margin-bottom: 15px;
font-size: 1.05em;
}
article ul {
list-style-type: disc;
padding-left: 30px;
}
article li {
margin-bottom: 8px;
}
article a {
color: #004a99;
text-decoration: none;
font-weight: 600;
}
article a:hover {
text-decoration: underline;
}
.faq-list .faq-item {
margin-bottom: 20px;
padding: 15px;
background-color: #fefefe;
border-left: 3px solid #004a99;
border-radius: 3px;
}
.faq-list .faq-item strong {
display: block;
color: #004a99;
font-size: 1.1em;
margin-bottom: 5px;
}
.related-links {
background-color: #fdfdfd;
padding: 20px;
border-radius: 5px;
border: 1px solid #e0e0e0;
}
.related-links ul {
list-style: none;
padding-left: 0;
}
.related-links li {
margin-bottom: 15px;
}
.related-links a {
font-weight: 700;
}
.related-links span {
font-size: 0.9em;
color: #666;
display: block;
margin-top: 3px;
}
.variable-table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
.variable-table th,
.variable-table td {
padding: 10px 12px;
border: 1px solid #ccc;
text-align: left;
}
.variable-table th {
background-color: #004a99;
color: white;
}
.variable-table td:nth-child(2),
.variable-table td:nth-child(3),
.variable-table td:nth-child(4) {
text-align: center;
}
@media (max-width: 768px) {
.container {
margin: 10px;
padding: 15px;
}
header h1 {
font-size: 2em;
}
#results .primary-result {
font-size: 1.8em;
}
#results .intermediate-value {
flex-basis: 100%;
}
.button-group {
flex-direction: column;
align-items: center;
}
button {
width: 80%;
}
.variable-table th,
.variable-table td {
font-size: 0.9em;
padding: 8px 10px;
}
}
Calculation Results
—
Formula Used: Weighted Average Shares Outstanding = Σ (Shares * Weighting Period) / Total Period Duration. Each share issuance/repurchase is weighted by the fraction of the reporting period it was outstanding.
Shares Outstanding Over Time and Their Weighting
Share Transactions and Weighting
| Transaction Type |
Shares |
Date |
Days Outstanding |
Weighted Contribution |
| Enter data to see transactions. |
What is Weighted Average Shares Outstanding?
The **weighted average shares outstanding** is a crucial metric in financial analysis, representing the average number of a company's shares that were outstanding over a specific period, typically a quarter or a fiscal year. Unlike a simple average, it accounts for the timing of any new shares issued or existing shares repurchased during that period. This calculation is fundamental for accurately determining a company's Earnings Per Share (EPS), a key indicator of profitability on a per-share basis.
Who Should Use It:
- Financial Analysts: To calculate and compare EPS across different companies and periods.
- Investors: To understand a company's true profitability and valuation, especially during periods of significant corporate actions like stock buybacks or new equity offerings.
- Company Management: For internal reporting, performance evaluation, and communication with stakeholders.
- Accountants: To ensure compliance with accounting standards (like GAAP and IFRS) for financial reporting.
Common Misconceptions:
- It's the same as ending shares outstanding: This is incorrect. Ending shares outstanding only reflects the number of shares at the period's close, ignoring the timing of transactions.
- It's a simple average of beginning and ending shares: This is also inaccurate if significant share changes occurred mid-period.
- It only applies to public companies: While most critical for public companies reporting EPS, private companies can also use it for internal valuation and analysis.
Weighted Average Shares Outstanding Formula and Mathematical Explanation
The core principle behind calculating **weighted average shares outstanding** is to give each share a "weight" based on how long it was outstanding during the reporting period. This ensures that shares issued or repurchased early in the period have a greater impact than those issued or repurchased late in the period.
The general formula can be expressed as:
Weighted Average Shares Outstanding = Σ (Number of Shares × Weighting Period) / Total Period Duration
Let's break down the components:
- Identify the Period: Define the reporting period (e.g., January 1 to March 31).
- Determine Shares Outstanding at Each Point: Track the number of shares outstanding at the beginning of the period and immediately after any event (issuance or repurchase) that changes the total number of shares.
- Calculate the Duration of Each Share Block: For each block of shares (e.g., shares outstanding from the start until the first issuance, or shares issued on a specific date until the period end), calculate how long they were outstanding within the reporting period. This is often expressed in days, but can also be months or fractions of a year.
- Calculate the Weighting Period: This is the fraction of the total reporting period that a specific block of shares was outstanding. For example, if the period is 90 days and a block of shares was outstanding for 45 days, its weighting period is 45/90 = 0.5.
- Calculate the Weighted Contribution: Multiply the number of shares in each block by its corresponding weighting period.
- Sum the Weighted Contributions: Add up the weighted contributions from all blocks of shares.
- Divide by Total Period Duration: Divide the sum of weighted contributions by the total number of days (or months, or fractions of a year) in the reporting period.
Variables Explained:
| Variable |
Meaning |
Unit |
Typical Range |
| Sinitial |
Shares outstanding at the beginning of the period. |
Shares |
Positive Integer |
| Sissued |
Number of shares issued during the period. |
Shares |
Non-negative Integer |
| Dissue |
Date shares were issued. |
Date |
Within the reporting period |
| Srepurchased |
Number of shares repurchased during the period. |
Shares |
Non-negative Integer |
| Drepurchase |
Date shares were repurchased. |
Date |
Within the reporting period |
| Dend |
End date of the reporting period. |
Date |
End of reporting period |
| Daysperiod |
Total number of days in the reporting period. |
Days |
~90 (Q1/Q3), ~91 (Q2), ~92 (Q4), ~365/366 (Year) |
| Daysoutstanding, i |
Number of days a specific block of shares was outstanding during the period. |
Days |
0 to Daysperiod |
| Wi |
Weighting factor for block 'i' (Daysoutstanding, i / Daysperiod). |
Fraction (0 to 1) |
0 to 1 |
| WASO |
Weighted Average Shares Outstanding. |
Shares |
Positive Number |
Practical Examples (Real-World Use Cases)
Understanding how **weighted average shares outstanding** is calculated in practice is key. Here are a couple of scenarios:
Example 1: Simple Issuance
Scenario: TechStart Inc. is reporting for the first quarter (Jan 1 – Mar 31). They started the quarter with 500,000 shares outstanding. On February 15th, they issued 100,000 new shares via a secondary offering. The quarter has 90 days.
Inputs:
- Starting Shares Outstanding: 500,000
- Shares Issued: 100,000
- Date of Share Issuance: February 15th
- Shares Repurchased: 0
- Date of Share Repurchase: N/A
- Period End Date: March 31st
Calculation:
- Total Days in Period: 90 days (Jan 1 – Mar 31)
- Days initial shares were outstanding: Jan 1 – Mar 31 = 90 days. Weight = 90/90 = 1.0. Contribution = 500,000 * 1.0 = 500,000 shares.
- Days new shares were outstanding: Feb 15 – Mar 31 = 45 days. Weight = 45/90 = 0.5. Contribution = 100,000 * 0.5 = 50,000 shares.
- Total Weighted Shares = 500,000 + 50,000 = 550,000 shares.
Result: Weighted Average Shares Outstanding = 550,000
Interpretation: Even though the company ended with 600,000 shares, the weighted average is 550,000, reflecting that the additional 100,000 shares were only outstanding for half the quarter.
Example 2: Repurchase Mid-Quarter
Scenario: AutoParts Co. reports for the second quarter (Apr 1 – Jun 30), which has 91 days. They began with 2,000,000 shares. On May 1st, they repurchased 200,000 shares as part of a buyback program.
Inputs:
- Starting Shares Outstanding: 2,000,000
- Shares Issued: 0
- Date of Share Issuance: N/A
- Shares Repurchased: 200,000
- Date of Share Repurchase: May 1st
- Period End Date: June 30th
Calculation:
- Total Days in Period: 91 days (Apr 1 – Jun 30)
- Days initial shares were outstanding: Apr 1 – Jun 30 = 91 days. Weight = 91/91 = 1.0. Contribution = 2,000,000 * 1.0 = 2,000,000 shares.
- Days repurchased shares were *not* outstanding: Apr 1 – Jun 30 = 91 days total. Shares were repurchased on May 1st. The 200,000 shares were outstanding from Apr 1 – Apr 30 (30 days). Weight = 30/91. Contribution = 200,000 * (30/91) = 65,934 shares (approx).
- Alternative calculation for repurchase:
- Shares outstanding from Apr 1 – Apr 30: 2,000,000. Days: 30. Weight: 30/91. Contribution: 2,000,000 * (30/91) = 659,341.
- Shares outstanding from May 1 – Jun 30: 1,800,000. Days: 61. Weight: 61/91. Contribution: 1,800,000 * (61/91) = 1,202,198.
- Total Weighted Shares = 659,341 + 1,202,198 = 1,861,539 shares.
Result: Weighted Average Shares Outstanding = 1,861,539 (approx.)
Interpretation: The company ended the quarter with 1,800,000 shares. However, the weighted average is higher because for the first 30 days of the quarter, 2,000,000 shares were outstanding. This calculation provides a more accurate average for EPS.
How to Use This Weighted Average Shares Outstanding Calculator
Our **weighted average shares outstanding calculator** is designed for simplicity and accuracy. Follow these steps to get your results:
- Input Starting Shares: Enter the total number of shares outstanding at the very beginning of your reporting period (e.g., January 1st for a Q1 report).
- Enter Share Issuances: If new shares were issued during the period (e.g., through stock options exercised, new equity offerings), enter the number of shares issued in the "Shares Issued During Period" field. Then, select the exact date these shares were issued using the date picker.
- Enter Share Repurchases: If the company bought back shares (treasury stock), enter the number of shares repurchased in the "Shares Repurchased During Period" field. Select the exact date of the repurchase using the date picker.
- Specify Period End Date: Enter the last day of the reporting period you are analyzing (e.g., March 31st for Q1). This is crucial for calculating the duration.
- Calculate: Click the "Calculate" button.
Reading the Results:
- Primary Result (Weighted Avg Shares Outstanding): This is the main output, shown prominently. It represents the average number of shares outstanding over the period, adjusted for the timing of transactions.
- Weighted Shares Issued: Shows the total contribution of newly issued shares, weighted by how long they were outstanding.
- Weighted Shares Repurchased: Shows the total impact of repurchased shares, weighted by how long they *were not* outstanding.
- Total Period (Days): The total duration of the reporting period in days, used as the denominator in the weighting calculation.
- Table: The table provides a detailed breakdown of each transaction, including the days each block of shares was outstanding and its weighted contribution to the average.
- Chart: Visualizes the share count changes and their relative impact over the period.
Decision-Making Guidance: The calculated **weighted average shares outstanding** is vital for computing EPS. A lower WASO (relative to ending shares) can result from significant buybacks, potentially increasing EPS. Conversely, significant issuances increase WASO, potentially diluting EPS. Analyzing these trends helps in understanding a company's financial health and strategic decisions regarding its capital structure.
Key Factors That Affect Weighted Average Shares Outstanding Results
Several factors can significantly influence the **weighted average shares outstanding** calculation and, consequently, a company's financial metrics like EPS:
- Timing of Share Issuances: Shares issued early in a period contribute more heavily to the weighted average than those issued late. A large issuance just before the period ends will have minimal impact on the weighted average for that period.
- Timing of Share Repurchases: Conversely, repurchases made early in the period reduce the weighted average more significantly than those made late. Buying back a large block of shares early reduces the denominator for EPS calculations for the majority of the period.
- Magnitude of Transactions: The sheer number of shares issued or repurchased matters greatly. A small number of shares transacted will have a minor effect, while large buybacks or offerings can substantially shift the weighted average.
- Period Length: The total duration of the reporting period (quarterly vs. annually) affects the weighting. A share issued mid-year is outstanding for 0.5 of the year, but only ~0.25 of a quarter, leading to different weighting factors. The calculation usually uses days for precision.
- Stock Splits and Dividends: While not directly share *issuances* or *repurchases*, stock splits and stock dividends increase the number of shares outstanding. These adjustments are typically applied retroactively to all periods presented for comparability, meaning the WASO for prior periods is restated as if the split/dividend occurred at the beginning of those periods.
- Changes in Share Classes: If a company has different classes of stock (e.g., Class A and Class B common stock, or preferred stock with conversion features), the calculation becomes more complex. Each class may need to be calculated separately, and convertible securities must be assessed for their potential dilutive effect.
- Acquisitions/Divestitures: If a company acquires another company and issues its own stock as payment, this is treated as a share issuance. If it spins off a subsidiary or sells a division, the shares related to that divested entity are removed from outstanding. These events must be carefully dated and accounted for.
Frequently Asked Questions (FAQ)
Q1: Why is the weighted average shares outstanding important for EPS?
A: Earnings Per Share (EPS) is calculated as Net Income / Shares Outstanding. Using the weighted average shares outstanding provides a more accurate and representative denominator than simply using the ending number of shares, especially when there are significant changes in share count during the period. This leads to a more reliable measure of profitability per share.
Q2: How do stock options affect weighted average shares outstanding?
A: When stock options are exercised and new shares are issued, it increases the shares outstanding. These new shares are included in the weighted average calculation from the date they are issued. Unexercised options do not affect the basic weighted average shares outstanding but can impact diluted EPS if "in-the-money".
Q3: What if shares were issued or repurchased on the same day?
A: In such cases, you would typically calculate the net change for that day. However, for precision in the weighted average calculation, it's best practice to treat them as separate events if they occur at different times of the day, or to make a reasonable assumption based on the net effect and the time of day. Most accounting standards prefer treating them distinctly if significant.
Q4: Does a reverse stock split affect the weighted average shares outstanding?
A: Yes, a reverse stock split reduces the number of shares outstanding. Similar to a forward split, accounting standards require that the weighted average shares outstanding for all periods presented be retroactively adjusted as if the reverse split had occurred at the beginning of the earliest period presented. This ensures comparability across periods.
Q5: How are fractional shares handled in the calculation?
A: While share counts are typically whole numbers, if transactions result in fractional shares (e.g., due to dividend reinvestment plans or specific corporate actions), they should be included in the calculation. The weighted average can therefore be a fractional number.
Q6: What is the difference between basic and diluted EPS?
A: Basic EPS uses the basic weighted average shares outstanding. Diluted EPS considers the potential impact of all dilutive securities (like convertible bonds, preferred stock, and stock options) that could increase the number of shares outstanding if exercised or converted. The calculation for diluted EPS involves more complex adjustments.
Q7: Can I use months instead of days for the calculation?
A: Yes, you can use months. If you use months, you would count the number of full months a share block was outstanding and divide by the total number of months in the period (e.g., 12 for a year, 3 for a quarter). Using days is generally more precise, especially for shorter periods or transactions occurring mid-month.
Q8: What if the period end date is before the transaction date?
A: This indicates an input error. The period end date must be on or after any transaction dates within that period. The calculator should ideally validate this, and our tool will highlight such inconsistencies if they arise.
Related Tools and Internal Resources
function calculateWeightedAverageShares() {
var initialShares = parseFloat(document.getElementById("initialShares").value);
var sharesIssued = parseFloat(document.getElementById("sharesIssued").value);
var issueDate = document.getElementById("issueDate").value;
var sharesRepurchased = parseFloat(document.getElementById("sharesRepurchased").value);
var repurchaseDate = document.getElementById("repurchaseDate").value;
var periodEndDate = document.getElementById("periodEndDate").value;
var errors = {};
var today = new Date();
today.setHours(0, 0, 0, 0); // Normalize today's date for comparison
// — Input Validation —
if (isNaN(initialShares) || initialShares < 0) {
errors.initialShares = "Please enter a valid non-negative number for starting shares.";
document.getElementById("initialSharesError").innerText = errors.initialShares;
document.getElementById("initialSharesError").classList.add("visible");
} else {
document.getElementById("initialSharesError").innerText = "";
document.getElementById("initialSharesError").classList.remove("visible");
}
if (isNaN(sharesIssued) || sharesIssued 0 && !issueDate) {
errors.issueDate = "Please select the date shares were issued.";
document.getElementById("issueDateError").innerText = errors.issueDate;
document.getElementById("issueDateError").classList.add("visible");
} else if (issueDate) {
var issueDateObj = new Date(issueDate);
issueDateObj.setHours(0, 0, 0, 0);
if (issueDateObj > today) {
errors.issueDate = "Issue date cannot be in the future.";
document.getElementById("issueDateError").innerText = errors.issueDate;
document.getElementById("issueDateError").classList.add("visible");
} else {
document.getElementById("issueDateError").innerText = "";
document.getElementById("issueDateError").classList.remove("visible");
}
} else {
document.getElementById("issueDateError").innerText = "";
document.getElementById("issueDateError").classList.remove("visible");
}
if (isNaN(sharesRepurchased) || sharesRepurchased 0 && !repurchaseDate) {
errors.repurchaseDate = "Please select the date shares were repurchased.";
document.getElementById("repurchaseDateError").innerText = errors.repurchaseDate;
document.getElementById("repurchaseDateError").classList.add("visible");
} else if (repurchaseDate) {
var repurchaseDateObj = new Date(repurchaseDate);
repurchaseDateObj.setHours(0, 0, 0, 0);
if (repurchaseDateObj > today) {
errors.repurchaseDate = "Repurchase date cannot be in the future.";
document.getElementById("repurchaseDateError").innerText = errors.repurchaseDate;
document.getElementById("repurchaseDateError").classList.add("visible");
} else {
document.getElementById("repurchaseDateError").innerText = "";
document.getElementById("repurchaseDateError").classList.remove("visible");
}
} else {
document.getElementById("repurchaseDateError").innerText = "";
document.getElementById("repurchaseDateError").classList.remove("visible");
}
if (!periodEndDate) {
errors.periodEndDate = "Please select the period end date.";
document.getElementById("periodEndDateError").innerText = errors.periodEndDate;
document.getElementById("periodEndDateError").classList.add("visible");
} else {
var periodEndDateObj = new Date(periodEndDate);
periodEndDateObj.setHours(0, 0, 0, 0);
if (periodEndDateObj > today) {
errors.periodEndDate = "Period end date cannot be in the future.";
document.getElementById("periodEndDateError").innerText = errors.periodEndDate;
document.getElementById("periodEndDateError").classList.add("visible");
} else {
document.getElementById("periodEndDateError").innerText = "";
document.getElementById("periodEndDateError").classList.remove("visible");
}
}
// Check date sequence validity
var issueDateObj = issueDate ? new Date(issueDate) : null;
var repurchaseDateObj = repurchaseDate ? new Date(repurchaseDate) : null;
var periodEndDateObj = periodEndDate ? new Date(periodEndDate) : null;
if (issueDateObj && periodEndDateObj && issueDateObj > periodEndDateObj) {
errors.issueDate = "Issue date cannot be after period end date.";
document.getElementById("issueDateError").innerText = errors.issueDate;
document.getElementById("issueDateError").classList.add("visible");
}
if (repurchaseDateObj && periodEndDateObj && repurchaseDateObj > periodEndDateObj) {
errors.repurchaseDate = "Repurchase date cannot be after period end date.";
document.getElementById("repurchaseDateError").innerText = errors.repurchaseDate;
document.getElementById("repurchaseDateError").classList.add("visible");
}
if (issueDateObj && repurchaseDateObj && issueDateObj > repurchaseDateObj && sharesIssued > 0 && sharesRepurchased > 0) {
// Decide which one to flag or flag both if logic is complex
errors.issueDate = "Issue date should precede repurchase date if both occur.";
errors.repurchaseDate = "Repurchase date should follow issue date if both occur.";
document.getElementById("issueDateError").innerText = errors.issueDate;
document.getElementById("issueDateError").classList.add("visible");
document.getElementById("repurchaseDateError").innerText = errors.repurchaseDate;
document.getElementById("repurchaseDateError").classList.add("visible");
}
if (Object.keys(errors).length > 0) {
document.getElementById("results").style.display = "none";
return;
}
// — Calculation Logic —
var totalPeriodDays = 0;
var weightedSharesIssued = 0;
var weightedSharesRepurchased = 0;
var weightedAvgShares = 0;
var transactions = [];
if (periodEndDate) {
var startDate = new Date(periodEndDate);
// Assuming the period starts on Jan 1st if no start date is provided, or can derive from context like Q1/Q2 etc.
// For simplicity, let's assume a common reporting period start if not explicitly given.
// If we need a specific start date, it would be another input field.
// Let's derive it based on common quarterly reporting: Jan 1, Apr 1, Jul 1, Oct 1
var periodStartDate;
var month = startDate.getMonth();
if (month <= 2) periodStartDate = new Date(startDate.getFullYear(), 0, 1); // Q1
else if (month <= 5) periodStartDate = new Date(startDate.getFullYear(), 3, 1); // Q2
else if (month = 0) { // Only consider initial shares if valid
events.push({ type: 'start', date: periodStartDate, shares: initialShares, weight: 1.0 });
}
if (sharesIssued > 0 && issueDate) {
events.push({ type: 'issue', date: issueDateObj, shares: sharesIssued });
}
if (sharesRepurchased > 0 && repurchaseDate) {
events.push({ type: 'repurchase', date: repurchaseDateObj, shares: sharesRepurchased });
}
events.push({ type: 'end', date: periodEndDateObj, shares: 0 }); // End marker
// Sort events by date
events.sort(function(a, b) {
return a.date.getTime() – b.date.getTime();
});
// Filter out events after period end date (should have been caught by validation but good practice)
events = events.filter(function(event) {
return event.date <= periodEndDateObj;
});
var prevDate = periodStartDate;
var currentSharesOutstanding = initialShares; // Start with initial shares
for (var i = 0; i prevDate.getTime()) {
var timeDiffEvents = currentDate.getTime() – prevDate.getTime();
daysDiff = Math.round(timeDiffEvents / (1000 * 3600 * 24));
}
// Calculate weighted contribution for the period since last event
if (daysDiff > 0 && currentSharesOutstanding > 0) {
var weight = daysDiff / totalPeriodDays;
weightedSum += (currentSharesOutstanding * weight);
transactions.push({
type: "Shares Outstanding",
shares: currentSharesOutstanding,
date: prevDate.toISOString().split('T')[0],
daysOutstanding: daysDiff,
weightedContribution: (currentSharesOutstanding * weight).toFixed(0)
});
}
// Update shares outstanding based on event type
if (event.type === 'issue') {
currentSharesOutstanding += event.shares;
weightedSharesIssued += (event.shares * ( (totalPeriodDays – daysDiff)/totalPeriodDays ) ); // Approx, more precise needed if multiple events
transactions.push({
type: "Issued",
shares: event.shares,
date: event.date.toISOString().split('T')[0],
daysOutstanding: (totalPeriodDays – daysDiff), // Conceptual – this is days it IS outstanding for rest of period
weightedContribution: (event.shares * ((totalPeriodDays – daysDiff)/totalPeriodDays)).toFixed(0) // Approximation
});
} else if (event.type === 'repurchase') {
currentSharesOutstanding -= event.shares;
if (currentSharesOutstanding 0) {
var finalDays = totalPeriodDays – ( (periodEndDateObj.getTime() – prevDate.getTime()) / (1000 * 3600 * 24) );
if (finalDays > 0) {
var weight = finalDays / totalPeriodDays;
weightedSum += (currentSharesOutstanding * weight);
transactions.push({
type: "Ending Balance",
shares: currentSharesOutstanding,
date: periodEndDateObj.toISOString().split('T')[0],
daysOutstanding: finalDays,
weightedContribution: (currentSharesOutstanding * weight).toFixed(0)
});
}
}
}
prevDate = currentDate;
}
// Refined calculation of weighted average shares outstanding
// Re-calculate based on distinct periods between events
weightedSum = 0;
currentSharesOutstanding = initialShares; // Reset for precise calculation
prevDate = periodStartDate;
var transactionTableHtml = ";
// Add initial balance transaction
var initialDays = 0;
if(issueDateObj && issueDateObj > periodStartDate) initialDays = Math.round((issueDateObj.getTime() – periodStartDate.getTime()) / (1000 * 3600 * 24));
else if (repurchaseDateObj && repurchaseDateObj > periodStartDate) initialDays = Math.round((repurchaseDateObj.getTime() – periodStartDate.getTime()) / (1000 * 3600 * 24));
else if (periodEndDate) initialDays = totalPeriodDays;
if (initialShares >= 0 && initialDays > 0) {
weightedSum += initialShares * (initialDays / totalPeriodDays);
transactionTableHtml += `
| Starting Shares |
${initialShares.toLocaleString()} |
${periodStartDate.toISOString().split('T')[0]} |
${initialDays} |
${(initialShares * (initialDays / totalPeriodDays)).toFixed(0).toLocaleString()} |
`;
}
// Process issuances and repurchases chronologically
var sortedTransactions = [];
if (sharesIssued > 0 && issueDate) sortedTransactions.push({ date: issueDateObj, type: 'issue', shares: sharesIssued });
if (sharesRepurchased > 0 && repurchaseDate) sortedTransactions.push({ date: repurchaseDateObj, type: 'repurchase', shares: sharesRepurchased });
sortedTransactions.sort(function(a, b) {
return a.date.getTime() – b.date.getTime();
});
var lastEventDate = periodStartDate;
var sharesForPeriod = initialShares;
for (var j = 0; j lastEventDate.getTime()) {
daysInPeriod = Math.round((txDate.getTime() – lastEventDate.getTime()) / (1000 * 3600 * 24));
}
if (daysInPeriod > 0) {
weightedSum += sharesForPeriod * (daysInPeriod / totalPeriodDays);
transactionTableHtml += `
| ${tx.type === 'issue' ? 'Issued' : 'Repurchased'} |
${tx.type === 'issue' ? `+${tx.shares.toLocaleString()}` : `-${tx.shares.toLocaleString()}`} |
${txDate.toISOString().split('T')[0]} |
${daysInPeriod} |
${(sharesForPeriod * (daysInPeriod / totalPeriodDays)).toFixed(0).toLocaleString()} |
`;
}
// Update shares count for the next period
if (tx.type === 'issue') {
sharesForPeriod += tx.shares;
weightedSharesIssued += tx.shares; // This is cumulative issued, not weighted yet
} else { // repurchase
sharesForPeriod -= tx.shares;
if (sharesForPeriod lastEventDate.getTime()) {
finalDays = Math.round((periodEndDateObj.getTime() – lastEventDate.getTime()) / (1000 * 3600 * 24)) + 1; // +1 to include end date
}
if (finalDays > 0 && sharesForPeriod >= 0) {
weightedSum += sharesForPeriod * (finalDays / totalPeriodDays);
transactionTableHtml += `
| Ending Shares |
${sharesForPeriod.toLocaleString()} |
${periodEndDateObj.toISOString().split('T')[0]} |
${finalDays} |
${(sharesForPeriod * (finalDays / totalPeriodDays)).toFixed(0).toLocaleString()} |
`;
}
if (transactions.length === 0 && initialShares >= 0) { // If no transactions, just use initial shares for the whole period
weightedSum = initialShares;
transactionTableHtml = `
| Initial & Ending Shares |
${initialShares.toLocaleString()} |
${periodStartDate.toISOString().split('T')[0]} to ${periodEndDateObj.toISOString().split('T')[0]} |
${totalPeriodDays} |
${initialShares.toFixed(0).toLocaleString()} |
`;
}
weightedAvgShares = weightedSum;
document.getElementById("weightedAvgShares").innerText = weightedAvgShares.toFixed(0).toLocaleString();
document.getElementById("weightedSharesIssued").innerText = weightedSharesIssued.toFixed(0).toLocaleString();
document.getElementById("weightedSharesRepurchased").innerText = weightedSharesRepurchased.toFixed(0).toLocaleString();
document.getElementById("transactionTableBody").innerHTML = transactionTableHtml;
document.getElementById("results").style.display = "block";
updateChart(initialShares, sharesIssued, issueDate, sharesRepurchased, repurchaseDate, periodEndDate, totalPeriodDays);
} else {
document.getElementById("results").style.display = "none";
}
}
function resetForm() {
document.getElementById("initialShares").value = "1,000,000";
document.getElementById("sharesIssued").value = "0";
document.getElementById("issueDate").value = "";
document.getElementById("sharesRepurchased").value = "0";
document.getElementById("repurchaseDate").value = "";
document.getElementById("periodEndDate").value = ""; // Or set to today's date
document.getElementById("results").style.display = "none";
document.getElementById("transactionTableBody").innerHTML = '
| Enter data to see transactions. |
';
clearChart();
// Clear error messages
var errorElements = document.querySelectorAll('.error-message');
for (var i = 0; i 0) {
assumptions += "- Shares Issued: " + document.getElementById("sharesIssued").value + " on " + document.getElementById("issueDate").value + "\n";
}
if (document.getElementById("sharesRepurchased").value > 0) {
assumptions += "- Shares Repurchased: " + document.getElementById("sharesRepurchased").value + " on " + document.getElementById("repurchaseDate").value + "\n";
}
assumptions += "- Period End Date: " + document.getElementById("periodEndDate").value + "\n";
assumptions += "- Total Period Days: " + totalPeriodDays + "\n";
var textToCopy = "Weighted Average Shares Outstanding Calculation Results:\n\n";
textToCopy += "Primary Result:\n" + weightedAvgShares + "\n\n";
textToCopy += "Intermediate Values:\n";
textToCopy += "- Weighted Shares Issued: " + weightedSharesIssued + "\n";
textToCopy += "- Weighted Shares Repurchased: " + weightedSharesRepurchased + "\n";
textToCopy += "- Total Period (Days): " + totalPeriodDays + "\n\n";
textToCopy += formulaExplanation + "\n\n";
textToCopy += assumptions;
// Use navigator.clipboard for modern browsers
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(textToCopy).then(function() {
alert("Results copied to clipboard!");
}).catch(function(err) {
console.error("Failed to copy text: ", err);
// Fallback for older browsers or specific environments
var textArea = document.createElement("textarea");
textArea.value = textToCopy;
textArea.style.position = "fixed";
textArea.style.left = "-9999px";
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
document.execCommand('copy');
alert("Results copied to clipboard!");
} catch (e) {
alert("Failed to copy results. Please copy manually.");
}
document.body.removeChild(textArea);
});
} else {
// Fallback for older browsers
var textArea = document.createElement("textarea");
textArea.value = textToCopy;
textArea.style.position = "fixed";
textArea.style.left = "-9999px";
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
document.execCommand('copy');
alert("Results copied to clipboard!");
} catch (e) {
alert("Failed to copy results. Please copy manually.");
}
document.body.removeChild(textArea);
}
}
// — Charting Logic —
var chartInstance = null; // To hold the chart instance
function updateChart(initialShares, sharesIssued, issueDate, sharesRepurchased, repurchaseDate, periodEndDate, totalPeriodDays) {
var canvas = document.getElementById('sharesOutstandingChart');
var ctx = canvas.getContext('2d');
// Destroy previous chart instance if it exists
if (chartInstance) {
chartInstance.destroy();
}
if (!periodEndDate || totalPeriodDays <= 0) {
clearChart();
return;
}
var periodEndDateObj = new Date(periodEndDate);
var periodStartDate;
var month = periodEndDateObj.getMonth();
if (month <= 2) periodStartDate = new Date(periodEndDateObj.getFullYear(), 0, 1); // Q1
else if (month <= 5) periodStartDate = new Date(periodEndDateObj.getFullYear(), 3, 1); // Q2
else if (month = periodStartDate && issueDateObj = periodStartDate && repurchaseDateObj <= periodEndDateObj) {
var adjustedShares = initialShares;
if (issueDateObj && issueDateObj 0 ? (initialShares + sharesIssued – sharesRepurchased) : 0 });
// Sort points by date
points.sort(function(a, b) {
return a.date.getTime() – b.date.getTime();
});
// Generate labels and data, ensuring unique dates and correct share counts
var uniqueDates = {};
var currentSharesCount = initialShares;
var processedPoints = [];
// Add initial state
processedPoints.push({ date: periodStartDate, shares: initialShares });
// Add transaction points
if (issueDateObj && issueDateObj >= periodStartDate && issueDateObj = periodStartDate && repurchaseDateObj <= periodEndDateObj) {
var sharesBeforeRepurchase = initialShares;
if (issueDateObj && issueDateObj < repurchaseDateObj) { // If issuance happened before repurchase
sharesBeforeRepurchase += sharesIssued;
}
processedPoints.push({ date: repurchaseDateObj, shares: sharesBeforeRepurchase – sharesRepurchased });
}
// Add end state
var finalShares = initialShares + sharesIssued – sharesRepurchased;
if (finalShares dateMap[dateStr].shares) { // Prioritize later share count if same date
dateMap[dateStr] = p;
}
});
for (var dateKey in dateMap) {
finalProcessedPoints.push(dateMap[dateKey]);
}
finalProcessedPoints.sort(function(a, b) {
return a.date.getTime() – b.date.getTime();
});
// Populate labels and data arrays
finalProcessedPoints.forEach(function(point) {
labels.push(point.date.toISOString().split('T')[0]);
sharesData.push(point.shares);
// Conceptual weighted data – showing the state that contributes
// A true weighted average chart would be complex, this shows the state changes
weightedSharesData.push(point.shares); // Placeholder, actual weighted avg is a single number
});
chartInstance = new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: 'Shares Outstanding (Snapshot)',
data: sharesData,
borderColor: '#007bff',
backgroundColor: 'rgba(0, 123, 255, 0.1)',
fill: true,
tension: 0.1
}
// Add a second series if meaningful, e.g., EPS trend if calculable
// For WASO, showing share count changes is primary.
// Could potentially show the 'weighted' value if calculated per segment.
]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true,
title: {
display: true,
text: 'Number of Shares'
}
},
x: {
title: {
display: true,
text: 'Date'
}
}
},
plugins: {
tooltip: {
callbacks: {
label: function(context) {
var label = context.dataset.label || ";
if (label) {
label += ': ';
}
if (context.parsed.y !== null) {
label += context.parsed.y.toLocaleString();
}
return label;
}
}
}
}
}
});
}
function clearChart() {
var canvas = document.getElementById('sharesOutstandingChart');
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (chartInstance) {
chartInstance.destroy();
chartInstance = null;
}
}
// Initial setup for date inputs if needed (e.g., default period end date)
document.addEventListener('DOMContentLoaded', function() {
var today = new Date();
var dd = String(today.getDate()).padStart(2, '0');
var mm = String(today.getMonth() + 1).padStart(2, '0'); // January is 0!
var yyyy = today.getFullYear();
document.getElementById("periodEndDate").value = yyyy + '-' + mm + '-' + dd;
// Trigger calculation on load if there are default values
// calculateWeightedAverageShares(); // Commented out to avoid auto-calc on empty form
});