Project 2
MTH5005: Programming in Python II
1 Overview
For this project, you will extend the functionality of your PriceTracker class to track additional statistics, and also implement a new class MarketTracker that tracks several prices at once.
Due Date and Submission
The assignment is due on 25 April 2025 at 23:59. To submit the assignment, you must:
1. Commit and push your final project code in your repository username-project-2 (where username is your username) to QMUL’s GitHub Server at https://github. qmul. ac. uk. The procedure for this is exactly the same as what we have been doing in lab sessions, and you should use the same repository we have been using in Labs 6, 7, 8, and 9.
2. Go to the module’s QMPlus page and visit the submission portal for the assignment. You do not need to upload anything here, but you will need to confirm that your project has been pushed and you now want it marked.
Only code submissions via your git repository on github.qmul.ac.uk will be accepted. It is not possible to upload your code via QMPlus and email submissions will NOT be accepted.
Late submissions will be handled according to the School’s Late Submission Policy:
For every period of 24 hours, or part thereof, that an assignment is overdue there shall be a deduction of five per cent of the total marks available (i.e. five marks for an assessment marked out of 100). After seven calendar days (168 hours or more late) the mark shall be reduced to zero, and recorded as 0FL (zero, fail, late).
https://qmplus.qmul.ac.uk/mod/book/view.php?id=2699291&chapterid=236293
Warning
• Your code should be properly formatted and commented. Poorly formatted code will receive deductions.
• Your code should not have any syntax errors. If you program cannot be run due to a syntax error, you will receive 0 marks for the relevant part of the submission. Your code will be tested against Python 3.11 and you can check that it runs correctly by running one of the code testers on our GitHub site.
• Correct code should still pass the relevant tests from labs 6, 7, 8, and 9 even after completing Task 1 and 2. You should ensure that the final version of your code passes the relevant lab tests. Here, “relevant tests” means all tests from each of labs 6, 8, and 9 and the tests for range_query in lab 7.
• It is better to submit an incomplete or incorrect solution that correctly runs than a hastily finished solution that Python cannot load!
• It is fine to collaborate during labs and discuss general solutions to problems, but you should write your own code and documentation. Submissions that are liter- ally identical to one another or to a common third source may result in academic misconduct charges!
Files to submit
Your submission should include the following files and functionality, implemented over the last several labs:
TreeNode . py
|
This should contain your TreeNode class from Lab 6, which defines a type for nodes in your MinHeap class.
|
BST. py
|
This should contain a function range_query that can be used to query a range for any given instance of BST
|
Heap. py
|
This should contain the implementation of the MinHeap class from Lab 8, which is used by your price tracker.
|
PriceTracker. py
|
This should contain the PriceTracker class from Lab 8, together with the specified additions discussed in the next sections.
|
MarketTracker. py
|
This should contain a new class MarketTracker described in the fol- lowing sections.
|
Your code will likely depend on other files that you have been provided, including AVLTree . py and Node . py. You can include these (and any other Python files) in your repository, but these will not be marked. We will be testing your code using the versions of these files that you were provided, so you must ensure your code works without any modifications to files other than those in the above table!
Marks Breakdown
Your code will be tested using a similar framework to that you have been using to check your code in the labs, but we will be running additional checks for correctness. There are 100 marks available for this assignment, broken down as follows:
10 marks
|
All required functions, methods, and classes are present and correctly documented with docstrings.
|
10 marks
|
At least 5 commits made to your repository—one after completing each of Labs 6, 7, 8, and 9 and one after completing the instructions here. All should have informative messages to identify them.
|
50 marks
|
Correctness tests for the classes TreeNode, Heap, and PriceTracker developed in labs 6, 8, and 9 and the function range_query from Lab 7.
|
15 marks
|
Correctness tests for the additional statistics you will implement in PriceTracker as part of Task 1
|
15 marks
|
Correctness tests for the additional class MarketTracker you will im- plement as part of Task 2
|
2 Task 1: Tracking additional data
For the first additional task, you should modify your PriceTracker class so that it also main- tains a record of the 10-day maximum and 10-day average price of an asset. Two notes:
• You should be able to do the first by maintaining a second heap in your class along with the existing min-heap. You should not implement a new class for max-heaps. Instead, you should find a way to use a min-heap as a max-heap.
Hint: Think about what you might do with numerical keys k to ensure that the element with largest value of k was at the top of a min-heap.
• In order to maintain the average, it should be sufficient to keep track of only the current average over the most recent 10-day window, computed as the sum of all prices in the window divided by the number of prices in the window. You should not need a heap or anything fancy for this. You should think of a way to update this average without com- pletely recalculating it from scratch each time a price arrives.
Hint: it may be useful to maintain an extra attribute in your PriceTracker class that keeps track of the number of prices in the current window.
Your AVLTree should now store tuples of the form.
1 ( price : float ’
2 ten_ day _min : float ’
3 ten_ day _max : float ’
4 ten_ day _avg : float )
|
Note that is important that the first 2 elements of each tuple remain the same as in Lab 9! This will allow us to test your code from Lab 9 regardless of whether you have completed this task or not.
3 Task 2: Tracking multiple prices
The PriceTracker class allows us to track data for a single asset. For this task, you must im- plement the tracking of multiple assets in a market. Declare a new class MarketTracker in the file MarketTracker. py. Your class should maintain a price tracker for each separate asset, and should have the following methods:
• add_price(self’ name: str ’ time: datetime’ price: float) that takes a name for an asset, a time, and a price. For example:
1 add _price ( " NVDA " ’ datetime (2025 ’ 3 ’ 31 ’ 15 ’ 5) ’ 110 . 40)
|
represents a data point saying that Nvidia stock was worth 110.40 at 15:05:00 on 31 March 2025. Your method should update the price tracker for the asset with the given name. For example, the above call should add the specified time and price to the tracker “NVDA”.
• get_price_data(self’ name: str ’ start: datetime’ end: datetime) —this should function exactly as the method for your PriceTracker class, except that it takes an extra parameter name of type str representing the name of the asset whose data in the given range should be returned. For example, if mt is a MarketTracker instance, then calling:
1 mt . get _price_ data ( " NVDA " ’
2 datetime (2025 ’ 3 ’ 1) ’
3 datetime (2025 ’ 4 ’ 1) )
|
should return an ordered list of tuples containing all the data that was recorded for the as- set named “NVDA” between 1 March 2025 and 1 April 2025. Each tuple you return should have the form.
1 ( time : datetime ’ ( price : float ’
2 ten_ day _min : float ’
3 ten_ day _max : float ’
4 ten_ day _avg : float ) )
|
That is, each should be a pair whose first element is a time and whose second element is a tuple containing all price data for this time. If an asset symbol is not found, your method should raise a KeyError.
In order to keep things relatively simple, when processing a new price with your add_price method, you should only update the data point for the specified asset. This means that not all assets will have the same number or frequency of data points. It maybe helpful to think of your class as maintaining a list of statistics related to the times at which an asset’s price was updated.