# 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