def get_prices(my_stocks): for keys in my_stocks: new_stock = Stock(keys) stock_price = get_data(new_stock) new_stock.set_price(stock_price) my_stocks[keys] = new_stock.price return my_stocks
def functionGetStock(): form = SearchForm() if request.method == 'POST' and form.validate_on_submit(): stock = Stock.select(Product.id.alias('product_id'), Product.product_name.alias('product_name'), Product.product_code.alias('product_code'), Product.description.alias('product_description'), Product.price.alias('product_price'), Stock.id.alias('stock_id'), Stock.amount.alias('stock_amount'))\ .join(Product, on=(Stock.product_id == Product.id))\ .where( Product.product_code.contains(form.search.data) | Product.product_name.contains(form.search.data) | Product.description.contains(form.search.data) ) else: stock = Stock.select(Product.id.alias('product_id'), Product.product_name.alias('product_name'), Product.product_code.alias('product_code'), Product.description.alias('product_description'), Product.price.alias('product_price'), Stock.id.alias('stock_id'), Stock.amount.alias('stock_amount')).join( Product, on=(Stock.product_id == Product.id)) return render_template('stock/list_stock.html', current_user=current_user, form=form, len_list=len(stock), list_stock=stock)
def setUp(self): """Define test variables and initialize app.""" self.app = create_app(config_name="testing") self.client = self.app.test_client # binds the app to the current context with self.app.app_context(): # create all tables db.create_all() # Insert testing data Stock(test_stock_1_ticker, test_stock_1_date_1, close=test_stock_1_close_1).save() Stock(test_stock_1_ticker, test_stock_1_date, close=test_stock_1_close).save() Stock(test_stock_2_ticker, test_stock_2_date_1, close=test_stock_2_close_1).save() Stock(test_stock_2_ticker, test_stock_2_date, close=test_stock_2_close).save() User(test_user_id, test_user_name).save() Watchlist(test_stock_1_ticker, test_user_id).save() Watchlist(test_stock_2_ticker, test_user_id).save()
def test_calc_sma(self, patched_rolling_mean): # for some reason, the test doesn't pass when I directly pass in # self.stock.data['Adj Close'] to the assert_called_with function. It # bombs out somewhere deep in Pandas... I'll need to figure that out later adj_close = self.stock.data['Adj Close'] Stock.calc_sma(self.stock, 3) patched_rolling_mean.assert_called_with(adj_close, 3) assert(isinstance(self.stock.data['sma3'], Series) is not None)
def update_stock_price(stock: models.Stock, db: Session = Depends(get_db)): """Update stock price""" price = finnhub_client.quote(stock.ticker)['c'] stock.price = price stock.last_updated = datetime.now() db.commit() db.refresh(stock) return stock
def test_add_stocks(self): # make 1 user u1 = User(username='******', email='*****@*****.**') db.session.add(u1) # make 2 stocks s1 = Stock(stkid='fb') s2 = Stock(stkid='nvda') db.session.add(s1) db.session.add(s2) db.session.commit() u1.insterest_in(s1)
async def create_stock(stock_request: StockRequest, background_tasks: BackgroundTasks, db: Session = Depends(get_db)): stock = Stock() stock.symbol = stock_request.symbol db.add(stock) db.commit() background_tasks.add_task(fetch_stock_data, stock.id) return { "code": "success", "message": "stock created" }
def test_NaN(self): Stock.calc_sma(self.stock,3) # After calculating an average, ensure their are NaNs in the right places assert(pd.isnull(self.stock.data.iloc[0]['sma3'])) assert(not pd.isnull(self.stock.data.iloc[2]['sma3'])) shape_before_clearing = self.stock.data.shape # tuple of (rows, columns) Stock.clear_NaN(self.stock) # assert the number of rows decreases by 2 assert(self.stock.data.shape[0] == shape_before_clearing[0] - 2) # assert the number of columns remains the same assert(self.stock.data.shape[1] == shape_before_clearing[1]) # Ensure there are no more NaNs. assert(not pd.isnull(self.stock.data.iloc[0]['sma3']))
def get_stock_stats(db: Session, stock: models.Stock) -> schemas.StockResponse: stock.highest_price_today = db.query(func.max( models.StockLog.price)).filter( models.StockLog.stock_id == stock.stock_id, models.StockLog.timestamp.between(date.today(), date.today() + timedelta(days=1))).one()[0] stock.lowest_price_today = db.query(func.min( models.StockLog.price)).filter( models.StockLog.stock_id == stock.stock_id, models.StockLog.timestamp.between(date.today(), date.today() + timedelta(days=1))).one()[0] return stock
def item_stock(item_id): item = Item.query.get(item_id) if 'stock' not in request.form or request.form['stock'] not in ['0', '1']: return jsonify({'success': False, 'message': u'参数错误'}) if not item or item.is_deleted or item.vendor_id != current_user.vendor.id: return jsonify({'success': False, 'message': u'无此商品'}) stock = Stock.query.filter_by(item_id=item_id, distributor_id=current_user.id).first() if stock is None: stock = Stock(item.id, current_user.id, request.form['stock']) else: stock.stock = request.form['stock'] db.session.add(stock) db.session.commit() return jsonify({'success': True})
def review_pass(stock_id): if stock_id: session = base.DBSession() review_stock = session.query(Stock_apply).filter( Stock_apply.id == stock_id).first() if review_pass: stock_name = review_stock.stock_name user_id = review_stock.user_id sub = Stock(name=review_stock.stock_name, cover=review_stock.cover, introduction=review_stock.introduction) session.add(sub) session.delete(review_stock) session.commit() # 用户增加股票 stock = session.query(Stock).filter( Stock.name == stock_name).first() sub = Bank(user_id=user_id, stock_id=stock.id, stock_number=1000) session.add(sub) session.commit() return "成功" else: raise ValueError else: raise ValueError
def test_find_sell_stocks(self): ''' Stock.find_sell_stocks() should only return Stock IDs with 2 or more non-expired signals (this will probably change later) ''' signal_1, signal_2, signal_3, signal_4 = Signal(), Signal(), Signal(), Signal() # Signal 1 should qualify signal_1.expiration_date = dt.date.today() + dt.timedelta(days=1) signal_1.is_buy_signal = False # Signal 2 should qualify signal_2.expiration_date = dt.date.today() signal_2.is_buy_signal = False # Signal 3 should not qualify since it's not a sell signal signal_3.expiration_date = dt.date.today() signal_3.is_buy_signal = True # Signal 4 should not qualify since it's expired signal_4.expiration_date = dt.date.today() - dt.timedelta(days=1) signal_4.is_buy_signal = False self.stock.signals.append(signal_1) self.stock.signals.append(signal_2) self.stock.signals.append(signal_3) self.stock.signals.append(signal_4) db.session.add(self.stock) # add a second stock to ensure everything isn't picked up stock_2 = SF.build_stock("GOOG","Google Inc.") db.session.add(stock_2) db.session.commit() # Returns a (Stock, #signals) tuple sell_list = Stock.find_sell_stocks() print sell_list assert(len(sell_list) == 1) assert(sell_list[0][0] == self.stock) assert(sell_list[0][1] == 2) # assert there are exactly 2 signals found
def handle_market_cap(request): """ Generate response to intent type MarketCapIntent with the current market cap of the ticker. :type request AlexaRequest :return: JSON response including market cap of the ticker """ ticker = request.get_slot_value(slot_name="stockTicker").upper() # Query DB for stock data company_stats = Stock.get_stats(ticker) market_cap = company_stats.get('marketcap', None) company_name = company_stats.get('companyName', ticker) if type(market_cap) is NoneType: logger.error(f"There was an error getting market capitalization for {company_name}") message = strings.INTENT_MARKET_CAP_MSG_FAIL.format(ticker) response = ResponseBuilder.create_response(request, message=message) else: message = strings.INTENT_MARKET_CAP_MSG.format(company_name, market_cap) response = ResponseBuilder.create_response(request, message=message) \ .set_session('stockTicker', ticker) reprompt_message = strings.INTENT_GENERAL_REPROMPT return response.with_reprompt(reprompt_message)
def watchListAdd(): data = request.json print(data) if data: watchList = WatchlistContent.query.filter( WatchlistContent.watchlistId == data["watchlistId"]).all() print(len(watchList)) if len(watchList) >= 10: return { "error": "You can't have more than 10 stocks in your watchlist" } stock = Stock.query.filter(Stock.ticker == data["ticker"]).first() if not stock: newStock = Stock(ticker=data['ticker']) db.session.add(newStock) db.session.commit() stock = Stock.query.filter(Stock.ticker == data["ticker"]).first() watchListItem = WatchlistContent(stockId=stock.id, watchlistId=data["watchlistId"]) db.session.add(watchListItem) db.session.commit() watchListStocks = [] watchlist = WatchlistContent.query.filter( WatchlistContent.watchlistId == data["watchlistId"]).all() if watchlist: for oneStock in watchlist: stockTicker = Stock.query.filter( Stock.id == oneStock.stockId).first() watchListStocks.append(stockTicker.ticker) return {"tickers": watchListStocks} return "error no list"
def updateStocksFromAPI(): response = requests.get(iex_api_url + '/ref-data/symbols') all_stocks = response.json() for stock in all_stocks: db_stock = Stock.query.filter_by(symbol=stock['symbol']).first() if db_stock is None: db_stock = Stock(symbol=stock['symbol'], name=stock['name'], type=stock['type'], is_enabled=stock['isEnabled']) db.session.add(db_stock) else: db_stock.name = stock['name'] db_stock.type = stock['type'] db_stock.is_enabled = stock['isEnabled'] db.session.commit()
def add_stock(): if not current_user.is_authenticated: return redirect(url_for('login')) # add stock to database # declare the product form form = StockForm(request.form) form.product.choices = [(x.id, x.name) for x in Product.query.all()] form.stocktype.choices = [(x.id, x.name) for x in Stocktype.query.all()] msg = None if request.method == 'GET': form.process() return render_template('layouts/default.html', content=render_template('pages/add-stock.html', form=form, message=msg)) # check if both http method is POST and form is valid on submit if form.validate_on_submit(): # assign form data to variables cost_price = request.form.get('cost_price', '', type=float) sell_price = request.form.get('sell_price', '', type=float) quantity = request.form.get('quantity', '', type=int) product_id = request.form.get('product', '', type=int) stocktype_id = request.form.get('stocktype', '', type=int) # see if stock entry already exists stock = Stock.query.filter_by(product_id=product_id, quantity=quantity, stocktype_id=stocktype_id).first() # if stock: flash( f'Error: A stock entry for {stock.quantity} {stock.product} already exists!' ) else: stock = Stock(cost_price, sell_price, quantity, product_id, stocktype_id) stock.save() flash( f'Stock for {stock.product.name} successfully created! Return to stock page or add another stock.' ) else: flash('I am sorry but the details you entered cannot be saved :(') # print (msg) return render_template('layouts/default.html', content=render_template('pages/add-stock.html', message=msg, form=form))
def book_in(book_id): book = Book.query.get(book_id) stock = Stock(available=True, book=book) db.session.add(stock) db.session.commit() return redirect("/books/")
def get(self, product_id): '''Get a product with its stock''' found_product = Product.get_by_id(id=product_id) if found_product: product_json = found_product.json_dump() product_json['stock'] = Stock.get_by_product(product_id=product_id) return {"message": "ok", "data": product_json}, 200 return {"message": "No product with that id"}, 404
def settings(): """Return CRUD view for User data""" (lat, lon) = (current_user.latitude, current_user.longitude) userStocks = current_user.stocks.all() stockList = [stock.symbol for stock in userStocks] userTodos = current_user.todos.all() todoList = [(todo.id, todo.todo) for todo in userTodos] userEmbeds = current_user.embeds.all() embedList = [(embed.embed, embed.name) for embed in userEmbeds] # TODO move all forms to top locationForm = LocationForm() # TODO move `if` blocks to a func if locationForm.submitLoc.data and locationForm.validate_on_submit(): current_user.set_location(locationForm.lat.data, locationForm.lon.data) db.session.commit() flash('Updated location.') return redirect('/settings') stockForm = StockForm() if stockForm.submitStock.data and stockForm.validate_on_submit(): stock = Stock(symbol=stockForm.symbol.data, author=current_user) db.session.add(stock) db.session.commit() flash('Added stock!') return redirect('/settings') todoForm = TodoForm() if todoForm.submitTodo.data and todoForm.validate_on_submit(): todo = Todo(todo=todoForm.todo.data, author=current_user) db.session.add(todo) db.session.commit() flash('Added todo!') return redirect('/settings') embedForm = EmbedForm() if embedForm.submitEmbed.data and embedForm.validate_on_submit(): embed = Embed(embed=embedForm.embed.data, name=embedForm.name.data, author=current_user) db.session.add(embed) db.session.commit() flash('Added embed!') return redirect('/settings') return render_template('settings.html', stocks=stockList, stockForm=stockForm, todoForm=todoForm, todos=todoList, embedForm=embedForm, embeds=embedList, locationForm=locationForm, lat=lat, lon=lon)
def remove_stock(component_id, comment): document = Document(datetime.utcnow(), current_user.id, 'Cписание', comment) db.session.add(document) db.session.commit() stock = Stock(document.id, component_id, 0) db.session.add(stock) db.session.commit() return redirect(url_for('stock'))
def test_add_stocks(self): # create four users u1 = User(username='******', email='*****@*****.**') u2 = User(username='******', email='*****@*****.**') u3 = User(username='******', email='*****@*****.**') u4 = User(username='******', email='*****@*****.**') db.session.add_all([u1, u2, u3, u4]) # create four stocks s1 = Stock(name="Stock1", price=500) s2 = Stock(name="Stock2", price=600) s3 = Stock(name="Stock3", price=700) db.session.add_all([s1, s2, s3]) db.session.commit() # buy the stocks u1.add_stock(s1, 10) # spend all 5000 for 10 s1 u1.add_stock(s1, -5) # sell 5 stocks to gain 2500 money u1.add_stock(s1, 10) # try to buy more stocks than money left u1.add_stock(s1, -10) # try to sell more stocks than bought u1.add_stock(s2, 2) u2.add_stock(s1) u2.add_stock(s2) u2.add_stock(s3) u2.add_stock(s1, -1) # remove the stockitem completely from tables u3.add_stock(s2, -3) # try to sell stock which in not purchased db.session.commit() u1_stocks = u1.stocks u2_stocks = u2.stocks u3_stocks = u3.stocks u1_s1_count = u1.stock_items.filter_by(stock=s1).first().quantity self.assertEqual(1300, u1.money) self.assertEqual(3700, u2.money) self.assertEqual(5000, u3.money) self.assertEqual(u1_stocks, [s1, s2]) self.assertEqual(u2_stocks, [s2, s3]) self.assertEqual(u3_stocks, []) self.assertEqual(u1_s1_count, 5)
def makeTrade(userId): if method == "POST": data = request.json timestamp = datetime.datetime.utcnow() newTrade = Trade(ticker=data["ticker"], price=data["price"], shares=round(int(data["shares"]), 2), buy=data["buy"], buyDate=timestamp, userId=userId) currentStock = Stock.query.filter( Stock.ticker == data["ticker"]).first() if not currentStock: newStock = Stock(ticker=data['ticker']) db.session.add(newStock) db.session.commit() currentStock = Stock.query.filter( Stock.ticker == data["ticker"]).first() stockId = currentStock.id currentlyOwned = Stocklist.query.filter( Stocklist.stockId == stockId).filter( Stocklist.userId == userId).first() currentShares = 0 if not currentlyOwned else float( currentlyOwned.shares) newShares = float(data["shares"]) * (1 if data["buy"] else -1) updatedShares = round((currentShares + newShares), 2) currentUser = User.query.filter(User.id == userId).first() currentBalance = float(currentUser.balance) cost = round((float(data["shares"]) * float(data["price"])) * (1 if data["buy"] else -1), 2) updatedBalance = round((currentBalance - cost), 2) if updatedShares < 0: return {"error": "You can't have negative shares"} if updatedBalance < 0: return {"error": "You can't have a negative balance"} if currentlyOwned: currentlyOwned.shares = updatedShares else: currentlyOwned = Stocklist(stockId=stockId, userId=userId, shares=updatedShares) currentUser.balance = updatedBalance db.session.add(newTrade) db.session.add(currentlyOwned) db.session.add(currentUser) db.session.commit() all_stocks = Stocklist.query.filter(Stocklist.userId == userId).all() # return in format {ticker: shares} return { "stocks": list({ Stock.query.filter(Stock.id == stock.stockId).first().ticker: str(stock.shares) } for stock in all_stocks) }
def post(self): '''Add stock.Admin only''' parser = reqparse.RequestParser() parser.add_argument('product_id', help='The product_id field cannot be blank', required=True, type=int) parser.add_argument('quantity', help='The quantity field cannot be blank', required=True, type=int) data = parser.parse_args() new_stock = Stock(id=None, product_id=data['product_id'], quantity=data['quantity'], available=True) new_stock.save() return {"message": "stock added"}, 201
def add_stock(a): name = a desc = get_company_profile(a) features, labels, feature_list = get_feature(a) daytrend, predictions, test_labels = predict_rf(features, labels, feature_list) stock = Stock(stockname=name, description=desc, daytrend=daytrend) db.session.add(stock) db.session.commit() print('sucess')
def buy(): form = BuyForm() if form.validate_on_submit(): query_symbol = form.symbol.data query_quantity = form.shares.data share = get_quote(query_symbol) buy_price = float(share['price']) transaction_value = buy_price * query_quantity if transaction_value > current_user.cash: flash('Not enough cash to proceed with the purchase') return redirect(url_for('main_bp.quote')) owned_stock = Stock.is_owned(query_symbol, current_user) if owned_stock: owned_stock.shares += query_quantity else: stock = Stock(symbol=query_symbol, shares=query_quantity, buy_price=buy_price, owner=current_user) db.session.add(stock) current_user.cash -= transaction_value db.session.commit() transaction = Transaction(user_id=current_user.id, stock_id=Stock.is_owned( query_symbol, current_user).id, buy_price=buy_price, shares=query_quantity) db.session.add(transaction) db.session.commit() flash( f"You bought {query_quantity} {query_symbol} shares at £ {buy_price:0.2f} each" ) return redirect(url_for('main_bp.index')) flash('Something went wrong, please try again') return redirect(url_for('main_bp.quote'))
def _get_stocks(ticker_list): stocks = [] for ticker in ticker_list: data = Stock.get_last(ticker) if data is None: logger.error( f"Watchlist contains unknown stock ticker: " + str(ticker)) raise UnknownStockError(ticker) stocks.append(data) return stocks
def test_inventory_model(self): """ Test number of records in Inventory table """ # create test stock inventory = Stock(id=0, name="RCM", quantity=10, expiry_date=date(2002, 12, 31)) # save stock to database db.session.add(inventory) db.session.commit() self.assertEqual(Stock.query.count(), 1)
def add_stock(): response = requests.get('https://api.sportsdata.io/v3/nfl/scores/json/Players?key=eaf6aafbc0734ec7bc6e91b70072cd58') players = response.json() for player in players: myplayer = Stock( id=player['PlayerID'], name=player['Name'], team=player['Team'], position=player['Position'], age=player['Age'], experience=player['Experience'], jersey=player['Number'], photoURL=player['PhotoUrl'], initialVal=5 ) db.session.add(myplayer) db.session.commit()
def add_stock(): #Add stock if current_user.role < 3 or current_user.is_anonymous: #None return abort(404) #add_stock.html global last_stock_mail #Allows the owner to add or subtract stock to an item form = AddStockForm() if form.validate_on_submit(): try: stock = Stock.query.filter_by(item_id=form.id.data, colour=form.colour.data).first() stock.quantity += form.stock.data if stock.quantity < 0: flash("You cannot have fewer tha 0") return redirect(url_for("add_stock")) except: if len(Shop.query.filter_by(id=form.id.data).all()) != 0: stock_quantity = form.stock.data new_stock = Stock(colour=form.colour.data, item_id=form.id.data, quantity=stock_quantity) db.session.add(new_stock) else: flash("There is no item with that ID") return redirect(url_for("add_stock")) if stock.quantity <= 5 and last_stock_mail != datetime.now().date(): msg = "Please order more of item " + str( stock.item_id) + " in " + (stock.colour) Config.server.sendmail("*****@*****.**", "*****@*****.**", msg) last_stock_mail = datetime.now().date() db.session.commit() return redirect(url_for("add_stock")) item_stock = {} #id,colour--id, name, colour, stock shop = Shop.query.all() stock = Stock.query.all() for item in shop: tem_sto = Stock.query.filter_by(item_id=item.id).all() for s in tem_sto: item_stock[str(item.id) + str(s.colour)] = [ item.id, item.item_name, s.colour, s.quantity ] return render_template("add_stock.html", quest_answ=quest_answ, title="Add stock", form=form, item_stock=item_stock)
def manage_stock(): if not current_user.is_administrator: return render_template('error/401.html') form = AddStock() if form.validate_on_submit(): stock = Stock(room_id=int(t + random.randint(0, 10)), rest_num=form.rest_num.data, full_num=form.full_num.data) db.session.add(stock) db.session.commit() flash('仓库注册成功') return render_template('stock/stock.html', form=form, stocks=db.session.query(Stock.room_id, Stock.rest_num, Stock.full_num))
def debug_portfolios(): try: data = helpers.ws_get_positions() portfolios = {} for key, entry in data.items(): # POSITION HANDLING --------------------------------------- if entry["account_id"] not in portfolios.keys(): port = Portfolio(entry["account_id"]) portfolios.update({entry["account_id"]: port}) else: port = portfolios[entry["account_id"]] port.positions.append(Stock(entry)) portfolio_dicts = [p.to_dict() for k, p in portfolios.items()] response = jsonify(portfolio_dicts) response.headers.add('Access-Control-Allow-Origin', '*') return response except Exception as e: return Markup(str(e))
def stock(): for item in current_user.get_added(): db.session.delete(item) current_user.added.remove(item) db.session.commit() stock_db = list(set(db.session.query(Stock.component_id).all())) stock = [] print(stock_db) for item in stock_db: stock.append(Stock.query.filter(Stock.component_id == item[0]).first()) print(stock) form = SpecificationForm() if request.method == 'POST': if form.count.data is None: flash('Используйте "." вместо ","') return redirect(url_for('stock', form=form, stock=stock)) document = Document(datetime.today().strftime("%Y/%m/%d %H:%M"), current_user.id, form.document_type.data, form.text.data) db.session.add(document) db.session.commit() last_count = Stock.query.filter( Stock.component_id == form.id.data).first().get_count() stock = Stock(document.id, form.id.data, form.count.data) db.session.add(stock) db.session.commit() if form.document_type.data == 'Приход': flash('Приход {} на склад'.format(stock.get_name()), 'message') elif form.document_type.data == 'Расход': if stock.get_count() != 0 and stock.get_count() == last_count: flash( 'Расход детали {} со склада невозможен. Недостаточно деталей' .format(stock.get_name()), 'message') else: flash('Расход детали {} со склада'.format(stock.get_name()), 'message') else: flash('Деталь {} списана'.format(stock.get_name()), 'message') return redirect(url_for('stock', form=form, stock=stock)) return render_template('stock.html', form=form, stock=stock)
def getStockName(): form = StockNameForm() if form.validate_on_submit(): for name in form.stock_name.data.split(','): name = name.strip() if not Stock.query.filter_by(name=name).first(): stock = Stock(name=name) db.session.add(stock) # stocks.append(name) db.session.commit() stocks = Stock.query.all() task = get_background_price.apply_async() location_url = url_for('taskstatus', task_id=task.id) form.stock_name.data = "" return render_template('index.html', title='Stockey', stocks=stocks, form=form, location_url=location_url) return render_template('index.html', title='Stockey', form=form)
def test_get_name_and_exchange(self): name_exchange_tuple = Stock.get_name_and_exchange(self.stock) assert(name_exchange_tuple[0] == 'Apple Inc.') assert(name_exchange_tuple[1] == 'NASDAQ')
class TestStock(unittest.TestCase): def setUp(self): db.create_all() self.stock = Stock(symbol='tsla', name='Tesla Motors Inc', market='NASDAQ') def tearDown(self): db.drop_all() def test_stock_repr(self): assert(self.stock.__repr__() == "<Stock(id='None', symbol='TSLA', name='Tesla Motors Inc', market='NASDAQ')>") def test_init(self): assert(self.stock.symbol == "TSLA") assert(self.stock.name == "Tesla Motors Inc") assert(self.stock.market == "NASDAQ") def test_calculate_adjusted_ohlc(self): # 10 for 1 stock split df = SF.build_dataframe(values={'High':[20,3], 'Adj Close':[1.9,2.9], 'Close':[19,2.9]}) df = self.stock.calculate_adjusted_ohlc(df) print df assert(all([col in df.columns for col in ['Adj High', 'Adj Low', 'Adj Open']])) self.assertAlmostEqual(df['Adj High'].iloc[0], 2, 2) self.assertAlmostEqual(df['Adj High'].iloc[1], 3, 2) def test_find_buy_stocks(self): ''' Stock.find_buy_stocks() should only return Stocks with 2 or more non-expired signals (this will probably change later) ''' signal_1, signal_2, signal_3, signal_4 = Signal(), Signal(), Signal(), Signal() # Signal 1 should qualify signal_1.expiration_date = dt.date.today() + dt.timedelta(days=1) signal_1.is_buy_signal = True # Signal 2 should qualify signal_2.expiration_date = dt.date.today() signal_2.is_buy_signal = True # Signal 3 should not qualify since it's not a buy signal signal_3.expiration_date = dt.date.today() signal_3.is_buy_signal = False # Signal 3 should not qualify since it's expired signal_4.expiration_date = dt.date.today() - dt.timedelta(days=1) signal_4.is_buy_signal = True self.stock.signals.append(signal_1) self.stock.signals.append(signal_2) self.stock.signals.append(signal_3) self.stock.signals.append(signal_4) db.session.add(self.stock) # add a second stock to ensure everything isn't picked up stock_2 = SF.build_stock("GOOG","Google Inc.") db.session.add(stock_2) db.session.commit() # Returns a (Stock, #signals) tuple buy_list = Stock.find_buy_stocks() print buy_list assert(len(buy_list) == 1) assert(buy_list[0][0] == self.stock) assert(buy_list[0][1] == 2) # assert there are exactly 2 signals found def test_find_sell_stocks(self): ''' Stock.find_sell_stocks() should only return Stock IDs with 2 or more non-expired signals (this will probably change later) ''' signal_1, signal_2, signal_3, signal_4 = Signal(), Signal(), Signal(), Signal() # Signal 1 should qualify signal_1.expiration_date = dt.date.today() + dt.timedelta(days=1) signal_1.is_buy_signal = False # Signal 2 should qualify signal_2.expiration_date = dt.date.today() signal_2.is_buy_signal = False # Signal 3 should not qualify since it's not a sell signal signal_3.expiration_date = dt.date.today() signal_3.is_buy_signal = True # Signal 4 should not qualify since it's expired signal_4.expiration_date = dt.date.today() - dt.timedelta(days=1) signal_4.is_buy_signal = False self.stock.signals.append(signal_1) self.stock.signals.append(signal_2) self.stock.signals.append(signal_3) self.stock.signals.append(signal_4) db.session.add(self.stock) # add a second stock to ensure everything isn't picked up stock_2 = SF.build_stock("GOOG","Google Inc.") db.session.add(stock_2) db.session.commit() # Returns a (Stock, #signals) tuple sell_list = Stock.find_sell_stocks() print sell_list assert(len(sell_list) == 1) assert(sell_list[0][0] == self.stock) assert(sell_list[0][1] == 2) # assert there are exactly 2 signals found def test_signals_are_ordered_properly(self): ''' The first signal should be the one with the latest expiration date ''' signal_1, signal_2, signal_3 = Signal(), Signal(), Signal() signal_1.expiration_date = dt.date.today()+dt.timedelta(days=3) signal_1.is_buy_signal = True signal_2.expiration_date = dt.date.today()+dt.timedelta(days=1) signal_2.is_buy_signal = True signal_3.expiration_date = dt.date.today()+dt.timedelta(days=5) signal_3.is_buy_signal = True self.stock.signals.append(signal_1) self.stock.signals.append(signal_2) self.stock.signals.append(signal_3) db.session.add(self.stock) print self.stock.signals # signals aren't re-ordered until the commit, unless # reorder_on_append is set db.session.commit() print self.stock.signals assert(self.stock.signals[0] == signal_3) def test_save_dataframe_creates_new_stock(self): ''' When a Stock doesn't exist, a new Stock object should be created and saved. ''' assert(Stock.query.count() == 0) df = DataFrame() self.stock._save_dataframe(df) assert(Stock.query.count() == 1) def test_save_dataframe_does_not_create_new_stock(self): ''' When a Stock already exists, no new Stock object should be created. ''' df = DataFrame() assert(Stock.query.count() == 0) self.stock._save_dataframe(df) assert(Stock.query.count() == 1) self.stock._save_dataframe(df) assert(Stock.query.count() == 1) def test_load_dataframe_from_db(self): ''' When loading a dataframe, all fields our model knows about should be loaded, including RSI/MACD/moving averages, etc. ''' today = dt.date.today() self.stock.stockpoints.append(StockPoint(today, 1.5, 3.17, 1.21, 1.76, 1.76, 123456, 30.14, 1.21, macd_signal=None, adj_open=1.25, adj_high=1.33, adj_low=1.45, high_52_weeks=1, low_52_weeks=1)) db.session.add(self.stock) db.session.commit() df = self.stock.load_dataframe_from_db() print df assert(df.loc[today]['Open'] == 1.5) assert(df.loc[today]['High'] == 3.17) assert(df.loc[today]['Low'] == 1.21) assert(df.loc[today]['Close'] == 1.76) assert(df.loc[today]['Adj Close'] == 1.76) assert(df.loc[today]['Volume'] == 123456) assert(df.loc[today]['RSI'] == 30.14) assert(df.loc[today]['MACD'] == 1.21) assert(pd.isnull((df.loc[today]['MACD-Signal']))) assert(df.loc[today]['Adj Open'] == 1.25) assert(df.loc[today]['Adj High'] == 1.33) assert(df.loc[today]['Adj Low'] == 1.45) assert(df.loc[today]['52-Week-High'] == 1) assert(df.loc[today]['52-Week-Low'] == 1) @patch('app.models.Stock.fetch_ohlc_from_yahoo') def test_fetch_all_ohlc_from_yahoo(self,mock_fetch): df = self.stock.fetch_and_save_all_ohlc() end = dt.date.today() start = end - dt.timedelta(Stock.LOOKBACK_DAYS) mock_fetch.assert_called_with(start,end) @patch('app.models.DataReader') def test_fetch_ohlc_from_yahoo(self, MockDataReader): end = dt.date.today() start = end - dt.timedelta(days=1) df = self.stock.fetch_ohlc_from_yahoo(start, end) MockDataReader.assert_called_with("TSLA","yahoo",start,end) @patch('app.models.today') def test_should_fetch_should_fetch(self, mock_today): ''' _should_fetch should return True if there's a weekday between the last point date and today ''' mock_today.return_value = dt.date(2014,11,22) df = SF.build_dataframe(end_date=dt.date(2014,11,20)) self.stock._save_dataframe(df) assert(self.stock._should_fetch() == True) @patch('app.models.today') def test_should_fetch_should_not_fetch(self, mock_today): ''' _should_fetch should return False if there are only weekend days between the last point date and today ''' mock_today.return_value = dt.date(2014,11,24) df = SF.build_dataframe(end_date=dt.date(2014,11,21)) self.stock._save_dataframe(df) assert(self.stock._should_fetch() == False) @patch('app.models.today') @patch('app.models.Stock.fetch_ohlc_from_yahoo') def test_fetch_and_save_missing_ohlc(self, mock_fetch, mock_today): mock_today.return_value = dt.date(2014,10,10) df = SF.build_dataframe(end_date=dt.date(2014,10,7)) self.stock._save_dataframe(df) self.stock.fetch_and_save_missing_ohlc() date3 = dt.date(2014,10,8) date4 = dt.date(2014,10,9) mock_fetch.assert_called_with(date3, date4) @patch('app.models.Stock.fetch_and_save_missing_ohlc') @patch('app.models.Stock.fetch_and_save_all_ohlc') def test_get_dataframe(self, mock_fetch_all, mock_fetch_missing): db.session.add(self.stock) db.session.commit() self.stock.get_dataframe() assert(mock_fetch_all.called) self.stock.stockpoints.append(StockPoint(date=dt.date.today(), open=1,high=2,low=1,close=1, adj_close=1,volume=1)) db.session.add(self.stock) db.session.commit() self.stock.get_dataframe() assert(mock_fetch_missing.called) @patch('app.models.DataReader') def test_fetch_ohlc_from_yahoo_fails_gracefully_with_invalid_stock(self, mockDataReader): mockDataReader.side_effect = IOError # raised when symbol isn't found self.stock.symbol = 'This is an invalid symbol' start = end = dt.date.today() - dt.timedelta(days=1) df = self.stock.fetch_ohlc_from_yahoo(start,end) assert(df is None) def test_saving_bad_df_to_database(self): ''' Should only save the two points with valid data ''' assert(StockPoint.query.count() == 0) df = SF.build_dataframe(values={'Open':['-',1,2]}) self.stock._save_dataframe(df) print df assert(StockPoint.query.count() == 2) def test_update_dataframe(self): ''' Should update the RSI, MACD, MACD-Signal, SMAs, and Adj values ''' df = SF.build_dataframe(values={'RSI':[1],'MACD':[2],'MACD-Signal':[3], 'Adj Open':[1.25],'Adj High':[1.33], 'Adj Low':[1.45], '52-Week-High':[3], '52-Week-Low':[3],'SMA-50':[5], 'SMA-200':[5]}) self.stock._save_dataframe(df) for index,col in enumerate("""RSI|MACD|MACD-Signal|SMA-50|SMA-200|Adj Open|Adj High|Adj Low|52-Week-High|52-Week-Low""".split('|')): df.ix[0,col] = index self.stock.update_dataframe(df) print self.stock.stockpoints[0] assert(self.stock.stockpoints[0].rsi == 0) assert(self.stock.stockpoints[0].macd == 1) assert(self.stock.stockpoints[0].macd_signal == 2) assert(self.stock.stockpoints[0].sma_50 == 3) assert(self.stock.stockpoints[0].sma_200 == 4) assert(self.stock.stockpoints[0].adj_open == 5) assert(self.stock.stockpoints[0].adj_high == 6) assert(self.stock.stockpoints[0].adj_low == 7) assert(self.stock.stockpoints[0].high_52_weeks == 8) assert(self.stock.stockpoints[0].low_52_weeks == 9)
def setUp(self): db.create_all() self.stock = Stock(symbol='tsla', name='Tesla Motors Inc', market='NASDAQ')
def test_set_data(self, patched_DataReader): num_days = 2 * 365 Stock.set_data(self.stock, num_days) end = datetime.date.today() start = end - datetime.timedelta(days = num_days + 365) patched_DataReader.assert_called_with('AAPL', 'yahoo', start, end)