Equity income metrics: dividend yield, payout ratio, dividend-discount
(Gordon growth) fair value, and yield-on-cost. Straightforward ratios with guards against division by zero.
A Soma program from the finance part of the verified corpus: 49 lines, cells DividendMetrics, DividendTests. It passes soma check with soma 3.2.4.
How it is built
The cell DividendMetrics declares 4 signals in its face: yield_pct(annual_div: Float, price: Float) -> Float, payout_ratio(annual_div: Float, eps: Float) -> Float, gordon_value(next_div: Float, discount: Float, growth: Float) -> Float and yield_on_cost(annual_div: Float, cost_basis: Float) -> Float. Handlers: yield_pct (line 13), payout_ratio (line 18), gordon_value (line 24) and yield_on_cost (line 29).
The file also holds 1 test cell (DividendTests) with 5 assertions, run by soma test.
The source
dividend_yield.cell
// Equity income metrics: dividend yield, payout ratio, dividend-discount
// (Gordon growth) fair value, and yield-on-cost. Straightforward ratios
// with guards against division by zero.
cell DividendMetrics {
face {
signal yield_pct(annual_div: Float, price: Float) -> Float
signal payout_ratio(annual_div: Float, eps: Float) -> Float
signal gordon_value(next_div: Float, discount: Float, growth: Float) -> Float
signal yield_on_cost(annual_div: Float, cost_basis: Float) -> Float
}
on yield_pct(annual_div: Float, price: Float) {
if price == 0.0 { return 0.0 }
return annual_div / price * 100.0
}
on payout_ratio(annual_div: Float, eps: Float) {
if eps == 0.0 { return 0.0 }
return annual_div / eps
}
// Gordon growth: V = D1 / (k - g), valid only when k > g
on gordon_value(next_div: Float, discount: Float, growth: Float) {
if discount <= growth { return 0.0 }
return next_div / (discount - growth)
}
on yield_on_cost(annual_div: Float, cost_basis: Float) {
if cost_basis == 0.0 { return 0.0 }
return annual_div / cost_basis * 100.0
}
}
cell test DividendTests {
rules {
// $2 div on a $50 stock = 4%
assert abs(yield_pct(2.0, 50.0) - 4.0) < 0.0001
// $2 div on $5 EPS = 40% payout
assert abs(payout_ratio(2.0, 5.0) - 0.40) < 0.0001
// Gordon: D1=2, k=8%, g=3% → 2/0.05 = 40
assert abs(gordon_value(2.0, 0.08, 0.03) - 40.0) < 0.0001
// degenerate Gordon (k <= g) guarded to 0
assert abs(gordon_value(2.0, 0.03, 0.08)) < 0.0001
// yield on cost beats current yield when bought cheaper
assert yield_on_cost(2.0, 25.0) > yield_pct(2.0, 50.0)
}
}What the toolchain says
$ soma check dividend_yield.cell
✓ All checks passed.$ soma test dividend_yield.cell
test DividendTests ...
✓ assert abs(yield_pct(2.0, 50.0) - 4.0) < 0.0001
✓ assert abs(payout_ratio(2.0, 5.0) - 0.40) < 0.0001
✓ assert abs(gordon_value(2.0, 0.08, 0.03) - 40.0) < 0.0001
✓ assert abs(gordon_value(2.0, 0.03, 0.08)) < 0.0001
✓ assert yield_on_cost(2.0, 25.0) > yield_pct(2.0, 50.0)
5 tests: 5 passed, 0 failed$ soma verify dividend_yield.cell
Verifying dividend_yield.cell...
No state machine in this program: nothing to prove beyond `soma check` (invariants and lifecycles are what verify proves).
VERIFY OK (vacuous — no state machine)