# C$50 Finance ## tl;dr Implement a website via which users can "buy" and "sell" stocks, a la the below. ## Background If you’re not quite sure what it means to buy and sell stocks (i.e., shares of a company), head to http://www.investopedia.com/university/stocks/ for a tutorial. You’re about to implement C$50 Finance, a web app via which you can manage portfolios of stocks. Not only will this tool allow you to check real stocks' actual prices and portfolios' values, it will also let you buy (okay, "buy") and sell (okay, "sell") stocks by querying Yahoo Finance for stocks' prices.

Indeed, Yahoo lets you download stock quotes in CSV format via URLs like http://download.finance.yahoo.com/d/quotes.csv?s=NFLX&f=sl1d1t1c1ohgv&e=.csv. Notice how Netflix’s symbol (NFLX) is embedded in this URL (as the value of the HTTP parameter called `s`); that’s how Yahoo knows whose data to return. Notice also the value of the HTTP parameter called `f`; it’s a bit cryptic (and officially undocumented), but the value of that parameter tells Yahoo which fields of data to return to you. If curious as to what they mean, here’s a handy reference. Incidentally, Yahoo sometimes returns prices in currencies other than US dollars (USD) without telling you which, but we’ll assume everything’s in US dollars for simplicity.

Let’s turn our attention now to the app’s distribution code!

## Distribution

``````$wget https://github.com/cs50/problems/archive/finance.zip$ unzip finance.zip
$rm finance.zip$ mv problems-finance finance
$cd finance$ ls
application.py  helpers.py        static
finance.db      requirements.txt  templates``````

### Running

1. Install this problem’s dependencies (within `finance/`):

``pip3 install --user -r requirements.txt``
2. Start Flask’s built-in web server (within `finance/`):

``flask run``

Select CS50 IDE > Web Server to see the distribution code in action. You won’t be able to log in or register, though, just yet!

3. In another terminal window, start phpLiteAdmin (within `finance/`):

``phpliteadmin finance.db``

#### `requirements.txt`

Next take a quick look at `requirements.txt`. That file simply prescribes the packages on which this app will depend.

#### `static/`

Glance too at `static/`, inside of which is `styles.css`. That’s where some initial CSS lives. You’re welcome to alter it as you see fit.

#### `templates/`

Now look in `templates/`. In `login.html` is, essentially, just an HTML form, stylized with Bootstrap. In `apology.html`, meanwhile, is a template for an apology. Recall that `apology` in `helpers.py` took two arguments: `top` and `bottom`. Here they are again! And here’s why. 0:-)

Last up is `layout.html`. It’s a bit bigger than usual, but that’s mostly because it comes with a fancy, mobile-friendly "navbar" (navigation bar), also based on Bootstrap. Notice how it defines a block, `main`, inside of which templates (including `apology.html` and `login.html`) shall go. It also includes support for Flask’s message flashing so that you can relay messages from one route to another for the user to see.

## Specification

### `register`

Complete the implementation of `register` in such a way that it allows a user to register for an account.

• Require that a user input a username. Render an apology if the user’s input is blank or the username already exists.

• Require that a user input a password and then that same password again. Render an apology if either input is blank or the passwords do not match.

• `INSERT` the new user into `users`, storing a hash of the user’s password, not the password itself. Odds are you’ll find `pwd_context.hash` of interest.

• Odds are you’ll want to create a new template (e.g., `register.html`) that’s quite similar to `login.html`.

Once you’ve implemented `register` correctly, you should be able to register for an account and log in (since `login` and `logout` already work)! And you should be able to see your rows via phpLiteAdmin or `sqlite3`.

### `quote`

Complete the implementation of `quote` in such a way that it allows a user to look up a stock’s current price.

• Require that a user input a stock’s symbol.

• Odds are you’ll want to create two new templates (e.g., `quote.html` and `quoted.html`). When a user visits `/quote` via GET, render one of those templates, inside of which should be an HTML form that submits to `/quote` via POST. In response to a POST, `quote` can render that second template, embedding within it one or more values from `lookup`.

### `buy`

Complete the implementation of `buy` in such a way that it enables a user to buy stocks.

• Require that a user input a stock’s symbol. Render an apology if the input is blank or the symbol does not exist (as per the return value of `lookup`).

• Require that a user input a number of shares. Render an apology if the input is not a positive integer.

• Odds are you’ll want to call `lookup` to look up a stock’s current price.

• Odds are you’ll want to `SELECT` how much cash the user currently has in `users`.

• Add one or more new tables to `finance.db` via which to keep track of the purchase. Store enough information so that you know who bought what at what price and when.

• Use appropriate SQLite types.

• Define `UNIQUE` indexes on any fields that should be unique.

• Define (non-`UNIQUE`) indexes on any fields via which you will search (as via `SELECT` with `WHERE`).

• Render an apology, without completing a purchase, if the user cannot afford the number of shares at the current price.

• You don’t need to worry about race conditions (or use transactions).

Once you’ve implemented `buy` correctly, you should be able to see users' purchases in your new table(s) via phpLiteAdmin or `sqlite3`.

### `index`

Complete the implementation of `index` in such a way that it displays an HTML table summarizing, for the user currently logged in, which stocks the user owns, the numbers of shares owned, the current price of each stock, and the total value of each holding (i.e., shares times price). Also display the user’s current cash balance along with a grand total (i.e., stocks' total value plus cash).

• Odds are you’ll want to execute multiple `SELECT`s. Depending on how you implement your table(s), you might find GROUP BY, HAVING, SUM, and/or WHERE of interest.

• Odds are you’ll want to call `lookup` for each stock.

### `sell`

Complete the implementation of `sell` in such a way that it enables a user to sell shares of a stock (that he or she owns).

• The user interface is entirely up to you. You may allow the user to sell one or more shares, or you may require the user to sell all shares of a stock at once.

• You must check for and render apologies for any possible errors.

• You don’t need to worry about race conditions (or use transactions).

### `history`

Complete the implementation of `history` in such a way that it displays an HTML table summarizing all of a user’s transactions ever, listing row by row each and every buy and every sell.

• For each row, make clear whether a stock was bought or sold and include the stock’s symbol, the (purchase or sale) price, the number of shares bought or sold, and the date and time at which the transaction occurred.

• You might need to alter the table you created for `buy` or supplement it with an additional table. Try to minimize redundancies.

### personal touch

• Empower users to change their passwords.

• Empower users to buy more shares or sell shares of stocks they already own via `index` itself, without having to type stocks' symbols manually.

• Empower users with some other feature of comparable scope.

## Testing

No `check50` for this one, but be sure to try to "break" your own site, as by

• inputting alpabetical strings into forms when only numbers are expected,

• inputting zero or negative numbers into forms when only positive numbers are expected,

• inputting floating-point values into forms when only integers are expected,

• trying to spend more cash than a user has,

• trying to sell more shares than a user has,

• inputting an invalid stock symbol, and

• including potentially dangerous characters like `'` and `;` in SQL queries.

## Staff’s Solution

You’re welcome to stylize your own app differently, but here’s what the staff’s solution looks like!

Feel free to register for an account and play around. Do not use a password that you use on other sites.

It is reasonable to look at the staff’s HTML and CSS.

## Hints

• Within `cs50.SQL` is an `execute` method whose first argument should be a `str` of SQL. If that `str` contains named parameters to which values should be bound, those values can be provided as additional named parameters to `execute`. See the implementation of `login` for one such example. The return value of `execute` is as follows:

• If `str` is a `SELECT`, then `execute` returns a `list` of zero or more `dict` objects, inside of which are keys and values representing a table’s fields and cells, respectively.

• If `str` is an `INSERT`, and the table into which data was inserted contains an autoincrementing `PRIMARY KEY`, then `execute` returns the value of the newly inserted row’s primary key.

• If `str` is a `DELETE` or an `UPDATE`, then `execute` returns the number of rows deleted or updated by `str`.

If an `INSERT` or `UPDATE` would violate some constraint (e.g., a `UNIQUE` index), then `execute` returns `None`. In cases of error, `execute` raises a `RuntimeError`.

• Be sure to use named bind parameters (i.e., a paramstyle of `named`) when calling CS50’s `execute` method, a la `WHERE name=:name`. Do not use `format` or `+` (i.e., concatenation), lest you risk a SQL injection attack.

• If (and only if) already comfortable with SQL, you’re welcome to use SQLAlchemy Core or Flask-SQLAlchemy (i.e., SQLAlchemy ORM) instead of `cs50.SQL`.

• You’re welcome to add additional static files to `static/`.

• You’re welcome to select an alternative theme for your site as well as change the site’s aesthetics more generally, including apologies.

• Odds are you’ll want to consult Jinja’s documentation when implementing your templates.

• It is reasonable to ask others to try out (and try to trigger errors in) your site. Via Share in CS50 IDE’s top-right corner can you share your Application by making it Public. Take care not to share your Editor, which would provide access to your Python code and SQLite database.

## FAQs

### ImportError: No module named 'application'

By default, `flask` looks for a file called `application.py` in your current working directory (because we’ve configured the value of `FLASK_APP`, an environment variable, to be `application.py`). If seeing this error, odds are you’ve run `flask` in the wrong directory!

If, upon running `flask`, you see this error, odds are you (still) have `flask` running in another tab. Be sure to kill that other process, as with ctrl-c, before starting `flask` again. If you haven’t any such other tab, execute `fuser -k 8080/tcp` to kill any processes that are (still) listening on TCP port 8080.