class FortuneTeller::Utils::SocialSecurity
Calculates adjusted benefit from PIA Based on www.ssa.gov/oact/quickcalc/early_late.html 11/16/2017
Constants
- AWI_1951_START
- COLA_1975_START
- DELAY_RATES
- TRANSITION_YEARS
Attributes
pia[RW]
Public Class Methods
new(dob:, start_month:)
click to toggle source
# File lib/fortuneteller/utils/social_security.rb, line 9 def initialize(dob:, start_month:) @dob = dob @adjusted_dob = (dob.day == 1 ? dob.yesterday : dob) @start_month = start_month.at_beginning_of_month end
Private Class Methods
awi_projector()
click to toggle source
# File lib/fortuneteller/utils/social_security.rb, line 225 def self.awi_projector projected = [] projected_increases = { # From https://www.ssa.gov/oact/TR/TRassum.html 2017 => 3.9, 2018 => 4.8, 2019 => 4.5, 2020 => 4.3, 2021 => 4.2, 2022 => 3.9, 2023 => 3.7, 2024 => 3.8, 2025 => 3.8, 2026 => 3.8 } last_awi = AWI_1951_START[2016-1951] (2017..2070).each do |year| increase = projected_increases[[2026, year].min] last_awi = (last_awi*((100+increase)/100.0)).floor projected << last_awi end projected end
Public Instance Methods
calculate_benefit()
click to toggle source
# File lib/fortuneteller/utils/social_security.rb, line 64 def calculate_benefit frm = full_retirement_month puts "FRM: #{frm}" return @pia if @start_month == frm if(@start_month < frm) min_rm = min_retirement_month raise bounds_error(start: @start_month, min: min_rm) if @start_month < min_rm early_benefit( months: month_diff(@start_month, frm) ) else max_rm = max_retirement_month raise bounds_error(start: @start_month, max: max_rm) if @start_month > max_rm late_benefit( months: month_diff(frm, @start_month) ) end end
estimate_pia(current_salary:, annual_raise:)
click to toggle source
# File lib/fortuneteller/utils/social_security.rb, line 15 def estimate_pia(current_salary:, annual_raise:) year = Date.today.year last_year = @start_month.year salary_history = {year => current_salary} ((@dob.year+18)..(year-1)).reverse_each do |y| salary_history[y] = (salary_history[y+1]/annual_raise).floor end if(last_year > year) ((year+1)..last_year).each do |y| salary_history[y] = (salary_history[y-1]*annual_raise).floor end end salaries = salary_history.map{|y, s| s*indexing_factors[y]} aime = (salaries.sort.last(35).reduce(:+)/(35.0*12)).floor puts "AIME #{aime}" if aime > bend_points[1] pia_62 = (0.9*bend_points[0]+0.32*(bend_points[1]-bend_points[0])+0.15*(aime-bend_points[1])).floor elsif aime > bend_points[0] pia_62 = (0.9*bend_points[0]+0.32*(aime-bend_points[0])).floor else pia_62 = (0.9*aime).floor end pia_adjusted = pia_62 ((@dob.year+63)..@start_month.year).each do |y| pia_adjusted = (pia_adjusted*(100+COLA_1975_START[y-1-1975])/100.0).floor end @pia = pia_adjusted end
fra_pia=(fra_pia)
click to toggle source
# File lib/fortuneteller/utils/social_security.rb, line 47 def fra_pia=(fra_pia) pia_adjusted = fra_pia if @start_month.year < full_retirement_month.year (@start_month.year..(full_retirement_month.year-1)).each do |y| pia_adjusted = (pia_adjusted/((100+COLA_1975_START[y-1975])/100.0)).floor end elsif @start_month.year > full_retirement_month.year puts "START GREATER" ((full_retirement_month.year+1)..@start_month.year).each do |y| puts "START: #{@start_month.year}, YEAR: #{y}" puts "PIA ADJ = #{pia_adjusted}" pia_adjusted = (pia_adjusted*(100+COLA_1975_START[y-1-1975])/100.0).floor end end @pia = pia_adjusted end
Private Instance Methods
bend_points()
click to toggle source
# File lib/fortuneteller/utils/social_security.rb, line 134 def bend_points return @bend_points unless @bend_points.nil? age_62_year = @dob.year+62 age_62_index = AWI_1951_START[(age_62_year-1951)] year_1979_index = AWI_1951_START[(1979-1951)] year_1979_bends = [18000, 108500] @bend_points = [ (year_1979_bends[0].to_f*(age_62_index/year_1979_index)).floor, (year_1979_bends[1].to_f*(age_62_index/year_1979_index)).floor, ] end
bounds_error(start:, min: nil, max: nil)
click to toggle source
# File lib/fortuneteller/utils/social_security.rb, line 221 def bounds_error(start:, min: nil, max: nil) self.class::StartDateBounds.new(start: start, min: min, max: max) end
early_benefit(months:)
click to toggle source
# File lib/fortuneteller/utils/social_security.rb, line 193 def early_benefit(months:) if months <= 36 multiplier = 100.0 - ((5.0 * months) / 9.0) else multiplier = 100.0 - 20.0 - ((5.0 * months) / 12.0) end puts "EARLY PIA: #{(pia*multiplier/100.0).floor}" (@pia*multiplier/100.0).floor end
full_retirement_month()
click to toggle source
# File lib/fortuneteller/utils/social_security.rb, line 164 def full_retirement_month return @frm unless @frm.nil? year = @adjusted_dob.year frm = @adjusted_dob.at_beginning_of_month if year <= 1938 @frm = frm.years_since(65) elsif (year >= 1943 and year <= 1954) @frm = frm.years_since(66) elsif year >= 1960 @frm = frm.years_since(67) else t = TRANSITION_YEARS[year][0] @frm = frm.years_since(t[0]).years_since(t[1]) end end
indexing_factors()
click to toggle source
# File lib/fortuneteller/utils/social_security.rb, line 147 def indexing_factors return @indexing_factors unless @indexing_factors.nil? age_60_year = @dob.year+60 age_60_index = AWI_1951_START[(age_60_year-1951)] @indexing_factors = {} (18..60).each do |age| year = @dob.year+age @indexing_factors[year] = age_60_index.to_f/AWI_1951_START[(year-1951)] end (61..70).each do |age| year = @dob.year+age @indexing_factors[year] = 1.0 end @indexing_factors end
late_benefit(months:)
click to toggle source
# File lib/fortuneteller/utils/social_security.rb, line 203 def late_benefit(months:) year = @adjusted_dob.year if year <= 1924 monthly = 6/24.0 elsif year <= 1942 monthly = DELAY_RATES[year] else monthly = 16.0/24.0 end multiplier = 100.0 + (monthly*months) puts "LATE PIA: #{(pia*multiplier/100.0).floor}" (@pia*multiplier/100.0).floor end
max_retirement_month()
click to toggle source
# File lib/fortuneteller/utils/social_security.rb, line 181 def max_retirement_month @adjusted_dob.at_beginning_of_month.years_since(70) end
min_retirement_month()
click to toggle source
# File lib/fortuneteller/utils/social_security.rb, line 185 def min_retirement_month if @adjusted_dob.day == 1 @adjusted_dob.years_since(62) else @adjusted_dob.at_beginning_of_month.years_since(62).months_since(1) end end
month_diff(a, b)
click to toggle source
# File lib/fortuneteller/utils/social_security.rb, line 217 def month_diff(a, b) (b.year * 12 + b.month) - (a.year * 12 + a.month) end