Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions assignment8.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
'''
Created on Nov 24, 2016
@author: danielamaranto
This program accepts a list of integers from a user and assumes the user enters the list with surrounding brackets,
as indicated in the instructions. For any set of integers, it will create an array of individual trials of
daily return on investment for each position entered by the user. It will generate 1 text file of the mean and
standard deviation of each position, and it will generate a separate histogram for each position.

I am the sole author of this program, but I have included my references where applicable.
'''

#Import functions and a class from separate modules
import outputs
from investment import investment_position

def main():
complete = False
while complete is False:
# Get input from user: 1 list of positions and the number of trials
position_input = input('Enter a list of investments:').replace(' ','')[1:-1] #Surrounding brackets deleted
trials_input = input('Enter a number of trials:').replace(' ','')

try:
investments = [int(i) for i in position_input.split(sep=',')]
num_trials = int(trials_input)
files = 1
with open('results.txt', 'w') as file: #If user is re-running, this will wipe the
file.write('') #text file clean
print('Generating output...')
for i in investments:
files = files + 1 #A histogram is generated for each position and a text
position = investment_position(i,num_trials) #file is generated for all positions collectively.
outputs.generate_statistics(position)
outputs.generate_histogram(position)
print(str(files) + ' files generated.')
complete = True

# All invalid entries are handled here, including floats, alphabetical entries, etc.
except ValueError:
print('Invalid input\n')
except IndexError:
print('Invalid input\n')
except UnboundLocalError:
print('Invalid input\n')
except TypeError:
print('Invalid input\n')
except KeyboardInterrupt:
print('Invalid input\n')


if __name__ == '__main__':
main()
31 changes: 31 additions & 0 deletions investment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'''
Created on Nov 24, 2016
I created a class that would perform all of the required calculation for each
position determined by the user. Functions referenced by the class's attributes
are located in the position_outcomes module.
@author: danielamaranto
'''

import numpy as np
from position_outcomes import cumu_ret

class investment_position:
def __init__(self, shares, trials):
self.position = shares
self.position_value = 1000/shares
self.num_trials = trials

def all_trials_result(self):
trial_array = np.array([cumu_ret(self.position) for i in range(self.num_trials)])
return trial_array

def daily_ret(self):
normalized_result = np.array([i/1000-1 for i in self.all_trials_result()])
return normalized_result

def mean(self):
return self.daily_ret().mean()

def stdev(self):
return self.daily_ret().std()

31 changes: 31 additions & 0 deletions outputs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'''
Created on Nov 24, 2016

@author: danielamaranto
'''
from investment import investment_position
import matplotlib.pyplot as plt

def generate_statistics(investment):
'''I referred to python documentation to write to the text file.
https://docs.python.org/3/tutorial/inputoutput.html'''
with open('results.txt', 'a') as file:
data = 'Number of shares: ' + str(investment.position) + \
'\nValue of each share: $' + str(investment.position_value) + \
'\nMean: ' + str(investment.mean()) + \
'\nStandard Deviation: ' + str(investment.stdev()) + '\n\n'
file.write(data)

def generate_histogram(investment):
'''I referred to python documentation to properly format the histogram filenames (zfill)
and to generate individual plots (savefig).
https://docs.python.org/2/library/string.html
http://matplotlib.org/api/pyplot_api.html'''
plt.hist(investment.daily_ret(),100, range=[-1,1])
plt.xlabel('Daily Return')
plt.ylabel('Number of Trials')
plt.title('Histogram of investment trials')
plt.grid(True)
name = str(investment.position).zfill(4)
plt.savefig('histogram_'+ name +'_pos.pdf', format='pdf')
plt.close('all')
21 changes: 21 additions & 0 deletions position_outcomes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
'''
Created on Nov 27, 2016
These functions assist the investment_portfolio class with generation of the daily investment outcome.
@author: danielamaranto
'''
import numpy as np
import random

#Determines the outcome of a single share
def share_result():
result = random.uniform(0,1)
if result <= 0.49:
win = False
else:
win = True
return win

#Determines the outcome of one day of trading
def cumu_ret(shares):
wins = np.array([share_result() for i in range(shares)])
return 2 * (1000/shares) * np.sum(wins)
31 changes: 31 additions & 0 deletions tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'''
Created on Nov 27, 2016

@author: danielamaranto
'''
import unittest
import numpy as np
from position_outcomes import *

'''Given that all my functions rely on randomly generated data, my tests either
confirm whether or not the functions work based on probabilities with large numbers
of trials or they confirm that functions output the correct format of data.
I found the assertAlmostEqual method from the python documentation website.
https://docs.python.org/2/library/unittest.html
'''

class Test(unittest.TestCase):

def testShareResult(self):
result = [share_result() for i in list(range(10000))]
proportion_true = sum(result)/10000
self.assertAlmostEqual(proportion_true, 0.51, 2)

def testCumulative(self):
result = np.array([cumu_ret(1) for i in list(range(100000))])
outcome = result.mean()
self.assertAlmostEqual(outcome, 1020, -2) #Expected value of 1 share is .51 * 2000, or 1020


if __name__ == "__main__":
unittest.main()