Snippets

Michael Lee WF Hackathon Workshop #1

Created by Michael Lee last modified
from flask import Flask, request, render_template, jsonify, redirect
import random
import os
import urllib.request, urllib.parse, urllib.error, json
import datetime

app = Flask(__name__)
app.debug = True

stocks = []
date = datetime.date(2000, 1, 3)
cash = 100000

class Stock:
    def __init__(self, symbol, quantity, purch_date, init_price):
        self.symbol = symbol
        self.quantity = quantity
        self.purch_date = purch_date
        self.init_price = init_price
        self.earnings = 0
        self.last_price = init_price
        self.last_earning = 0

@app.route("/")
def index():
    return render_template('paper.html', date=date, stocks=stocks, cash=cash)

@app.route("/advance/<int:days>")
def advance_day(days):
    global date
    date += datetime.timedelta(days=days)
    while not is_trading_day(date):
        date += datetime.timedelta(days=1)
    update_stocks()
    return redirect('/')

def update_stocks():
    for s in stocks:
        q = fetch_quotes(s.symbol, date, date)
        if q:
            s.earnings = s.quantity * (float(q['Close']) - s.init_price)
            s.last_earning = s.quantity * (float(q['Close']) - s.last_price)
            s.last_price = float(q['Close'])

@app.route('/trade')
def trade():
    global cash
    symbol = request.args['symbol']
    quantity = int(request.args['quantity'])
    q = fetch_quotes(symbol, date, date)
    if q:
        s = Stock(symbol, quantity, date, float(q['Open']))
        cash -= quantity * s.init_price
        stocks.append(s)
    return redirect('/')

@app.route('/sell/<int:sidx>')
def sell(sidx):
    global cash
    stock = stocks[sidx]
    cash += stock.quantity * stock.last_price
    del stocks[sidx]
    return redirect('/')

@app.route('/lookup/<sym>')
def lookup(sym):
    quotes = fetch_quotes(sym, date-datetime.timedelta(30), date)
    if quotes:
        return jsonify(quotes)
    else:
        return jsonify({})

def is_trading_day(date):
    return fetch_quotes('YHOO', date, date) is not None

def fetch_quotes(symbol, start_date, end_date):
    base_url = 'http://query.yahooapis.com/v1/public/yql'
    yql = ('select * from yahoo.finance.historicaldata where symbol = "' + symbol
           + '" and startDate = "' + start_date.isoformat()
           + '" and endDate = "' + end_date.isoformat() + '"')
    req_url = (base_url + '?q=' + urllib.parse.quote(yql)
               + '&env=http%3A%2F%2Fdatatables.org%2Falltables.env&format=json')
    try:
        response = urllib.request.urlopen(req_url)
        results = json.loads(response.read().decode('utf-8'))['query']['results']
        if results:
            return results['quote']
        else:
            return None
    except urllib.error.HTTPError:
        return None

if __name__ == '__main__':
    app.run()
<!DOCTYPE html>
<html>
    <head>
        <title>Simple Paper Trader</title>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
        <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
        <script src="https://cdn.rawgit.com/etpinard/plotlyjs-finance/master/plotlyjs-finance.js"></script>
    </head>
    <body>
    <p>
        Date: {{ date.isoformat() }}
        <button form="trade" formaction="/advance/1">Advance day</button>
        <button form="trade" formaction="/advance/30">Advance month</button>
        <button form="trade" formaction="/advance/365">Advance year</button>
    </p>
    {% if stocks %}
        <h3>Portfolio</h3>
        <ol>
        {% for s in stocks %}
            <li>
                Symbol: {{ s.symbol.upper() }},
                Quantity: {{ s.quantity }},
                Purchased: {{ s.purch_date.isoformat() }},
                Price: {{ '${:,.2f}'.format(s.last_price) }},
                Gains: {{ '${:,.2f}'.format(s.earnings) }}
                <button form="trade" formaction="/sell/{{ loop.index0 }}">Sell</button>
            </li>
        {% endfor %}
        </ol>
    {% endif %}
    <p>
        Cash on hand: {{ "${:,.2f}".format(cash) }}
    </p>

    <hr>

    <h3>Trade</h3>
    <p>
        <form id="trade" action="/trade">
            <label for="symbol">Symbol</label>
            <input type="text" name="symbol">
            <label for="quantity">Quantity</label>
            <input type="text" name="quantity">
            <input type="Submit" value="Buy">
        </form>
    </p>

    <hr>

    <h3>Lookup</h3>
    <p>
        <form id="lookup">
            <label for="symbol">Symbol</label>
            <input id="lookup_symbol" type="text" name="symbol">
        </form>
    </p>

    <div id="plotly" style="width:700px;height:400px;"></div>

    <script>
        $(function() {
            $('#lookup').submit(function(e) {
                var sym = $('#lookup_symbol').val();
                console.log(sym);
                $.getJSON('/lookup/' + sym, function(quotes) {
                    if (quotes) {
                        var fig = PlotlyFinance.createCandlestick(
                                {
                                    open: $.map(quotes, function (q) {
                                        return parseFloat(q.Open)
                                    }),
                                    high: $.map(quotes, function (q) {
                                        return parseFloat(q.High)
                                    }),
                                    low: $.map(quotes, function (q) {
                                        return parseFloat(q.Low)
                                    }),
                                    close: $.map(quotes, function (q) {
                                        return parseFloat(q.Close)
                                    }),
                                    dates: $.map(quotes, function (q) {
                                        return new Date(q.Date)
                                    })
                                }
                        );
                        Plotly.newPlot('plotly', fig.data, fig.layout);
                        console.log($.map(quotes, function (q) {
                                        return q.Date
                                    }));
                    }
                });
                e.preventDefault();
            });
        });
    </script>
    </body>
</html>

Comments (0)