How to Calculate Weighted Average Number of Shares
Accurately determine your company's weighted average number of shares outstanding for EPS calculations and financial analysis.
Weighted Average Shares Calculator
Enter the total number of shares outstanding at the start of the period.
Enter the total number of days in the reporting period (e.g., 365 for a full year).
Number of shares issued or repurchased.
Date when the share change occurred.
Calculation Results
—
Beginning Shares Weighted: —
Change 1 Weighted: —
Total Weighted Shares: —
Formula: (Shares at Start * Days in Period) + (Shares Change 1 * Days After Change 1) + … / Total Days in Period
Weighted Average Shares Calculation Breakdown
Share Issuance and Repurchase Summary
Description
Shares
Date
Days in Period Weighted
Weighted Amount
Shares at Start
—
Beginning of Period
—
—
What is Weighted Average Number of Shares?
The weighted average number of shares outstanding is a crucial metric in corporate finance and accounting. It represents the average number of shares that were outstanding over a specific period, adjusted for the timing of any share issuances or repurchases. This calculation is fundamental for accurately computing earnings per share (EPS), a key profitability indicator that investors use to evaluate a company's performance.
Who should use it?
Publicly traded companies for their financial statements.
Financial analysts and investors to understand a company's per-share profitability.
Internal finance teams for accurate financial reporting.
Companies undergoing mergers, acquisitions, or significant capital restructuring.
Common Misconceptions:
Misconception: It's simply the average of the shares at the beginning and end of the period. Reality: This ignores the timing of share changes, leading to inaccurate results.
Misconception: It only applies to common stock. Reality: While most commonly calculated for common stock, it can be adapted for other classes of shares if they have different rights.
Misconception: It's the same as total shares outstanding. Reality: Total shares outstanding is a snapshot at a point in time, whereas the weighted average considers the entire period.
Understanding how to calculate weighted average number of shares is essential for anyone involved in financial analysis. It ensures that EPS reflects the true earnings attributable to each share over the entire reporting cycle.
Weighted Average Number of Shares Formula and Mathematical Explanation
The core idea behind the weighted average number of shares is to account for the fact that shares outstanding can change throughout a reporting period (e.g., a quarter or a year). Shares issued or repurchased partway through the period are only considered outstanding for the portion of the period they actually existed. The formula ensures that the average reflects this timing.
The general formula is:
Weighted Average Shares = (Sum of [Shares Outstanding * Period Weighted]) / Total Days in Period
Let's break this down:
Identify the Reporting Period: Determine the start and end dates of the period for which you are calculating the weighted average (e.g., January 1 to December 31 for a full year).
Determine Total Days in the Period: Count the total number of days within that period (e.g., 365 for a non-leap year, 366 for a leap year).
Identify All Share Changes: List all instances where the number of shares outstanding changed during the period. This includes new share issuances (e.g., through offerings, stock options exercised) and share repurchases (e.g., buybacks).
Calculate the Weighting Factor for Each Segment: For each distinct period (from the start of the reporting period to the first change, between subsequent changes, and from the last change to the end of the reporting period), calculate the number of days that specific number of shares was outstanding.
Calculate the Weighted Amount for Each Segment: Multiply the number of shares outstanding during each segment by the number of days that specific quantity was outstanding.
Sum the Weighted Amounts: Add up all the weighted amounts calculated in the previous step.
Divide by Total Days: Divide the total sum of weighted amounts by the total number of days in the reporting period.
Variables Explained:
Variable
Meaning
Unit
Typical Range
$N_0$
Number of shares outstanding at the beginning of the period.
Shares
≥ 0
$D_0$
Number of days the initial shares ($N_0$) were outstanding.
Days
0 to Total Days in Period
$N_i$
Number of shares outstanding after the i-th change.
Shares
≥ 0
$D_i$
Number of days the shares ($N_i$) were outstanding.
Where $k$ is the number of share changes during the period.
Practical Examples (Real-World Use Cases)
Let's illustrate the calculation of weighted average number of shares with a couple of scenarios.
Example 1: Simple Issuance During a Year
Scenario: A company, "TechSolutions Inc.", has 1,000,000 shares outstanding at the beginning of the year (January 1st). On April 1st (after 90 days of the 365-day year), they issue an additional 200,000 shares. We need to calculate the weighted average number of shares for the full year.
Inputs:
Shares Issued at Beginning of Period: 1,000,000
Total Days in Period: 365
Share Change 1: 200,000 (Issued)
Date of Change 1: 2023-04-01 (Assuming a non-leap year)
Calculations:
Period 1: From Jan 1 to Mar 31 (90 days). Shares outstanding = 1,000,000. Weighted = 1,000,000 * 90 = 90,000,000
Period 2: From Apr 1 to Dec 31 (275 days). Shares outstanding = 1,000,000 + 200,000 = 1,200,000. Weighted = 1,200,000 * 275 = 330,000,000
Total Weighted Shares = 90,000,000 + 330,000,000 = 420,000,000
Weighted Average Shares = 420,000,000 / 365 = 1,150,684.93 (approx.)
Interpretation: The weighted average number of shares outstanding for TechSolutions Inc. during the year is approximately 1,150,685. This figure will be used to calculate the company's diluted EPS for the year.
Example 2: Issuance and Repurchase Within a Quarter
Scenario: "Global Pharma Corp." starts the quarter (91 days) with 5,000,000 shares. On day 30, they repurchase 500,000 shares. On day 60, they issue 300,000 new shares. Calculate the weighted average shares for the quarter.
Inputs:
Shares Issued at Beginning of Period: 5,000,000
Total Days in Period: 91
Share Change 1: -500,000 (Repurchase)
Date of Change 1: Day 30 of the quarter
Share Change 2: 300,000 (Issued)
Date of Change 2: Day 60 of the quarter
Calculations:
Segment 1: Start to Day 30 (30 days). Shares outstanding = 5,000,000. Weighted = 5,000,000 * 30 = 150,000,000
Segment 2: Day 31 to Day 60 (30 days). Shares outstanding = 5,000,000 – 500,000 = 4,500,000. Weighted = 4,500,000 * 30 = 135,000,000
Segment 3: Day 61 to Day 91 (31 days). Shares outstanding = 4,500,000 + 300,000 = 4,800,000. Weighted = 4,800,000 * 31 = 148,800,000
Weighted Average Shares = 433,800,000 / 91 = 4,767,032.97 (approx.)
Interpretation: The weighted average number of shares for Global Pharma Corp. for this quarter is approximately 4,767,033. This reflects the impact of both the share repurchase and the subsequent issuance on the average share count.
How to Use This Weighted Average Shares Calculator
Our calculator simplifies the process of determining the weighted average number of shares outstanding. Follow these steps:
Enter Starting Shares: Input the number of shares outstanding at the very beginning of your reporting period (e.g., January 1st for an annual report).
Enter Period Length: Specify the total number of days in the reporting period (e.g., 365 for a standard year, 91 for a typical quarter).
Add Share Changes:
Click "Add Another Share Change" for each instance new shares were issued or existing shares were repurchased during the period.
For each change, enter the net number of shares added (positive value) or repurchased (negative value).
Select the exact date the change occurred using the date picker.
Calculate: Click the "Calculate" button. The calculator will automatically compute the weighted average shares.
How to Read Results:
Primary Result (Weighted Average Shares): This is the main output, representing the average number of shares outstanding over the period, adjusted for timing.
Intermediate Values: These show the weighted contribution of the starting shares and each subsequent change.
Table: The summary table provides a clear breakdown of each segment, including the number of days weighted and the resulting weighted amount.
Chart: The dynamic chart visually represents the contribution of each period to the total weighted average shares.
Decision-Making Guidance: The calculated weighted average number of shares is primarily used for the Earnings Per Share (EPS) calculation. A higher weighted average (all else being equal) will decrease EPS, while a lower average will increase it. Understanding the drivers behind changes in this number (issuances vs. repurchases) provides insight into a company's capital management strategy.
Key Factors That Affect Weighted Average Number of Shares Results
Several factors influence the weighted average number of shares, impacting EPS and investor perception:
Timing of Share Transactions: This is the most critical factor. Shares issued on the last day of the period have minimal impact, while shares issued early have a greater effect. Similarly, repurchases early in the period reduce the weighted average more significantly than those late in the period.
Volume of Share Issuances: When a company issues a large number of new shares (e.g., through a secondary offering, stock-based compensation vesting, or acquisitions paid with stock), it directly increases the potential weighted average shares. This can dilute existing shareholders' ownership percentage and earnings.
Volume of Share Repurchases: Conversely, significant share buyback programs reduce the number of outstanding shares. This decreases the weighted average, potentially increasing EPS and signaling management's confidence in the company's valuation.
Stock Splits and Reverse Splits: Stock splits (e.g., 2-for-1) increase the number of shares outstanding. Reverse stock splits decrease them. These actions require restating prior periods' weighted average shares to ensure comparability. For example, if a 2-for-1 split occurs mid-year, the shares before the split are effectively doubled when calculating the weighted average for the entire period.
Convertible Securities: While not directly changing the *basic* weighted average number of shares, the potential issuance of shares from convertible bonds or preferred stock influences the *diluted* EPS calculation, which also relies on weighted average principles.
Acquisitions/Divestitures: If a company acquires another firm using its stock, it increases the share count. If it divests a subsidiary and repurchases shares with the proceeds, it decreases the count. These events significantly impact the weighted average over the affected periods.
Employee Stock Options and Grants: When employees exercise stock options or restricted stock units vest, new shares are typically issued, increasing the outstanding share count and affecting the weighted average calculation for the periods in which these events occur.
Frequently Asked Questions (FAQ)
What is the difference between basic and diluted weighted average shares?
Basic weighted average shares only consider the shares currently outstanding. Diluted weighted average shares include the potential impact of all dilutive securities (like stock options, warrants, and convertible securities) as if they were exercised or converted. This calculator computes the basic weighted average shares.
Does a stock split affect the weighted average calculation?
Yes. A stock split retroactively adjusts the weighted average shares for all prior periods presented to maintain comparability. For example, in a 2-for-1 split, the weighted average shares for all periods are doubled.
How do I handle share changes that occur on the same day?
If multiple changes occur on the same day, you can either treat them as a single net change for that day or, for greater precision, calculate the weighted average for the portions of the day between each transaction. For simplicity, often the net change for the day is used.
What if shares were issued/repurchased on the very first or last day of the period?
If issued on the first day, they count for the entire period. If repurchased on the first day, they don't count for any part of the period. If issued on the last day, they count for zero days. If repurchased on the last day, they count for the entire period (as they were outstanding for most of it).
Why is the weighted average number of shares important for EPS?
Earnings Per Share (EPS) is calculated as Net Income divided by the number of outstanding shares. Using the weighted average ensures that EPS reflects the earnings attributable to the average number of shares held by investors throughout the entire reporting period, providing a more accurate picture of profitability per share.
Can I use fractions of shares in the calculation?
While theoretically possible, share counts are typically whole numbers. However, if dealing with complex instruments or conversions, ensure consistency in your calculations. This calculator assumes whole number inputs for shares.
What is the difference between weighted average shares and treasury stock?
Treasury stock represents shares that a company has repurchased but not retired. While treasury stock reduces the total number of outstanding shares, the calculation of weighted average shares specifically focuses on the *timing* of these repurchases (and issuances) throughout the period.
How often should the weighted average number of shares be calculated?
Companies typically calculate the weighted average number of shares outstanding quarterly and annually for financial reporting purposes, especially for calculating EPS.
var sharesIssuedInput = document.getElementById('sharesIssued');
var daysInPeriodInput = document.getElementById('daysInPeriod');
var weightedAverageSharesResult = document.getElementById('weightedAverageSharesResult');
var weightedSharesPeriod1 = document.getElementById('weightedSharesPeriod1');
var weightedSharesChange1 = document.getElementById('weightedSharesChange1');
var totalWeightedShares = document.getElementById('totalWeightedShares');
var summaryTableBody = document.getElementById('summaryTableBody');
var chart = null;
var chartContext = null;
function isValidNumber(value) {
return !isNaN(parseFloat(value)) && isFinite(value) && parseFloat(value) >= 0;
}
function getDaysInMonth(month, year) {
return new Date(year, month + 1, 0).getDate();
}
function addShareChange() {
var container = document.getElementById('shareChangesContainer');
var rowCount = container.getElementsByClassName('share-change-row').length / 2; // Each change has two inputs
var newChangeDiv = document.createElement('div');
newChangeDiv.className = 'input-group share-change-row';
newChangeDiv.innerHTML = `
Enter net shares issued (positive) or repurchased (negative).
`;
container.appendChild(newChangeDiv);
var newDateDiv = document.createElement('div');
newDateDiv.className = 'input-group share-change-row';
newDateDiv.innerHTML = `
Date when the share change occurred.
`;
container.appendChild(newDateDiv);
}
function validateInputs() {
var errors = false;
var sharesIssued = sharesIssuedInput.value.trim();
var daysInPeriod = daysInPeriodInput.value.trim();
if (sharesIssued === " || !isValidNumber(sharesIssued)) {
document.getElementById('sharesIssuedError').textContent = 'Please enter a valid number of shares.';
document.getElementById('sharesIssuedError').style.display = 'block';
errors = true;
} else {
document.getElementById('sharesIssuedError').textContent = ";
document.getElementById('sharesIssuedError').style.display = 'none';
}
if (daysInPeriod === " || !isValidNumber(daysInPeriod)) {
document.getElementById('daysInPeriodError').textContent = 'Please enter a valid number of days.';
document.getElementById('daysInPeriodError').style.display = 'block';
errors = true;
} else {
document.getElementById('daysInPeriodError').textContent = ";
document.getElementById('daysInPeriodError').style.display = 'none';
}
var shareChangeInputs = document.getElementsByClassName('sharesChanged');
var dateInputs = document.getElementsByClassName('dateOfChange');
for (var i = 0; i < shareChangeInputs.length; i++) {
var sharesChanged = shareChangeInputs[i].value.trim();
var sharesChangedError = shareChangeInputs[i].nextElementSibling; // The span with error message
if (sharesChanged === '' || !isValidNumber(sharesChanged)) {
sharesChangedError.textContent = 'Please enter a valid number.';
sharesChangedError.style.display = 'block';
errors = true;
} else {
sharesChangedError.textContent = '';
sharesChangedError.style.display = 'none';
}
}
for (var i = 0; i < dateInputs.length; i++) {
var dateOfChange = dateInputs[i].value.trim();
var dateError = dateInputs[i].nextElementSibling; // The span with error message
if (dateOfChange === '') {
dateError.textContent = 'Please select a date.';
dateError.style.display = 'block';
errors = true;
} else {
dateError.textContent = '';
dateError.style.display = 'none';
}
}
return !errors;
}
function calculateWeightedAverageShares() {
if (!validateInputs()) {
weightedAverageSharesResult.textContent = 'Invalid Input';
return;
}
var sharesIssuedStart = parseFloat(sharesIssuedInput.value);
var daysInPeriod = parseInt(daysInPeriodInput.value);
var shareChanges = [];
var sharesChangedInputs = document.getElementsByClassName('sharesChanged');
var dateInputs = document.getElementsByClassName('dateOfChange');
for (var i = 0; i 0 ? shareChanges[0].date.getTime() : periodEndTimestamp;
var daysInFirstSegment = Math.min(daysInPeriod, Math.floor((firstChangeDateTimestamp – periodStartTimestamp) / (1000 * 60 * 60 * 24)) + 1);
if (daysInFirstSegment > 0) {
// Ensure the start date is actually within the period range if a specific date was entered
var effectiveStartTimestamp = Math.max(periodStartTimestamp, periodStartDate.getTime());
var effectiveDaysInFirstSegment = Math.floor((Math.min(firstChangeDateTimestamp, periodEndDate.getTime()) – effectiveStartTimestamp) / (1000 * 60 * 60 * 24)) + 1;
if (effectiveDaysInFirstSegment < 0) effectiveDaysInFirstSegment = 0; // Handle cases where change date is before period start
totalWeightedSharesAmount += sharesIssuedStart * effectiveDaysInFirstSegment;
weightedSharesData.push({
description: 'Shares at Start',
shares: sharesIssuedStart,
days: effectiveDaysInFirstSegment,
weightedAmount: sharesIssuedStart * effectiveDaysInFirstSegment,
startDate: periodStartDate,
endDate: new Date(effectiveStartTimestamp + (effectiveDaysInFirstSegment – 1) * (1000 * 60 * 60 * 24))
});
currentShares = sharesIssuedStart; // Reset for next segment calculation
}
// Subsequent segments: between changes
for (var i = 0; i < shareChanges.length; i++) {
var change = shareChanges[i];
var changeTimestamp = change.date.getTime();
var sharesAfterChange = currentShares + change.shares;
var nextChangeTimestamp = (i + 1 0) {
// Ensure the segment calculation uses dates within the overall period
var effectiveSegmentStartTimestamp = Math.max(segmentStartTimestamp, periodStartTimestamp);
var effectiveSegmentEndTimestamp = Math.min(segmentEndTimestamp, periodEndTimestamp);
var effectiveDaysInSegment = Math.floor((effectiveSegmentEndTimestamp – effectiveSegmentStartTimestamp) / (1000 * 60 * 60 * 24)) + 1;
if (effectiveDaysInSegment 0) {
var lastChangeDate = shareChanges[shareChanges.length – 1].date;
var lastChangeTimestamp = lastChangeDate.getTime();
var finalSegmentStartTimestamp = Math.max(lastChangeTimestamp, periodStartTimestamp);
var finalSegmentEndTimestamp = periodEndTimestamp;
var effectiveFinalSegmentStartTimestamp = Math.max(finalSegmentStartTimestamp, periodStartTimestamp);
var effectiveFinalSegmentEndTimestamp = Math.min(finalSegmentEndTimestamp, periodEndTimestamp);
var daysInFinalSegment = Math.floor((effectiveFinalSegmentEndTimestamp – effectiveFinalSegmentStartTimestamp) / (1000 * 60 * 60 * 24)) + 1;
if (daysInFinalSegment > 0 && lastChangeTimestamp 0 && shareChanges.length == 0) {
// If there were no changes, the first segment calculation handles it. This is a safeguard.
}
}
// Ensure total days used for weighting doesn't exceed the specified daysInPeriod
var totalDaysUsedForWeighting = 0;
weightedSharesData.forEach(function(data) {
totalDaysUsedForWeighting += data.days;
});
// If there are no changes, totalDaysUsedForWeighting will be 0 from loop. Need to fix logic.
// The first segment calculation should correctly use daysInPeriod if no changes.
// Recalculate totalWeightedSharesAmount and weightedSharesData more robustly
totalWeightedSharesAmount = 0;
weightedSharesData = [];
currentShares = sharesIssuedStart;
var lastTimestamp = periodStartTimestamp;
// Add initial shares data
weightedSharesData.push({
description: 'Shares at Start',
shares: sharesIssuedStart,
date: periodStartDate,
days: 0, // Will be calculated below
weightedAmount: 0
});
// Add changes and calculate segments
var allTimestamps = [periodStartTimestamp];
shareChanges.forEach(function(change) {
allTimestamps.push(change.date.getTime());
});
allTimestamps.push(periodEndTimestamp);
var uniqueTimestamps = […new Set(allTimestamps)].sort(function(a, b) { return a – b; });
for (var i = 0; i < uniqueTimestamps.length – 1; i++) {
var segmentStartTs = uniqueTimestamps[i];
var segmentEndTs = uniqueTimestamps[i+1];
// Ensure segment is within the overall reporting period
var effectiveSegmentStartTs = Math.max(segmentStartTs, periodStartTimestamp);
var effectiveSegmentEndTs = Math.min(segmentEndTs, periodEndTimestamp);
var daysInSegment = Math.floor((effectiveSegmentEndTs – effectiveSegmentStartTs) / (1000 * 60 * 60 * 24)) + 1;
if (daysInSegment <= 0) continue; // Skip if segment is invalid or outside period
// Determine the share count for this segment
var sharesForSegment = sharesIssuedStart;
for (var j = 0; j < shareChanges.length; j++) {
if (shareChanges[j].date.getTime() <= segmentStartTs) {
sharesForSegment += shareChanges[j].shares;
}
}
var weightedAmount = sharesForSegment * daysInSegment;
totalWeightedSharesAmount += weightedAmount;
weightedSharesData.push({
description: (i === 0) ? 'Shares at Start' : `Change ${i}`,
shares: sharesForSegment,
date: new Date(segmentStartTs),
days: daysInSegment,
weightedAmount: weightedAmount,
startDate: new Date(effectiveSegmentStartTs),
endDate: new Date(effectiveSegmentEndTs)
});
}
// Final check for the last segment if uniqueTimestamps doesn't reach periodEndTimestamp correctly
if (uniqueTimestamps[uniqueTimestamps.length – 1] 0) {
var sharesForSegment = sharesIssuedStart;
for (var j = 0; j < shareChanges.length; j++) {
if (shareChanges[j].date.getTime() <= segmentStartTs) {
sharesForSegment += shareChanges[j].shares;
}
}
var weightedAmount = sharesForSegment * daysInSegment;
totalWeightedSharesAmount += weightedAmount;
weightedSharesData.push({
description: `Final Segment`,
shares: sharesForSegment,
date: new Date(segmentStartTs),
days: daysInSegment,
weightedAmount: weightedAmount,
startDate: new Date(effectiveSegmentStartTs),
endDate: new Date(effectiveSegmentEndTs)
});
}
}
var weightedAverageShares = totalWeightedSharesAmount / daysInPeriod;
weightedAverageSharesResult.textContent = weightedAverageShares.toLocaleString(undefined, { maximumFractionDigits: 2 });
weightedSharesPeriod1.innerHTML = `Beginning Shares Weighted: ${(sharesIssuedStart * daysInPeriod).toLocaleString(undefined, { maximumFractionDigits: 0 })}`; // This line is misleading, it should be the weighted amount for the FIRST segment
totalWeightedShares.innerHTML = `Total Weighted Shares: ${totalWeightedSharesAmount.toLocaleString(undefined, { maximumFractionDigits: 0 })}`;
// Update table
summaryTableBody.innerHTML = "; // Clear existing rows
var startRowHtml = `
`;
// Correcting the table logic to reflect segments
var tableRowsHtml = ";
var cumulativeDays = 0;
var currentSharesForTable = sharesIssuedStart;
var weightedAmountSumForTable = 0;
var segmentDataForTable = [];
var lastTimestampForTable = periodStartTimestamp;
// Add initial segment
var initialSegmentDays = Math.min(daysInPeriod, Math.floor((shareChanges.length > 0 ? shareChanges[0].date.getTime() : periodEndTimestamp) – periodStartTimestamp) / (1000 * 60 * 60 * 24)) + 1;
if (initialSegmentDays > 0) {
segmentDataForTable.push({
description: 'Shares at Start',
shares: sharesIssuedStart,
days: initialSegmentDays,
weightedAmount: sharesIssuedStart * initialSegmentDays,
startDate: periodStartDate,
endDate: new Date(periodStartTimestamp + (initialSegmentDays – 1) * (1000 * 60 * 60 * 24))
});
weightedAmountSumForTable += sharesIssuedStart * initialSegmentDays;
cumulativeDays += initialSegmentDays;
currentSharesForTable = sharesIssuedStart; // This is not quite right, need to track shares *after* changes
}
// Process changes and subsequent segments
for (var i = 0; i 0) {
// Use the shares that were outstanding *before* this change
var weightedAmount = sharesBeforeChange * daysInSegment;
segmentDataForTable.push({
description: `Shares Before Change ${i + 1}`,
shares: sharesBeforeChange,
days: daysInSegment,
weightedAmount: weightedAmount,
startDate: new Date(segmentStartTs),
endDate: new Date(segmentEndTs)
});
weightedAmountSumForTable += weightedAmount;
cumulativeDays += daysInSegment;
}
// Update shares count based on the current change
currentSharesForTable += change.shares;
lastTimestampForTable = changeTimestamp; // Update for the next segment calculation
// Add the shares *after* the change, for the segment starting now
var nextSegmentStartTs = Math.max(changeTimestamp, periodStartTimestamp); // Segment starts on the change date
var nextSegmentEndTs = Math.min((i + 1 0) {
segmentDataForTable.push({
description: `Shares After Change ${i + 1}`,
shares: currentSharesForTable,
days: daysInNextSegment,
weightedAmount: currentSharesForTable * daysInNextSegment,
startDate: new Date(nextSegmentStartTs),
endDate: new Date(nextSegmentEndTs)
});
weightedAmountSumForTable += currentSharesForTable * daysInNextSegment;
cumulativeDays += daysInNextSegment;
}
}
// Handle the final segment if the last change was before the period end
if (shareChanges.length === 0 && daysInPeriod > 0) {
// If no changes, only the initial segment exists (already handled or implicitly)
// The initial segment calculation should cover this case if initialSegmentDays = daysInPeriod
} else if (shareChanges.length > 0 && lastTimestampForTable 0) {
// Use the shares count after the last change
var weightedAmount = currentSharesForTable * daysInFinalSegment;
segmentDataForTable.push({
description: `Final Segment`,
shares: currentSharesForTable,
days: daysInFinalSegment,
weightedAmount: weightedAmount,
startDate: new Date(finalSegmentStartTs),
endDate: new Date(finalSegmentEndTs)
});
weightedAmountSumForTable += weightedAmount;
cumulativeDays += daysInFinalSegment;
}
}
// Correct table generation based on accurate segments
summaryTableBody.innerHTML = "; // Clear again
var actualTotalDays = 0;
var actualTotalWeighted = 0;
var currentSharesLevel = sharesIssuedStart;
var lastEventTimestamp = periodStartTimestamp;
// Sort all events: start, changes, end
var events = [{ timestamp: periodStartTimestamp, type: 'start', shares: sharesIssuedStart }];
shareChanges.forEach(function(change) {
events.push({ timestamp: change.date.getTime(), type: 'change', shares: change.shares });
});
events.push({ timestamp: periodEndTimestamp, type: 'end', shares: 0 }); // Placeholder for end
// Process events chronologically to define segments
events.sort(function(a, b) { return a.timestamp – b.timestamp; });
var segments = [];
var currentSharesCount = sharesIssuedStart;
var lastTs = periodStartTimestamp;
for (var i = 0; i < events.length; i++) {
var event = events[i];
var eventTs = event.timestamp;
// Ensure event is within period bounds
if (eventTs periodEndTimestamp) continue;
// If there's a gap between the last event and this one, create a segment
if (eventTs > lastTs) {
var segmentStartTs = Math.max(lastTs, periodStartTimestamp);
var segmentEndTs = Math.min(eventTs, periodEndTimestamp);
var segmentDays = Math.floor((segmentEndTs – segmentStartTs) / (1000 * 60 * 60 * 24)) + 1;
if (segmentDays > 0) {
segments.push({
description: `Shares during segment ending ${new Date(segmentEndTs).toLocaleDateString()}`,
shares: currentSharesCount, // Shares count *before* this event
days: segmentDays,
weightedAmount: currentSharesCount * segmentDays,
startDate: new Date(segmentStartTs),
endDate: new Date(segmentEndTs)
});
actualTotalWeighted += currentSharesCount * segmentDays;
actualTotalDays += segmentDays;
}
}
// Update shares count based on the event type
if (event.type === 'change') {
currentSharesCount += event.shares; // Add net change
} else if (event.type === 'start') {
currentSharesCount = event.shares; // Set initial count
}
// For 'end' type, currentSharesCount remains as is for the last segment calculation
lastTs = eventTs; // Update last processed timestamp
}
// Handle the very final segment if the last event wasn't the period end
if (lastTs 0) {
segments.push({
description: `Final Segment`,
shares: currentSharesCount, // Shares count after the last change
days: segmentDays,
weightedAmount: currentSharesCount * segmentDays,
startDate: new Date(segmentStartTs),
endDate: new Date(segmentEndTs)
});
actualTotalWeighted += currentSharesCount * segmentDays;
actualTotalDays += segmentDays;
}
}
// Populate table with refined segments
segments.forEach(function(segment, index) {
var rowHtml = `