Blended Retirement System costs, financial analysis of the US Military's new retirement system effective 2018
This is a multi-stage analysis of the new retirement system for all military personel going into effect January 1, 2018. Part one is a programming project in Python adding a calculator to the Department of Defense's website at militarypay.defense.gov
Under the previous system retirement was only awarded after 20 years of service, either active duty years or a combination including reserve 'good years'. A good year defined as meeting sufficient reserve service requirements.
The new system will be a combination of pension, bonus and investment fund matching. Since only 17% of service members stay to retire after 20 years, this new system will affect and potentially benefit the majority of service members.
Calculator
The calculator takes in multiple pay tables saved as csv files, one of the simplest data storage formats. These tables therefore take up minimal space and can be read and wrote to by any system.
The advantage of this calculator is it allows the user to retrieve reserve or active duty pay rates. User input determines which pay table is relevant and which particular pay on the chart to return.
Code
The program to do this is written in Python and the code is as follows with corresponding commenting.
"""Calculate 2017 US military service base pay. By Wolf"""
import sys
import math
import pandas as pd
def find_pay(rank, years, active, enlisted):
"""Returns cell value given rank, years, duty status, enlisted status"""
if active == 1:
if enlisted == 1:
ae_read = pd.read_csv('E_2017pay.csv')
ae1 = pd.DataFrame(ae_read)
a_e = ae1.set_index('Years')
pay = a_e.loc[years, rank]
return pay
elif enlisted == 0:
ao_read = pd.read_csv('O_2017pay.csv')
ao1 = pd.DataFrame(ao_read)
a_o = ao1.set_index('Years')
pay = a_o.loc[years, rank]
return pay
elif active == 0:
if enlisted == 1:
re_read = pd.read_csv('RE_2017pay.csv')
re1 = pd.DataFrame(re_read)
r_e = re1.set_index('Years')
pay = r_e.loc[years, rank]
return pay
elif enlisted == 0:
ro_read = pd.read_csv('RO_2017pay.csv')
ro1 = pd.DataFrame(ro_read)
r_o = ro1.set_index('Years')
pay = r_o.loc[years, rank]
return pay
def determine_years(service):
"""Takes years of service, choose experience range assigns to years"""
if 0 <= service < 2:
years = 'Under 2'
elif 2 <= service < 3:
years = 'Over 2'
elif 3 <= service < 4:
years = 'Over 3'
elif 4 <= service < 6:
years = 'Over 4'
elif 6 <= service < 8:
years = 'Over 6'
elif 8 <= service < 10:
years = 'Over 8'
elif 10 <= service < 12:
years = 'Over 10'
elif 12 <= service < 14:
years = 'Over 12'
elif 14 <= service < 16:
years = 'Over 14'
elif 16 <= service < 18:
years = 'Over 16'
elif 18 <= service < 20:
years = 'Over 18'
elif 20 <= service < 22:
years = 'Over 20'
elif 22 <= service < 24:
years = 'Over 22'
elif 24 <= service < 26:
years = 'Over 24'
elif 26 <= service < 30:
years = 'Over 26'
elif 30 <= service < 34:
years = 'Over 30'
elif 34 <= service < 38:
years = 'Over 34'
elif 38 <= service <= 40:
years = 'Over 38'
elif service < 0 and service > 40:
print "Service years was entered incorrectly. Must be >0 and <40."
return years
def calc_pay():
"""Opens Calculator prompt"""
separator = ' ' #separator of input values is space
print "Please enter rank followed by years in service."
print "Format is 'E-1' space #, ex: O-5 20 or 'E-3 6'"
user_input = raw_input(": ").split(separator) #reads in rank and service years
rank = user_input[0]
service = user_input[1]
active_input = raw_input("Active duty, Y? Reserve is N.: ").lower() #reads active duty or not
if active_input in ("yes", "y"): #Assigns rest of program's active/reserve references
active = 1
act_out = 'n active duty '
elif active_input in ("no", "n"):
active = 0
act_out = ' reserve '
else: sys.exit("Please try again with Y or N for active duty answer.")
enlist = str(user_input[0]) #This body determines whether user's rank is enlisted or officer
if ord(enlist[0]) == ord('E'):
enlisted = 1
else: enlisted = 0
rank = str(rank) #Prepares user inputs for function calls with correct data types
service = int(service)
years = determine_years(service) #Takes user's service years and assigns experience pay range
pay = find_pay(rank, years, active, enlisted) #Looks up correct chart and cell value for rank, years in, active or reserve, and enlisted or officer
if math.isnan(pay): #Prints a summary statement if there exists a base pay for user input, or an error message
print "There doesn't exist a base pay for that rank with those years of service"
else: print "The 2017 base pay for a"+act_out+rank+" with "+str(service)+" years of service is: ", '${:,.2f}'.format(pay)
if __name__ == "__main__":
calc_pay()
Screenshots
Here is a snapshot of the pay table for active duty enlisted soldiers represented in raw CSV
Here is a snapshot of the pay table for reserve officers automatically formatted in an excel application
Here is the input prompt when the program is ran
Following the first input there is a secondary input, after both are entered the ouput lists the pay rate for the selected rank, years of experience and active or reserve duty selection
If an input follows appropriate formatting but doesn't choose a valid pay rate, an error note is returned
Conclusion
The next project in this series will be data analysis to examine system wide costs and savings.
Comments
There are no comments yet.