def quote(): """Get stock quote.""" # User reached route via POST (as by submitting a form via POST) if request.method == "POST": symbol = request.form.get("symbol") # load quore page again if symbol is not provided if not symbol: flash("Please enter stock ticker symbol") return redirect(url_for("quote")) # request symbol info from IEX cloud quoteInfo = lookup(symbol) if quoteInfo is None: flash("The symbol was not found or something else went wrong.") return redirect(url_for("quote")) # Redirect user to page with stock ticker(-s) info return render_template("quoted.html", symbol = quoteInfo["symbol"], name = quoteInfo["name"], price = usd(quoteInfo["price"])) # User reached route via GET (as by clicking a link or via redirect) else: return render_template("quote.html")
def quote(): """Get stock quote.""" form = QuoteForm() if form.validate_on_submit(): resp = lookup(form.symbol.data) return render_template('quoted.html', resp=resp) return render_template('quote.html', form=form)
def index(): """Show portfolio of stocks""" if current_user.is_authenticated: rows = db.session.query(Transactions.symbol,db.func.sum(Transactions.shares)).\ filter_by(user_id=current_user.id).group_by(Transactions.symbol).\ having(db.func.sum(Transactions.shares)!=0).all() symbols = [row[0] for row in rows] prices = {symbol: lookup(symbol)['price'] for symbol in symbols} prices['cash'] = User.query.filter_by(id=current_user.id).first().cash prices['total'] = sum([row[1] * prices[row[0]] for row in rows]) return render_template('index.html', rows=rows, prices=prices) else: return redirect('login')
def buy(): """Buy shares of stock""" form = BuyForm() if form.validate_on_submit(): resp = lookup(form.symbol.data) user = User.query.filter_by(id=current_user.id).first() total_price = int(form.shares.data) * resp['price'] if user.cash < total_price: return apology("not enough cash to complete the transaction") user.cash -= total_price transaction = Transactions(symbol=form.symbol.data, shares=form.shares.data, price=resp['price'], user_id=user.id) db.session.add(transaction) db.session.commit() flash('BOUGHT!', 'success') return redirect('/') return render_template('buy.html', form=form)
def sell(): """Sell shares of stock""" rows = db.session.query( Transactions.symbol, Transactions.shares).filter_by(user_id=current_user.id).all() symbols = [row[0] for row in rows] form = SellForm() form.symbol.choices = ['Select Symbol'] + list(set(symbols)) if form.validate_on_submit(): if form.symbol.data not in symbols: return apology('symbol not in portfolio', 403) elif int(form.shares.data) > sum( [row[1] for row in rows if row[0] == form.symbol.data]): return apology('share number exceeded', 403) user = User.query.filter_by(id=current_user.id).first() resp = lookup(form.symbol.data) total_price = int(form.shares.data) * resp['price'] user.cash += total_price transaction = Transactions(symbol=form.symbol.data, shares=-form.shares.data, price=resp['price'], user_id=user.id) db.session.add(transaction) db.session.commit() flash('SOLD!', 'success') return redirect('/') else: return render_template('sell.html', symbols=symbols, form=form)
def buy(): """Buy shares of stock""" # return base buy page if no url variiables if not request.args and request.method == "GET": return render_template("buy.html") # get user id user_id = session.get("user_id") # request stock ticker symbol from URL symbol = request.args.get("symbol", '') shares = request.args.get("shares", '') # set shares if no number is provided if not shares: shares = 0 # check 'shares' is positive number if int(shares) < 0: return apology("Please enter positive number of shares to buy", 403) # get cash available #fund = db.execute("SELECT cash FROM users WHERE id = :user_id", user_id = user_id) fund = Users.query.filter(Users.id == user_id).first() funds = float(fund.cash) # no stock ticker symbol was provided through GET method if not symbol: # User reached route via POST (as by submitting a form via POST) if request.method == "POST": symbol = request.form.get("symbol") name = request.form.get("name") shares = int(request.form.get("shares")) price = float(request.form.get("price")) # load apology if symbol is not provided if not symbol: return apology("please enter stock ticker symbol", 403) # load apology if number is not provided if not shares or shares <= 0: return apology("Please enter positive number of shares to buy", 403) # check funds available if funds < price * shares: return apology("Sorry, not enough funds for this transaction", 403) # prepare data to be inserted into db amount = round(shares * price, 2) cash_after = funds - amount # fill in transactions table with new data new_transaction = Transactions(user_id=user_id, symbol=symbol, name=name, number=shares, price=price, amount=shares * price, type="buy") db.session.add(new_transaction) db.session.commit() # update cash cur_user = Users.query.filter(Users.id == user_id).first() cur_user.cash = cash_after db.session.commit() message = "You've successfully bought " + str( shares) + " shares of " + symbol flash(message) return redirect(url_for("index")) else: return apology("please enter stock ticker symbol", 403) # request symbol information from IEX cloud quoteInfo = lookup(symbol) # redirect to buy page with error message if no symbol was found if quoteInfo is None: return apology( "The symbol was not found or something else went wrong.", 403) # load buy page with stock ticker information filled in return render_template("buy.html", quoteInfo=quoteInfo, shares=shares, price=quoteInfo["price"], cash=funds, required=quoteInfo["price"] * int(shares))
def sell(): """Sell shares of stock""" user_id = session.get("user_id") # request a list of owned shares #holdings = db.execute("SELECT symbol, name, SUM(number) shares, SUM(amount) total, (SUM(amount) / SUM(number)) avgprice FROM transactions WHERE user_id = :user_id GROUP BY symbol", user_id = user_id) holdings = db.session.query(Transactions.symbol, Transactions.name, func.sum(Transactions.number).label('shares'), func.sum(Transactions.amount).label('total'), label('avgprice', func.sum(Transactions.amount) / func.sum(Transactions.number))).\ filter(Transactions.user_id == user_id).group_by(Transactions.symbol).all() # return base sell page if no url variiables if not request.args and request.method == "GET": if holdings is not None: # prepare a list of owned shares to choose from list = [] for row in holdings: list.append(row.symbol) # load sell page return render_template("sell.html", list=list) # return apology if user does not own any stock else: return apology("You do not own any stock to sell", 403) # request stock ticker symbol from URL symbol = request.args.get("symbol", '') # no stock ticker symbol was provided via GET if not symbol: # User reached route via POST (as by submitting a form via POST) if request.method == "POST": symbol = request.form.get("symbol") name = request.form.get("name") shares = request.form.get("shares") price = float(request.form.get("price")) # load apology if symbol is not provided if not symbol: return apology( "Please choose ticker symbol of stock you want to sell", 403) # load apology if number is not provided if not shares or int(shares) <= 0: return apology( "Please enter positive number of shares to sell", 403) # get owned number of stocks for row in holdings: if symbol == row.symbol: sharesOwned = row.shares break # check number of shares available if int(shares) > sharesOwned: return apology( "Sorry, you do not own enough number of shares ", 403) # prepare data to be inserted into db amount = round(int(shares) * price, 2) * -1 #funds = db.execute("SELECT cash FROM users WHERE id = :user_id", user_id = user_id) funds = Users.query.filter(Users.id == user_id).first() cash_after = float(funds.cash) - amount # fill in transactions table with new data new_transaction = Transactions(user_id=user_id, symbol=symbol, name=name, number=int(shares) * -1, price=price, amount=amount, type="sell") db.session.add(new_transaction) db.session.commit() cur_user = Users.query.filter(Users.id == user_id).first() cur_user.cash = cash_after db.session.commit() message = "You've successfully sold " + str( shares) + " shares of " + symbol flash(message) return redirect(url_for("index")) else: return apology("must enter stock ticker symbol", 403) # request symbol information from IEX cloud quoteInfo = lookup(symbol) # redirect to buy page with error message if no symbol was found if quoteInfo is None: return apology( "The symbol was not found or something else went wrong.", 403) # get number of owned stocks and average price of aquisition for row in holdings: if symbol == row.symbol: sharesOwned = row.shares avgPrice = row.avgprice amount = row.total break # load sell page with stock ticker information filled in return render_template("sell.html", quoteInfo=quoteInfo, sharesOwned=sharesOwned, avgPrice=avgPrice, amount=amount)