ICS 32 Fall 2018
Project #3:?Jack of All Trades

Due date and time:?Wednesday, November 14, 11:59pm

This project is to be done individually


We saw in the previous project that our Python programs are capable of connecting to the “outside world” around them — to other programs running on the same machine, or even to other programs running on different machines in faraway places. This is a powerful thing for a program to be able to do, because it is no longer limited to taking its input from a user or from a file stored locally; its input is now potentially anything that’s accessible via the Internet, making it possible to solve a vast array of new problems and process a much broader collection of information. Once you have the ability to connect your programs to others, a whole new world opens up. Suddenly, the idea that you should be able to write a program that combines, say, Google search queries, the Internet Movie Database, and your favorite social network to find people who like movies similar to the ones you like doesn’t seem so far-fetched.

But we also saw that getting programs to share information is tricky, for (at least) two reasons. Firstly, there’s a software engineering problem: A protocol has to be designed that both programs can use to have their conversation. Secondly, there’s a social problem: If the same person (or group of people) isn’t writing both programs, it’s necessary for them to agree on the protocol ahead of time, then to implement it. This second problem has a potentially catastrophic effect on our ability to make things work — how could you ever convince Google to agree to use your protocol just to communicate with you?

In practice, both of these problems are largely solved by the presence of?standards, such as those defined by the??and the?. Standards help by providing detailed communication protocols whose details have already been hammered out, with the intention of handling the most common set of needs that will arise in programs. This eliminates the need to design one’s own protocol (where the standard protocols will suffice, which is more often than you might think) and allows programs to be combined in arbitrary ways; as long as they support the protocol, they’ve taken a big step toward being able to interoperate with each other. What’s more, standard protocols often have standard implementations, so that you won’t have to code up the details yourself as you did in the previous project. For example, Python has built-in support for a number of standard Internet protocols, including HTTP (HyperText Transfer Protocol, the protocol that your browser uses to download web pages) among others.

At first blush, HTTP doesn’t seem all that important. It appears to be a protocol that will allow you to write programs that download web pages (i.e., that allow you to write programs that play the same role that web browsers do). But it turns out that HTTP is a lot more important than that, since it is the protocol that underlies a much wider variety of traffic on the Internet than you might first imagine. This is not limited only to the conversation that your browser has with a web server in order to download a web page, though that conversation most often uses HTTP (or its more secure variant, HTTPS). HTTP also underlies a growing variety of program-to-program communications using web protocols, where web sites or other software systems communicate directly with what are broadly called?web services, fetching data and also making changes to it. This is why you can post tweets to Twitter using either their web site, a client application on your laptop, or a smartphone app; all of these applications use the same protocol to communicate with the Twitter service, differing only in the form of user interface they provide.

Fortunately, since HTTP support is built directly into Python, we can write programs that use these web services without having to handle low-level details of the protocol, though there are some details that you’ll need to be familiar with if you want to use the provided implementation effectively. We’ll be discussing some of these details in lecture soon, and these will be accompanied by a?, which will give you some background in the tools you’ll need to solve these kinds of problems in Python.

This project gives you the opportunity to explore a small part of the vast sea of possibilities presented by web APIs and web services. You’ll likely find that you spend a fair amount of your time in this project understanding the web API you’ll need — being able to navigate technical documentation and gradually build an understanding of another system is a vital skill in building real software — and that the amount of code you need might not be as much as you expect when you first read the project write-up. As always, work incrementally rather than trying to work on the entire project all at once; there is partial credit available for a partial solution, as long as the portions that you’ve finished are stable and correct. When you’re done, you’ll have taken a valuable step toward being able to build Python programs that interact with web services, which opens up your ability to write programs for yourself that are real and useful.

Additionally, you’ll get what might be your first experience with writing classes in Python, which will broaden your ability to write clean, expressive Python programs, a topic we’ll continue revisiting and refining throughout the rest of this course. Along with that, you’ll learn about why it can be a powerful technique to write multiple, similar classes in a way that leaves them intentionally identical in at least one aspect.

Reminder: Do not select a partner

Unlike the previous projects, which offered you the option of using the pair programming technique, this project?requires that you work individually. So you will not be selecting a partner and you will not be doing pair programming this time; each student is responsible for his or her own submission for this project. While we do believe that pair programming offers a lot of benefits, you’ll also need to build your skills at working on your own, as future coursework (and possibly future employment) will depend on them.

Reusing your own work from a previous quarter

Unlike on work done with a partner, you are permitted to reuse your own work if you took this course previously. We recommend doing the projects again from a clean slate, anyway, because there are likely some significant things that you didn’t understand if you’ve failed this course previously. Still, it is not plagiarism to use code that was solely yours to begin with.

Overview of the program

In your work on this project, you will write a program that is capable of using information gathered from a web service to obtain past prices of stocks, calculate some metrics summarizing those prices, and ultimately report on potentially opportune times to buy or sell the stock, based on one of a few automated buying-and-selling strategies.

Some background on the buying and selling of stocks

It’s quite possible that you know relatively little about investing, so this section offers the necessary background that you’ll need for this project. Like many programs that you write to automate some kind of real-world activity, you need to know enough about that activity in order to understand the problem you’re trying to solve; this situation is no different.

First of all,?stock?represents ownership in a business entity. A given business entity, such as Apple, divides its overall ownership stake into?shares?of stock. For our purposes, you can think of each share as being a small, equal percentage of ownership of the company, though the arrangement can be more complex than this; the more shares you own, the greater percentage of the company you own. In the case of Apple, as of this writing, there are around 4.8 billion shares that are?publicly traded?(i.e., individuals like you and I can buy them, provided that we have the money and that someone else is willing to sell them to us). On the day I wrote this, you or I could have bought one of those shares for around $212, which would have given us ownership of roughly 1/4,800,000,000th of the company. (It should be noted that not nearly all companies in the world are publicly traded, but we’ll focus our attention in this project on those that are.)

Share prices in publicly-traded companies are determined via a?stock exchange, where interested buyers and sellers meet (electronically, most of the time) and negotiate prices. Buyers specify what they’re willing to pay, sellers specify what they’re willing to accept, and when there is a match between someone willing to buy for a certain amount and someone else willing to sell for that same amount, a?trade?takes place; the buyer exchanges money in return for shares. Prices can be somewhat volatile; using the example of Apple’s trading on the day of this writing, the price of one share ranged between $206 and $220 at different times during the day, with a total of around 45,000,000 shares changing hands just today. (And just to show you how volatile those prices can be, that same share traded for as low as $150 within the last year and about $235 at one point earlier this month.)

Stocks that trade on stock exchanges generally have a?symbol?(sometimes called a?ticker symbol) associated with them, which is a shorthand name that is used to uniquely identify a company on that exchange. In the United States, symbols are generally a sequence of uppercase letters; in some parts of the world, digits are also common. For example, the symbol on U.S. stock exchanges for Apple is AAPL, while Microsoft’s is MSFT, Johnson & Johnson’s is JNJ, and Verizon’s is VZ.

There are vast databases of every trade that was made in every stock every day: when the trade was completed, how many shares traded, the symbol identifying the stock that was traded, and at what price. This is an overwhelming amount of data, and is not generally available online for free in its full detail, since the data has so much potential value. Given such a database, one can develop automatic strategies for rapidly buying and selling and test them against loads of real-world pricing data, which can lead to shockingly effective ways to both make and lose money. (An error in one firm’s automated trading software in 2012 cost it in excess of $400 million in one day.)

However, even though we may not be able to easily access an itemized list of every individual trade from every day, it is possible to find summary data at little or no cost. For example, one thing we can obtain are daily summaries of trade activity, including these data points:

  • The?opening price, which is the price at which that stock’s first trade of the day was made.
  • The?closing price, which is the price at which that stock’s last trade of the day was made.
  • The?high price, which was the highest price at which the stock traded during the day, regardless of what time of day it was.
  • The?low price, which was the lowest price at which the stock traded during the day, regardless of what time of day it was.
  • The?volume, which is the total number of shares that changed hands during the day.

Given this information, we can start to form an understanding of the overall price action, even if we don’t have an explicit description of every individual trade.

Trading does not take place every day. Generally speaking, there are no trades on weekends or holidays, nor during nighttime hours where the stock exchange is located — though this is gradually changing as years go by. Your program will not need to do anything special to handle that; it will simply determine from historical data which days included trading and which didn’t, then ignore the days on which there were no trades.

What will your program do?

Generally, your program will perform the following tasks.

  • Wait for the user to specify what analysis they want to run.
  • Download the relevant information about the stock and its previous prices from a web service.
  • Calculate the user’s chosen?indicator?for each trading day in that stock.
  • Determine the days on which the user’s chosen?signal strategy?would have decided to buy or sell the stock.
  • Print a detailed report describing the outcome of the analysis.

There is more to be said about the details of each of these requirements, as there will be automation used in grading this project, but we’ll need to begin with an understanding of some of the background concepts.


The core of our analysis will be comparing daily price and volume data against the values of?indicators. There are three kinds of indicators we’ll use:

  • True range. The range of prices (highest price minus lowest price) for the current day, including any movement since the previous day’s close.
    • Suppose the stock had a high price of $160 and a low price of $150 on a given day. If the previous day’s close was within that range, as well, then the true range for this day is $160 – $150 = $10. If the previous day’s closing price was higher than $160 or lower than $150, then we’d extend the range accordingly; for example, if the previous day’s close was $145, then the true range for this day is $160 – $145 = $15.
    • Be aware, too, that there can’t be a true range value on the first day of your analysis, since its value depends (partly) on knowing the previous day’s closing price.
  • Simple moving average. The?N-day simple moving average?at the end of a particular day is the average of the most recent N closing prices. Days on which there is no trading are not counted. So, for example, the?10-day simple moving average?each day is simply the average of the most recent 10 closing prices. Note that the simple moving average on a particular day?includes?that day’s closing price, along with the N – 1 days preceding.
    • One wrinkle to be aware of here: You need at least N days of prices before you can begin calculating a simple moving average. So the first N – 1 days will not have a simple moving average at all; only on the Nth day are there enough closing prices to report an N-day moving average.
    • An additional wrinkle to be aware of: Simple moving averages can be calculated not only on closing prices, but also on volumes. They work identically, except that we’re aggregating the volume each day instead of the closing price.
  • Directional indicator. The?N-day directional indicator?for a stock is the number of closing prices out of the most recent N on which the stock’s price went up (i.e., it closed at a higher price than the previous close)?minus?the number of days out of the previous N on which the stock’s price went down (i.e., closed at a lower price than the previous close). It stands to reason, for example, that the?10-day directional indicator?will be somewhere between -10 and +10. As with the simple moving average, the directional indicator for a particular day includes that day’s closing price.
    • Unlike simple moving averages, directional indicators are always possible to calculate, by assuming that the price didn’t move on any previous day. In a given report, the first day’s indicator value will always be 0, because you don’t know whether the stock’s move that day was up or down (since you don’t have the previous day’s price). When there are fewer than N days of prices, you simply calculate the directional indicator using the number of days you have available.
    • Note, too, that directional indicators, like simple moving averages, can be calculated on volumes as well as on closing prices.

Generally, you can think of indicators as aggregating price information for multiple days together into single values that broadly describe what happened across those days. These can then form the basis of decisions about buying and selling.

Signal strategies

The main goal of the analysis is to generate?buy signals?and?sell signals, which are recommendations to buy or sell stock at the conclusion of a particular day.

There are multiple signal strategies that we’ll implement, each corresponding to one the indicators above:

  • Generate buy and sell signals based on the?true range, with the user choosing a?buy threshold?and a?sell threshold. Each threshold is specified as a percentage of the previous day’s closing price, as well as a notion of being below or above that percentage. For example, the user might choose to buy when the true range is above 2% of the previous day’s closing price, and to sell when the true range is below 0.1%.
    • If the true range on a particular day divided by the previous day’s closing price meets the buy threshold, generate a buy signal.
    • If the true range on a particular day divided by the previous day’s closing price meets the sell threshold, generate a sell signal.
    • Example: If the previous day’s closing price is $50 and today’s true range is $2, the percentage is 4%. Suppose the buy threshold is anything below 0.5% and the sell threshold is above 3%. 4% meets the sell threshold (i.e., it’s above 3%), so we would generate a sell signal for today.
  • Generate buy and sell signals based on the?N-day simple moving average of closing prices, with the user choosing N (i.e., the number of days). Smaller numbers of days are more sensitive (i.e., more likely to generate a signal), while larger numbers of days are less so. Signals are generated as follows:
    • If the closing price on a particular day has?crossed above?the simple moving average (i.e., the closing price on that day is above that day’s simple moving average, while the previous closing price is not above the previous simple moving average), generate a buy signal.
    • If the closing price on a particular day has?crossed below?the simple moving average, generate a sell signal.
    • Otherwise, generate no signal.
  • Generate buy and sell signals based on the?N-day simple moving average of volumes?instead, using the same approach as above.
  • Generate buy and sell signals based on the?N-day directional indicator of closing prices, with the user choosing N (i.e., the number of days) and?buy and sell thresholds.
    • If the directional indicator has?crossed above?the buy threshold (i.e., the indicator above the buy threshold on that day but is not above the buy threshold on the previous day), generate a buy signal.
    • If the directional indicator has?crossed below?the sell threshold, generate a sell signal.
    • Otherwise, generate no signal.
  • Generate buy and sell signals based on the?N-day directional indicator of volumes, using the same approach as above.

In general, any signal — buy or sell — can occur on any day; there is no general limitation that, for example, buys must precede sells or that consecutive signals can’t be the same (e.g., two consecutive buys or three consecutive sells), or even that a buy and sell signal can’t occur on the same day. There is also not guaranteed to be a signal every day; in fact, in most configurations, there will be relatively few signals generated.

Where to get historical data about stock trades

A recently-formed stock exchange called?IEX?(Investors Exchange LLC) provides a variety of data about stocks and trading via its?IEX API. The IEX API is a web API, similar to the YouTube Data API we saw in a??in lecture, that allows you to obtain the information you’ll need via Secure HTTP.

Testing out the IEX API

To begin to see how the IEX API works, try visiting the following link. There’s no need to modify it; use it as-is.

If successful, you should receive a result that looks roughly like this (though you may get different data than this, since the information is time sensitive).

[{"datetime":"2018-10-30T17:53:00-04:00","headline":"Mark Zuckerberg: Apple is
Facebook's 'biggest competitor by far' in messaging","source":"CNBC","url":
"summary":"No summary available.","related":"AAPL,FB",
{"datetime":"2018-10-30T15:23:00-04:00","headline":"Facebook could be bottoming
- here's why","source":"CNBC","url":
"summary":"No summary available.","related":"AAPL,FB",
{"datetime":"2018-10-30T13:32:00-04:00","headline":"Apple's new MacBook Air
blows the regular MacBook out of the water on price and power","source":"CNBC",
"summary":"No summary available.","related":"AAPL",

You may recognize from lecture that this format is JSON (JavaScript Object Notation), which is a common format of information that is exchanged with web API’s like this one. Unfortunately, it’s not presented in a way that’s particularly readable for us — though, in general, that’s not a problem for our program, because our program doesn’t have the same set of aesthetic needs that we do. To take your first look at what’s being returned, you might find it useful to copy all of the text returned to you, then visit??and paste the text and ask for it to be “pretty-printed.” You’ll now see the same text, but spaced in a way that will make its structure more obvious to a human reader.

Once it’s “pretty-printed,” take a look through it. Don’t worry if you don’t understand every detail, but start to get a rough sense of what kind of information is available and how it’s organized. When you want to know the details, the API documentation will explain everything you need, and you’ll find that you can discover a lot of the details through additional experimentation. But it’s important that you allow yourself to build an understanding gradually; this is not something you’ll necessarily be able to figure out right away, but a lot of the information won’t turn out to be relevant in this project, anyway. One characteristic that distinguishes real-world work from the often-sanitized kinds of projects you do in courses like this is the need to find small nuggets of information you need amongst large amounts of documentation that is largely irrelevant to the problem you want to solve; I want you to start building those skills (and alleviate your fears about this kind of thing) now, so you can start working on your own programs that are more “real” and, thus, more exciting.

Respecting IEX’s license

Being the owner of the service, IEX has a license that describes the conditions under which you’re permitted to use it. For the curious, the license (a “Terms of Use” document) for the IEX API is available at the link below. If you’ve never looked at the license for a software product, take a minute or two to see what one looks like; when you build software that depends on other software, what you can and can’t do with the other software will generally be described in a license like this one.

Don’t feel like you need to read the whole thing in detail, but at least spend a little time getting familiar with what a license like this looks like. If you want to work in technology, it won’t be the last one of these you’ll see. I’m certainly not a lawyer, but I do know how to skim through a license to see whether there are obvious red flags that suggest that I won’t be able to use a product in the way I plan to. And for the parts I’m less sure about, I can seek legal counsel — and sometimes my employers will require (and provide) legal oversight, but it helps if I understand the basics of the license first.

In general, what we mainly care about with respect to IEX’s license is that they require us to give them credit when we display their data, so we’ll respect this in the output of our program by doing so. Beyond that, the exploratory and educational nature of what we’re doing makes most of the rest of the license less important — of course we aren’t going to sue them, for example, if the data turns out to be incomplete or incorrect.

Skimming the documentation

The IEX API is described in detail at the link below. You certainly won’t need to read all of the documentation to start with, but you’ll want to take a look around and familiarize yourself with what kinds of information the API provides, because part of your goal in this project is to decide what parts of the API you’ll need to solve your problem.

Details of your program’s input and output

As in at least one previous project, the intent here is not to write a user-friendly user interface; what you’re actually doing is building a program that we can test?automatically, so it’s vital that your program reads inputs and writes outputs precisely as specified here.

Generally, your program will read a set of input without prompting the user in any way (i.e., without printing anything that tells the user what they should be entering). After that, your program will generate a report and print it.

The input

Your program will read its input from the Python shell in the following format. You can freely assume that the input will always be given in precisely this format; we will not be testing your program on any inputs that don’t match this specification.

  • The first line of input specifies the symbol associated with the stock, such as?AAPL?or?MSFT.
  • The second line of input specifies the time period for which an analysis is to be done. There are three possible values that will appear on this line:
    • M, which indicates an analysis that covers the last month.
    • Y, which indicates an analysis that covers the last year.
    • F, which indicates an analysis that covers the last five years.
  • The third line of input specifies what combination of an indicator and a signal strategy will be used in the analysis.
    • TR?means that the true range indicator will be used. This is followed by a space, followed by a buy threshold, followed by a space, followed by a sell threshold. Each threshold is described by either a?<?or a?>?character, followed by a percentage. For example,?TR <1.5 >0.5indicates that the true range indicator should be calculated, that a buy signal should be generated when the true range is less than 1.5%, and that a sell signal should be generated when the true range is greater than 0.5%.
    • MP?means that the simple moving average indicator will be calculated for the closing prices. This is followed by a space, followed by a number of days (i.e., the “N” value), followed by a space. A buy signal should be generated when the closing price crosses above the N-day simple moving average; a sell signal should be generated when the closing price crosses below the N-day simple moving average. For example,?MP 50?means that we should determine the 50-day simple moving average, then buy and/or sell when the price crosses above and/or below it.
    • MV?means the same thing as?MP, except that we calculate the simple moving average of the volumes instead of the closing prices. For example,?MV 10?means that we should determine the 10-day simple moving average of volumes, then buy and/or sell when the volume crosses above and/or below it.
    • DP?means that the directional indicator will be calculated for the closing prices. This is followed by a space, followed by a number of days (i.e., the “N” value), followed by a space, followed by a buy threshold (which is an integer between -N and N), followed by a space, followed by a sell threshold (which is an integer between -N and N). For example,?DP 10 5 -3?means that we should determine the 10-day directional indicator, then buy when it crosses above +5 and sell when it crosses below -3.
    • DV?means the same thing as?DP, except that we calculate the simple moving average of the volumes instead of the closing prices. For example,?DV 10 5 -3?means that we should determine the 10-day directional indicator of volumes, then buy and/or sell when the volume crosses above and/or below it.

The report

Your report will be printed out in a?tab-delimited?format, which is to say that you’ll write lines of output on which there are pieces of information separated by tab characters. For example, if you wanted to print a line with three pieces of information?A,?B, and?C, you’d print a line containing (in Python terms)?‘A\tB\tC’. This format has a couple of advantages for us:

  • It will be possible for you to easily copy and paste the entire output of your program into a spreadsheet to do further analysis on it.
  • It will be easier for us to automate testing, including easily detecting which information is missing. (As long as everything that’s there is where it needs to be, we can give partial credit for it, even if other things are missing.)

The format is described in the form of tables below, though you’ll write this in a tab-delimited form instead, with one tab character in between the cells on each line (and you’ll need to include the tab even if a cell is empty) and a newline on the end of each line.

The report begins with what is called a?header, which specifies some basic information about the stock that we’re analyzing.

The stock’s symbol, such as?AAPL
The name of the company, such as?Apple Inc.
The integer number of?shares outstanding?(i.e., how many shares of this stock exist, in total)

After that, for each day on which there was trading in that stock — based on the information returned to you by the IEX API — you would print one line of information containing these fields. (The lines would be sorted in ascending order of the date.)

Date Opening Price Closing Price High Price Low Price Volume Indicator BUY?if there is a buy signal on this day SELL?if there is a sell signal on this day

Some formatting rules apply to the values in this table:

  • All dates should be specified in?YYYY-MM-DD?format (e.g., October 30, 2018 would be printed as?2018-10-30).
  • All prices should be specified to exactly four digits beyond the decimal point, even if these digits are zeroes; no dollar sign should be included. (For example, a price of $50 would be printed as?50.0000.)
  • A true range indicator value should be specified as a percentage to four digits after the decimal point, even if these digits are zeroes; no percent sign should be included. (For example, a true range of 2.5% would be printed as?2.5000.)
  • Simple moving average indicator values should be specified to exactly four digits beyond the decimal point, even if these digits are zeroes; no dollar sign or other symbols should be included. (For example, a simple moving average of 15.57 would be printed as?15.5700.)
  • Directional indicator values should be printed as an integer number, such as?-3?or?6.

Your decimal values can differ from ours by 1/10000th (e.g., if we expect?17.8046, we would also accept?17.8045?or?17.8047).

Finally, you’ll need to print a citation that gives IEX credit for owning its own data, which is required by its terms of use. That citation would appear in three fields on the last line of your report, formatted as specified below. (We can’t quite meet their requirement, since we can’t print a clickable web link, but we can at least print the URL.)

Data provided for free by IEX View IEX’s Terms of Use https://iextrading.com/api-exhibit-a/

An example input and report

An example input and report for the program follows. Note that you will not necessarily get the same answer as I’m showing below if you run the program, mainly because the results are time sensitive (i.e., when you run a one-month report, you’re asking for the most recent one month of data; if you do that again next week, you’ll be getting different data). But if the prices were the ones I list below, the rest of the calculations are correct.

Suppose that the input to the program was as follows.

MP 10

What we’re doing is an analysis of the last month of a stock with symbol?BOO, using the 10-day moving average of closing prices to generate buy and sell signals.

The report would look like this. (Again, data that would come from the IEX API is hypothetical, but the indicators and signals are correct given that data.) Note that I’m simulating tab characters with spaces; what you’ll want are tabs between the fields, as specified. (Note, too, that your report may look like it’s spaced differently — or even unevenly — since tabs aren’t always printed as the same number of spaces. But the fields on each line should be separated by a tab character, even if that means the table appears to be formatted poorly.)

Forever Boo Enterprises
2018-10-01     8.0000  9.0000  9.5000  7.7500  5000
2018-10-02     8.9000  9.2000  9.2000  8.8000  7500
2018-10-03     9.1500  8.7500  9.2500  8.6000  10000
2018-10-04     8.7000  8.4500  8.7200  8.4100  8000
2018-10-05     8.5000  8.2700  8.5000  8.2700  9000
2018-10-08     8.3000  8.4000  8.6100  8.2400  6500
2018-10-09     8.3500  8.2900  8.3800  8.2000  4100
2018-10-10     8.2800  8.2000  8.3000  8.1800  3800
2018-10-11     8.2100  8.2500  8.3500  8.1800  5200
2018-10-12     8.2500  8.1000  8.3100  8.0900  7000    8.4910
2018-10-15     8.1500  8.3200  8.3500  8.0800  8200    8.4230
2018-10-16     8.3500  8.6000  8.6200  8.3000  9500    8.3630  BUY
2018-10-17     8.5000  8.5500  8.6500  8.4900  3700    8.3430
2018-10-18     8.5100  8.2900  8.5300  8.2800  11400   8.3270          SELL
2018-10-19     8.2700  8.3000  8.3600  8.2400  8100    8.3300
2018-10-22     8.2800  8.1900  8.3100  8.1600  9900    8.3090
2018-10-23     8.2000  8.4100  8.4300  8.2000  7600    8.3210  BUY
2018-10-24     8.3800  8.3000  8.4200  8.2900  4300    8.3310          SELL
2018-10-25     8.2900  8.5500  8.5500  8.2600  6800    8.3610  BUY
2018-10-26     8.6000  9.1400  9.1400  8.5600  10600   8.4650
2018-10-29     9.2100  9.5000  9.5500  9.1500  11100   8.5830
2018-10-30     9.6000  9.9800  9.9900  9.5000  13000   8.7210
2018-10-31     9.9600  9.9000  9.9800  9.8500  4900    8.8560
Data provided for free by IEX  View IEX's Terms of Use https://iextrading.com/api-exhibit-a/

Obtaining partial credit for a partial solution

When we grade your project, we will be focusing not only on looking for a perfect solution, but also for a partial one. For example, if you implement one of the indicators and one of the signal strategies, but not the others, we’ll aim to offer you partial credit.

What this means, though, is that we need to agree on the basic criteria for offering that partial credit. This means that even if your program can’t handle certain calculations, you’ll still want to organize your report in the appropriate format.

  • If all you display is the header information, we can offer some credit for that, even if none of the rest of the lines are printed.
  • If all you display is the citation at the bottom, we can also offer some credit for that.
  • If you print the dates but no price or volume information, no indicator values, and no buy or sell recommendations, we can offer some credit for that.
  • If you print the dates, price, and volume information, but no indicator values and no buy or sell recommendations, we can offer some credit for that.
  • If you’re able to display indicators but no buy or sell recommendations, that’s a more substantial amount of partial credit — and if you can print some kinds of indicators and not others, that’s also an avenue for partial credit.

So, generally, what you’ll want to be doing is printing the information you have in the correct places, even if you don’t have all of the information you need. That way, our test automation tools will be able to allocate partial credit appropriately and fairly. A program that is partially complete but is unable to generate any output will be graded a lot less favorably than one capable of printing some of the output but putting it in the right place, so you’ll want to keep that in mind as you work incrementally.

Design requirements and advice

As with the previous project, you’ll be required to design your program using multiple Python modules (i.e., multiple?.py?files), each encapsulating a different major part of the program. The following would be a good way to break this problem down into its component parts.

  • A module that implements the indicators. These must be implemented as?classes; see below.
  • A module that implements the signal strategies. These must be implemented as?classes; see below.
  • A module that is capable of downloading the necessary information from the IEX API, ideally organized in a way that makes it most useful to other parts of your program.
  • A module implementing the input and output portion of your program. This is the only module that should have an?if __name__ == ‘__main__’:?block to make it executable; you would execute this module to run your program. This module’s name must be?project3.py.

Indicators and signal strategies as classes

Each of your indicators and each of your signal strategies is required to be implemented as a Python?class, which contains attributes that configure it (e.g., for the simple-moving-average-based strategy, an attribute would store the number of days to use in the average calculation), and a method that executes the strategy against a collection of price information.

All of your indicator classes must have a method with the same signature (i.e., the same name, the same parameters, and the same type of return value), so that your user interface could call into it without depending on which kind of indicator object it is. The same must be true of your signal strategy classes.

(This is one key benefit in using classes in Python; we can treat different kinds of objects with similar capabilities the same way, which avoids us having to use?if?statements to differentiate. We saw an example of this in lecture, when we talked about?duck typing.)

Where should I start?

There are lots of ways to start this project, but your goal, as always, is to find stable ground as often as possible. One problem you know you’ll need to solve is generating the final report, so you could begin by generating a portion of it — maybe just the header and each day’s price, but formatted correctly, since this can lead to partial credit. Now you’re on stable ground.

One problem you know you’ll need to solve is the problem of calculating a list of indicator values, given a list of price information; you might consider continuing with that. You can test this from the Python shell before proceeding, and then you’re on stable ground. Continue with another indicator. Now you’re on stable ground again.

From there, you might continue by implementing a module that gives you a set of test price information without reaching out to the IEX API. You won’t want to submit this one, but it will be useful in allowing you to continue your work without handling the downloading of quotes from the API right away. This might allow you to continue by implementing and testing your signal strategies.

Once you’ve got these implemented, you might continue with the downloading feature, and, finally, the entire report. But, again, there are lots of sequences that could lead to a good solution, and you’ll want to consider how you can achieve partial solutions that nonetheless meet the requirements partially, because partial credit is available for those.

A note about the signal strategies presented here

The strategies used here to determine whether to buy or sell stocks are chosen more for their ability to be implemented using skills you have, as opposed to being designed as sound investing strategies. It is not uncommon for programs to use historical data — often over multiple time frames, in addition to daily — to make buying and selling decisions in place of people, and the things we’re doing here form a very loose basis for how some of those decisions get made, but the algorithms for making these decisions are generally more complex and tend to vary over time; what works today may no longer work a year from now when people’s behavior, as well as the behavior of other automated buying-and-selling programs, may have changed.


Put your name and student ID in a comment at the top of each of your?.py?files, then submit all of the files to Checkmate. Take a moment to be sure that you’ve submitted all of your files. Note, too, that the “executable” module (i.e., the one you execute when you want to run your whole program)?must?be named?project3.py.

Follow??for a discussion of how to submit your project via Checkmate. Be aware that I’ll be holding you to all of the rules specified in that document, including the one that says that you’re responsible for submitting the version of the project that you want graded. We won’t regrade a project simply because you submitted the wrong version accidentally.

Can I submit after the deadline?

Yes, it is possible, subject to the late work policy for this course, which is described in the section titled?Late work?at?.

  • Originally written by Alex Thornton, Fall 2018.