Rights-Issue Bonus-Factor Adjustment
Install and import#
npm install fintech-algorithmsimport { rightsIssueBonusFactorAdjustment } from "fintech-algorithms/earnings-and-per-share-analytics/earnings-and-share-foundations/rights-issue-bonus-factor-adjustment";Signature#
rightsIssueBonusFactorAdjustment(input)Extracts the bonus element of a rights issue by computing the theoretical ex-rights price and the market-to-TERP adjustment factor, then restates prior-period weighted-average shares and basic EPS with it. All arithmetic runs in 50-significant-digit decimal with half-even rounding and the figures come back as exact decimal strings. A contract failure is rethrown as an Error whose message begins EPS calculation failed: .
Parameters#
| Name | Type | Notes |
|---|---|---|
input | { events: Array<{ event_id, effective_or_exercise_date, existing_shares_per_block, new_shares_per_block, cum_rights_fair_value_per_share, subscription_price_per_share, offered_to_all_existing_shareholders, event_is_effective }>, periods: Array<{ period_id, basis_date, basis_is_uniform, earnings_available_to_ordinary_shareholders, weighted_average_ordinary_shares }> } | events and periods are both required and must be non-empty arrays. Each event needs existing_shares_per_block and new_shares_per_block as positive integer strings, an effective_or_exercise_date in YYYY-MM-DD form, a cum_rights_fair_value_per_share above zero, a subscription_price_per_share from zero up to that fair value, and both offered_to_all_existing_shareholders and event_is_effective set to true. Unlike the bonus-issue topic, event ids and dates are not required to be unique or ordered. Each period needs a basis_date, basis_is_uniform set to true, decimal earnings_available_to_ordinary_shareholders and a strictly positive weighted_average_ordinary_shares. Nothing is defaulted. |
Returns#
{ topic_id, state, events, periods }
state is always calculated. events gives one row per input event with event_id, terp and the reduced factor as factor_numerator and factor_denominator. periods gives period_id, applied_event_ids, factor_numerator, factor_denominator, restated_shares and restated_basic_eps; a period picks up only the events dated strictly after its basis_date. Unlike the bonus-issue topic, no earnings or pre-restatement columns are emitted.
Errors#
- When
subscription_price_per_shareexceedscum_rights_fair_value_per_shareor is negative, or the fair value is not above zero — throws Error - When
offered_to_all_existing_shareholdersorevent_is_effectiveis nottrue, a per-block share count is not a positive integer string, a date is not a realYYYY-MM-DDvalue,weighted_average_ordinary_sharesis not positive, orbasis_is_uniformis nottrue— throws Error
Complexity: time O(e * p) for e events and p periods,
space O(e + p).
Worked example#
executed Captured by running this function on the input its own test provides. Real output of real code — but not asserted against a published figure.
Input#
{
"events": [
{
"event_id": "SYN-RIGHTS-1",
"effective_or_exercise_date": "2025-06-01",
"existing_shares_per_block": "4",
"new_shares_per_block": "1",
"cum_rights_fair_value_per_share": "12.50",
"subscription_price_per_share": "8.00",
"offered_to_all_existing_shareholders": true,
"event_is_effective": true
}
],
"periods": [
{
"period_id": "SYN-2024",
"basis_date": "2024-12-31",
"basis_is_uniform": true,
"earnings_available_to_ordinary_shareholders": "18000000",
"weighted_average_ordinary_shares": "9000000"
},
{
"period_id": "SYN-CURRENT",
"basis_date": "2025-06-01",
"basis_is_uniform": true,
"earnings_available_to_ordinary_shareholders": "9500000",
"weighted_average_ordinary_shares": "9700000"
}
]
}Call#
rightsIssueBonusFactorAdjustment(input)Returns#
object with 4 fields: topic_id, state, events, periods
{
"topic_id": "D46-F01-A07",
"state": "calculated",
"events": [
{
"event_id": "SYN-RIGHTS-1",
"terp": "11.6",
"factor_numerator": "125",
"factor_denominator": "116"
}
],
"periods": [
{
"period_id": "SYN-2024",
"applied_event_ids": ["SYN-RIGHTS-1"],
"factor_numerator": "125",
"factor_denominator": "116",
"restated_shares": "9698275.8620689655172413793103448275862068965517241",
"restated_basic_eps": "1.856"
},
{
"period_id": "SYN-CURRENT",
"applied_event_ids": [],
"factor_numerator": "1",
"factor_denominator": "1",
"restated_shares": "9700000",
"restated_basic_eps": "0.97938144329896907216494845360824742268041237113402"
}
]
}Diagrams#
Calculation flow#
Rights-issue bonus-factor flow
flowchart LR
A["Validated rights event"] --> B{"Offered to all existing shareholders?"}
B -- "No" --> X["Reject from canonical method"]
B -- "Yes" --> C{"Non-time contingency resolved?"}
C -- "No" --> Y["Wait; do not adjust"]
C -- "Yes / none" --> D["Validate price date, source, currency, and scale"]
D --> E["TERP = (n × M + r × S) ÷ (n + r)"]
E --> F{"Subscription price S < fair value M?"}
F -- "No" --> G["No bonus element; factor = 1"]
F -- "Yes" --> H["Bonus factor = M ÷ TERP"]
H --> I["Apply only to eligible pre-rights basis"]
G --> I
I --> J["Preserve earnings and recalculate historical EPS"]
A --> K["Actual new shares"]
K --> L["Time-weight from issue or exercise date"]
How it works#
This page states the contract — how to call it correctly. The article explains the concept: why it works, and where it breaks.
References#
- IAS 33 Earnings per Share
- Statement No. 128, Earnings per Share
- Filed rights-issue restatement example
- SEC staff comment on factor direction
- Research limits