In [44]:
exchanges = {"A": ["AAPL", "BAC", "STW"],
"B": ["BAC", "TSLA"]}
indices = {"A": ["AAPL", "BAC", "STW", "MSFT"],
"B": ["BAC", "TSLA"],
"C": ["AAPL", "BAC"],
"D": ["AAPL", "BAC", "STW"]}
In [92]:
indexStocks = {} # dict that maps index to set of stocks in that index
for i in indices:
indexStocks[i] = set()
for stock in indices[i]:
indexStocks[i].add(stock)
def computableIndices(stocks):
# input: dictionary mapping stock name to 0 < number of occurrences, output set of computable indices given input exchanges
# run time = O( (selected exchanges) * (stocks/exchange) + indices * (stocks/index) )
out = set()
for index in indices:
status = True
for stock in indexStocks[index]:
if stock not in stocks:
status = False
break
if status:
out.add(index)
return out
class Allocation:
def __init__(self, exch_names):
self.exch_names = exch_names
self.stocks = {} # dict that maps stock name to number of occurrences in exchanges if stock was selected. Unselected stocks are not keys
for name in self.exch_names:
for stock in exchanges[name]:
if stock in self.stocks:
self.stocks[stock] += 1
else:
self.stocks[stock] = 1
self.computableIndices = computableIndices(self.stocks) # set of computable indices
self.missingStocks = {} # dict that maps index to number of stocks in that index that are not in the selected exchanges.
for i in indices:
self.missingStocks[i] = 0
for stock in indexStocks[i]:
if stock not in self.stocks: # unselected stock
self.missingStocks[i] += 1
print(f"included stocks = {self.stocks}")
print(f"missingStocks = {self.missingStocks}")
def score(self):
# must return number of indices computable with this allocation
return len(self.computableIndices)
def swap(self, ename_out, ename_in):
# must change the allocation to remove ename_out and add ename_in.
# we will run swap and then score in a loop 1e(4+) times so speed is a concern
print(f"computable indices before swap = {self.computableIndices}. ")
added = set(exchanges[ename_in]) # set of stocks added by the swap
removed = set() # set of stocks that were removed after the swap
for stock in exchanges[ename_out]:
if stock not in added:
if self.stocks[stock] == 1:
del self.stocks[stock]
removed.add(stock)
else:
self.stocks[stock] -= 1
else:
added.remove(stock)
print(f"added stocks = {added}")
print(f"removed stocks = {removed}")
for stock in added:
self.stocks[stock] = 1
for i in indices:
if i not in self.computableIndices:
if stock in indexStocks[i]:
self.missingStocks[i] -= 1
if self.missingStocks[i] == 0:
self.computableIndices.add(i)
for stock in removed:
for i in self.computableIndices.copy():
if stock in indexStocks[i]:
self.missingStocks[i] += 1
self.computableIndices.remove(i)
print(f"computable indices after swap = {self.computableIndices}. ")
In [93]:
a = Allocation(["B"])
a.score() #1
included stocks = {'BAC': 1, 'TSLA': 1}
missingStocks = {'A': 3, 'B': 0, 'C': 1, 'D': 2}
Out[93]:
1
In [94]:
a.swap("B", "A")
a.score() #1
computable indices before swap = {'B'}.
added stocks = {'STW', 'AAPL'}
removed stocks = {'TSLA'}
computable indices after swap = {'D', 'C'}.
Out[94]:
2
In [95]:
computableIndices(exchanges["A"])
Out[95]:
{'C', 'D'}
In [ ]: