Dictionaries and the Robo-Advisor

One helpful trick with dictionaries is to use them to store data with names.

Consider the robo-advisor tool below.

def get_age():
    need_age = True
    while need_age:
        age = input('What is your age?  Enter it as a numberic argument (e.g. "50", not "fifty")\n')
        try:
            age = int(age) # this will break (raise an exception) if age is not numeric
            need_age = False
        except Exception as e:
            print('Please try entering your age again')
    return age

def get_risk_preference():
    need_preference = True
    while need_preference:
        response = input("On a scale of 1-5, how much do you dislike risk?  1=not bothered by risk, 5=extremely worried about risk.\n")
        try:
            response = int(response) # this will break if response is not 1-5
            need_preference = False
        except Exception as e:
            print('Please try entering your preference again')
    return response

def get_allocation():
    
    age = get_age()
    
    # apply rule of 100
    equity_weight = 100-int(age)
    
    # get user's risk preference
    preference = get_risk_preference()
    
    # shift the allocation according to the user's preference
    if preference == 1:
        equity_weight += 10
    elif preference == 2:
        equity_weight += 5
    elif preference == 4:
        equity_weight -= 5
    elif preference == 5:
        equity_weight -= 10
        
    # correct weights to stick within 0-100
    equity_weight = min(equity_weight, 100)
    equity_weight = max(equity_weight, 0)
    
    debt_weight = 100-equity_weight
    
    print('I would recommend', equity_weight, 'percent stocks and ', debt_weight, 'percent bonds')
    
    return [equity_weight, debt_weight]
get_allocation()
---------------------------------------------------------------------------
StdinNotImplementedError                  Traceback (most recent call last)
<ipython-input-2-19454c49e5b0> in <module>
----> 1 get_allocation()

<ipython-input-1-bbc80d1b0c91> in get_allocation()
     23 def get_allocation():
     24 
---> 25     age = get_age()
     26 
     27     # apply rule of 100

<ipython-input-1-bbc80d1b0c91> in get_age()
      2     need_age = True
      3     while need_age:
----> 4         age = input('What is your age?  Enter it as a numberic argument (e.g. "50", not "fifty")\n')
      5         try:
      6             age = int(age) # this will break (raise an exception) if age is not numeric

/mnt/software/anaconda3/lib/python3.8/site-packages/ipykernel/kernelbase.py in raw_input(self, prompt)
    855         """
    856         if not self._allow_stdin:
--> 857             raise StdinNotImplementedError(
    858                 "raw_input was called, but this frontend does not support input requests."
    859             )

StdinNotImplementedError: raw_input was called, but this frontend does not support input requests.

The block of code where where shift the equity_weight variable is a bit tedious to look at.

A more convenient way to store that information is via a dictionary like so:

def get_allocation():
    
    age = get_age()
    
    # apply rule of 100
    equity_weight = 100-int(age)
    
    # get user's risk preference
    preference = get_risk_preference()
    
    # shift the allocation according to the user's preference
    shift = {1: 10, 2: 5, 3: 0, 4: -5, 5: -10}
    equity_weight += shift[preference]
        
    # correct weights to stick within 0-100
    equity_weight = min(equity_weight, 100)
    equity_weight = max(equity_weight, 0)
    
    debt_weight = 100-equity_weight
    
    print('I would recommend', equity_weight, 'percent stocks and ', debt_weight, 'percent bonds')
    
    return [equity_weight, debt_weight]
get_allocation()
What is your age?  Enter it as a numberic argument (e.g. "50", not "fifty")
31
On a scale of 1-5, how much do you dislike risk?  1=not bothered by risk, 5=extremely worried about risk.
5
I would recommend 59 percent stocks and  41 percent bonds
[59, 41]

So, why does this work? Well, recall that we asked the user to state their risk preference. This risk preference was given as an integer between 1 and 5. So, we can think of the integers 1-5 as “names” for preferences. That is, a person who is a 1 is very risk-tolerant/risk-loving. A person who is a 5 is very risk-averse.

Each of these five types of people has a “shift” to the rule of thumb equity weight. For instance, a very risk-averse person receives a shift of -10 to their recommended equity weight.

The dictionary:

shift = {
    1: 10,
    2: 5,
    3: 0,
    4: -5,
    5: -10
}

print(shift)
{1: 10, 2: 5, 3: 0, 4: -5, 5: -10}

records the person type as the key and the corresponding shift-value as the value in the dictionary.

Any person can then be referenced by their risk preference and their corresponding shift value is returned.

shift[5]
-10
shift[3]
0

Dictionaries are frequently used in this manner. That is, a programmer specifies a dictionary with a set of key-value pairs, and then later uses the dictionary by providing a key to receive the corresponding value.

Let’s consider another example of a dictionary in action.

sectors = {
    'Materials': 'ASIX',
    'Communications': 'T',
    'Cyclical': 'FLWS',
    'Energy': 'BATL',
    'Financial': 'TROW',
    'Healthcare': 'ABBV',
    'Industries': 'MMM',
    'Technology': 'BOX',
    'Utilities': 'CPK'
}

This dictionary uses sector names as keys and stock tickers as values.

Suppose the robo-advisor asks a user what sector they are interested in learning more about. For now, we don’t have enough tools in our toolkit to provide the user with a detailed response (though we will shortly!). Instead, let’s give the robot a bit of personality.

def fave_sector():
    need_fave = True
    
    while need_fave:
        fave = input('''What is your favorite sector?\n
        \t Materials\n
        \t Communications\n
        \t Energy\n
        \t Financial\n
        \t Healthcare\n
        \t Industrials\n
        \t Technology\n
        \t Utilities\n''')
        if fave in sectors.keys():
            need_fave = False
            
    print("That's cool,", sectors[fave],"is my favorite stock")
fave_sector()
What is your favorite sector?

        	 Materials

        	 Communications

        	 Energy

        	 Financial

        	 Healthcare

        	 Industries

        	 Technology

        	 Utilities
Industries
That's cool, MMM is my favorite stock