Search code examples
pythonflasklookupcs50

CS50x2023 Psets9 "Finance". "lookup" function issue with obtaining stock quotes


My issue in this task is to obtain any other then 'None' output from lookup function. After few days of fight I implement a code from yt tutorial exacly 1 to 1 and it still giving same result - 'None' from lookup. I have no idea where I may looking for the source of such behavior. Below I attaching my "quote.html" and @quote app Python code resposible in this exercise to obtain stock quotes and also lookup Python code and my terminal response when I am trying to quote any symbol.

Python code form app.py:

@app.route("/quote", methods=["GET", "POST"])
@login_required
def quote():
    """Get stock quote."""
    if request.method == "POST":
        symbol = request.form.get("symbol")
        quote = lookup(symbol)
        #if not symbol:
            #return apology("Symbol field can not be empty")
        if not quote:
            return apology("Invalid symbol", 400)
        return render_template("quote.html", quote=quote)
    else:
        return render_template("quote.html")

quote.html template:

{% extends "layout.html" %}

{% block title %}
    Quote
{% endblock %}

{% block main %}
    <h2>Get a Stock Quote</h2>
    <form action="{{ url_for('quote') }}" method="post">
        <label for="symbol">Symbol</label>
        <input type="text" id="symbol" name="symbol" placeholder="Symbol">
        <button type="submit">Get Quote</button>
    </form>
    {% if quote %}
        <h3>{{ quote['name'] }} ({{ quote['symbol'] }})</h3>
        <p>Price: {{ quote['price']|usd }}</p>
    {% endif %}
{% endblock %}

Python code for lookup function:

def lookup(symbol):
    """Look up quote for symbol."""

    # Prepare API request
    symbol = symbol.upper()
    end = datetime.datetime.now(pytz.timezone("US/Eastern"))
    start = end - datetime.timedelta(days=7)

    # Yahoo Finance API
    url = (
        f"https://query1.finance.yahoo.com/v7/finance/download/{urllib.parse.quote_plus(symbol)}"
        f"?period1={int(start.timestamp())}"
        f"&period2={int(end.timestamp())}"
        f"&interval=1d&events=history&includeAdjustedClose=true"
    )

    # Query API
    try:
        response = requests.get(url, cookies={"session": str(uuid.uuid4())}, headers={"User-Agent": "python-requests", "Accept": "*/*"})
        response.raise_for_status()

        # CSV header: Date,Open,High,Low,Close,Adj Close,Volume
        quotes = list(csv.DictReader(response.content.decode("utf-8").splitlines()))
        quotes.reverse()
        price = round(float(quotes[0]["Adj Close"]), 2)
        return {
            "name": symbol,
            "price": price,
            "symbol": symbol
        }
    except (requests.RequestException, ValueError, KeyError, IndexError):
        return None

TERMINAL VIEW after trying to quote any symbol:

finance/ $ flask run
 * Debug mode: off
INFO: WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on https://bartosz1tarka-legendary-parakeet-px6wj7xv6vw2655g-5000.app.github.dev
INFO: Press CTRL+C to quit
INFO:  * Restarting with stat
INFO: 127.0.0.1 - - [28/Jul/2024 19:00:23] "GET / HTTP/1.1" 400 -
INFO: 127.0.0.1 - - [28/Jul/2024 19:00:23] "GET /static/styles.css HTTP/1.1" 200 -
INFO: 127.0.0.1 - - [28/Jul/2024 19:00:24] "GET /quote HTTP/1.1" 200 -
INFO: 127.0.0.1 - - [28/Jul/2024 19:00:25] "GET /static/styles.css HTTP/1.1" 200 -
DEBUG: Starting new HTTPS connection (1): query1.finance.yahoo.com:443
DEBUG: https://query1.finance.yahoo.com:443 "GET /v7/finance/download/AAPL?period1=1721581229&period2=1722186029&interval=1d&events=history&includeAdjustedClose=true HTTP/11" 429 19
INFO: 127.0.0.1 - - [28/Jul/2024 19:00:29] "POST /quote HTTP/1.1" 400 -
INFO: 127.0.0.1 - - [28/Jul/2024 19:00:30] "GET /static/styles.css HTTP/1.1" 200 -

I would like to find out the reason why the lookup function returns None, or at least where I should looking for issue. Thanks in advance.


Solution

  • This lookup function does not match the current one from cs50. Suggest getting the latest helpers.py as mentioned in the spec