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 Active Enlisted


Here is a snapshot of the pay table for reserve officers automatically formatted in an excel application Reserve Officer


Here is the input prompt when the program is ran Input


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 Output


If an input follows appropriate formatting but doesn't choose a valid pay rate, an error note is returned Error


Conclusion

The next project in this series will be data analysis to examine system wide costs and savings.

Article: "BRS Part 1" by Wolf, in Projects

Comments


There are no comments yet.

Add a Comment

You can use the Markdown syntax to format your comment.

Comment Atom Feed

Related content