This is the fourth homework assignment. Your goal in this assignment is to write a function that performs a calculation on sequence data and returns a value.
Your solution to this homework will also be marked on code quality. This means that some part of the marks will be given for good code organisation, variable/function naming, and commenting. The marks for code quality are distinct from those for functionality; to gain full marks, your submission must be both functionally correct and readable.
Practical information#
The assignment is due Saturday the 29th of April at 11.55pm (5 min before midnight, Canberra time). This is Saturday in Semester week 8, that is, the second week after the teaching break. To submit your solution, you will upload a single Python file via Wattle. Here is the assignment submission link
The homework is individual. You must write your own solution, and you are expected to be able to explain every aspect of it.
As usual, you should have followed recent weeks’ lectures and worked through the exercises in [lab 4], [lab 5], and [lab 6], before starting on the assignment. The assignment should not take more than one or two hours to complete.
Disclaimer#
The exercise below describes a stock trading strategy, which is totally fictitious and should not be used for actual trading.
The problem#
In this homework, you will have to implement a simple trading strategy for buying and selling shares (one particular stock, not a portfolio) for an investor on a Stock Exchange. The stock is given as a sequence of numbers, each representing the price of one share at time i given by the sequence element index. The sequence is provided in full, but we shall treat it as a time series of values where at time i the only known sequence elements are those up to and including i — we cannot see into the future.
A stock trader, who can be a real person or a computer program (a bot) buys and sells shares of a stock using the available cash (“capital”). This can be very sophisticated activity, but we consider a simplified version of it. The rules which our stock trader follows are:
- At the beginning, the trader has a starting capital
capital
, which is used to buy shares; the trader owns no shares before the trading starts. - The shares can be bought or sold in integer quantities, each share costing the
value of
stock_price[i]
at the time i of transaction. - When the trader buys stock at time i they use a fixed fraction
(1-p)
of the available capital (p is a short for prudence), and purchases the maximum number of shares with the total cost not exceeding that fraction. After the purchase, the amount of available capital is reduced by the total cost of shares bought. This rule indicates that a situation when the available capital is insufficient to buy even a single share is possible. - When the trader sells the stock at time i, they sell the fraction
(1-p)
of shares owned (more accurately, the integer part of those). After the sale, the amount of available capital is increased by the total value of shares sold (and the number of owned shares decreases by the number of shares sold). - The trader decides whether to buy or to sell shares at the time i based on the comparison of current stock price and the price which the stock had at the previous time i-1. In other words, if the price increases, the trader sells a number of owned shares, or if the price decreases, the trader buys a number of shares determined by the above rules.
- Finally, at most only one transaction happens at each time i (a transaction
may not happen if the stock price doesn’t change, or the available capital is
insufficient). When the
stock_price
sequence ends, the trader stops their operations, and calculates the result — gain or loss in the value of the entire assets. In other words, the trader subtracts the value of starting capital from the value of available capital and the value of owned shares which are priced at the last value instock_price
.
Your task in this homework is to write a function stock_trade(stock_price, capital, p)
which takes these arguments:
stock_price
— a sequence of positive numbers,capital
— a positive number andp
— a float in the range0..1
,
and returns the profit or loss at the end of trading as a float value (if no trading
was done — for whatever reason — the return value must be 0.0
).
Assumptions and restrictions:
- The function must return a float.
- At the beginning, the “time” i=0, the trader buys the number
of shares determined by the described rules involving the initial
capital, the prudence coefficient
p
and the current stock price. - If the prudence fraction of capital is too low (less that the price of one share), the buyer cannot purchase any shares, and must wait until (if) the price drops low enough.
Template file and hints
As a starting point, we provide you with a skeleton code file: stock_trading.py. Download this file and write in it your implementation of the function.
The template file contains import math
statement — you may use functions from this package in your code.
You may also benefit from the use of the built-in function round
. Consider the values of available
capital, its prudence fraction and the cost of a share carefully. For example, a trader with prudence
0.9 and available capital 10, can buy 1 share of a stock priced at 1 (dollar).
This is obvious for pen and paper calculation, but on computer it may give you surprises
(due to limited precision of float point arithmetic) if you are not careful.
Testing#
The skeleton file has a testing function: test_stock_trade()
. It runs
some tests on stock_trade
function, and will raise an error if
any of the tests fail. If all tests pass, the testing function prints
the message “all tests passed” at the end.
Remember that testing only checks a small number of predefined cases; it can never prove that your function works correctly for all valid arguments. You should examine the test cases that are provided, and think about whether there are any important ones that are missing.
Note that you can define additional functions, if you think it helps you decompose the problem or write a better solution. Your function definitions should contain docstrings, but it would not be right to use triple-quoted strings as comments anywhere other than on the first line inside a function, or at the beginning of the file.
Marking#
Code quality
In this homework (like in the previous one) we will also be marking your submission for its code quality. This includes aspects such as:
-
Using good function, parameter and variable names.
The names of some functions in the homework are fixed, but if you define additional functions (to decompose the problem) then they should be given descriptive names.
-
Appropriate use of comments and docstrings.
This means not too little comments, but also not gratuitous, useless, incorrect or misleading commenting. Comments should be accurate, relevant, and readable. A docstring should appear as the first statement in every function definition.
-
Good code organisation.
This includes appropriate use of functions to decompose a problem and avoid code repetition (“don’t repeat yourself”, or DRY, principle).
-
Choice of appropriate data structures.
This includes the use of suitable representation of data which your program is operating on. In homework 4, the problem statement already defines a data structure for you to use. In more complex situations, when you define what functions your program will involve and what data they will be using, the choice of data structures is one of the program design. And implementation, too, involves use of data structures which can make the program simpler, shorter and more readable.
To remind you again, do not import modules that you do not use.
What to submit
You should edit the skeleton file stock_trading.py
. Upload only
this file with your implementation of the function using the
assignment submission link
on Wattle.
Remember that you must upload a single Python code file. Do NOT zip or convert it to another format.
The file that you submit must meet the following requirements:
- It must be syntactically correct Python code.
- Like the file you downloaded, it should contain only function
definitions, and, optionally, import statements. However, it is
not necessary to use any module (with exception of
math
) to solve the problem, and you should only import modules that you actually use. Comments, including docstrings (if they are used appropriately) are of course OK to include. Anything that is not a function definition or import statement will be ignored when we test your submission. Importantly, this means you must not use any global variables.
You will attend the following (after the due date) lab where you can discuss this problem with your tutor. This discussion is NOT part of the assessment. Questions which can be discussed are the following:
- If the file has syntax errors, can you use the error messages from the interpreter or IDE to identify where the syntax errors are?
- Does your submitted file meet the requirements stated above? Does it contain anything that is not a function definition? If so, can you point it out?
- Does your implementation pass all the tests run by the unmodified testing function?
- Is your implementation of the function correct for any valid argument?
- Do your functions always return a value of the correct type?
- Does the returning function also prints during execution? Why
such
print
calls are included (except that they were used for debugging during the development)? Is it right to define a function which both prints and returns? What is the difference between theprint
function call and thereturn
statement? - Did you think of any other test cases that should be used to test your function, in addition to those provided?
In marking this assignment we will consider the following:
- Does your submitted file satisfy the requirements specified above?
- Does your implementation compute the correct value for all valid arguments?
- Does the quality of your submitted Python code, including its organisation, naming and documentation (with docstrings and comments) meets the code quality criteria.
The assignment is worth 4% of your final mark. 2 marks are given for the functional correctness, and 2 marks for the quality and readability of your code.