diff --git a/assignment8.py b/assignment8.py new file mode 100644 index 0000000..28e7f73 --- /dev/null +++ b/assignment8.py @@ -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() \ No newline at end of file diff --git a/investment.py b/investment.py new file mode 100644 index 0000000..a7f1914 --- /dev/null +++ b/investment.py @@ -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() + \ No newline at end of file diff --git a/outputs.py b/outputs.py new file mode 100644 index 0000000..064fc22 --- /dev/null +++ b/outputs.py @@ -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') diff --git a/position_outcomes.py b/position_outcomes.py new file mode 100644 index 0000000..3c26091 --- /dev/null +++ b/position_outcomes.py @@ -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) \ No newline at end of file diff --git a/tests.py b/tests.py new file mode 100644 index 0000000..3f1dc17 --- /dev/null +++ b/tests.py @@ -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() \ No newline at end of file