From 36cf5627db8c2c49d7ffe1ea42fd4ab17cee92ce Mon Sep 17 00:00:00 2001 From: gord chung Date: Tue, 12 Dec 2023 15:30:32 -0500 Subject: [PATCH] page to interact with financial data - add an extension to reuse request session across flask --- app/api/root.py | 5 ++ app/api/v1/data.py | 36 +++++++++++ app/app.py | 3 +- app/extensions.py | 21 +++++++ app/templates/analytics.html | 87 +++++++++++++------------- app/templates/yahoo.html | 114 +++++++++++++++++++++++++++++++++++ 6 files changed, 220 insertions(+), 46 deletions(-) create mode 100644 app/templates/yahoo.html diff --git a/app/api/root.py b/app/api/root.py index 6927e46..72a7245 100644 --- a/app/api/root.py +++ b/app/api/root.py @@ -16,6 +16,11 @@ def analytics(): return flask.render_template("analytics.html") +@bp.get('/yahoo') +def yahoo(): + return flask.render_template("yahoo.html") + + @bp.get('/logout') def logout(): logout_user() diff --git a/app/api/v1/data.py b/app/api/v1/data.py index b3227e0..d1a114b 100644 --- a/app/api/v1/data.py +++ b/app/api/v1/data.py @@ -1,3 +1,4 @@ +import datetime import json import flask @@ -7,6 +8,7 @@ import numpy as np from app.api.v1 import bp +from app.extensions import reqs @bp.get('/data/random') @@ -65,6 +67,7 @@ def death_data(): return """ """ % (data['data'], col_props) return data + + +USER_AGENT_HEADERS = { + # required or yahoo will block + 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) ' + 'AppleWebKit/537.36 (KHTML, like Gecko) ' + 'Chrome/39.0.2171.95 Safari/537.36' +} + + +@bp.get('/data/market/prices') +def get_prices(): + ticker = request.args['ticker'] + interval = request.args.get('interval', '1d') + start = request.args.get('start', int(datetime.datetime(2023, 1, 1).timestamp())) + stop = request.args.get('stop', int(datetime.datetime.now().timestamp())) + events = request.args.get('events', 'capitalGain|div|split') + res = reqs.session.get( + f'https://query2.finance.yahoo.com/v8/finance/chart/{ticker}', + headers=USER_AGENT_HEADERS, + params={'interval': interval, 'events': events, + 'period1': start, 'period2': stop}) + data = res.json()['chart']['result'][0] + data['timestamp'] = np.datetime_as_string( + np.asarray(data['timestamp'], dtype='datetime64[s]'), unit='D').tolist() + if request.headers.get('Hx-Request'): + resp = flask.Response() + resp = flask.Response( + '' % (json.dumps(data))) + resp.headers['HX-Trigger-After-Swap'] = json.dumps( + {'displayPrices': {'target': 'priceChart', 'dataId': 'priceData'}}) + return resp + return data diff --git a/app/app.py b/app/app.py index f7af550..b3f8a1d 100644 --- a/app/app.py +++ b/app/app.py @@ -6,7 +6,7 @@ from app import config from app.cli import show from app.core.security import RegisterForm -from app.extensions import csrf, migrate, security +from app.extensions import csrf, migrate, reqs, security from app.models import auth as models from app.storage.db import db @@ -23,6 +23,7 @@ def create_app(conf=None): else: app.config.from_object(conf) + reqs.init_app(app) db.init_app(app) migrate.init_app(app, db) user_datastore = SQLAlchemyUserDatastore(db, models.User, models.Role) diff --git a/app/extensions.py b/app/extensions.py index 0633251..55edb71 100644 --- a/app/extensions.py +++ b/app/extensions.py @@ -1,8 +1,29 @@ +from flask import Flask from flask_migrate import Migrate from flask_security import Security from flask_wtf import CSRFProtect +import requests + + +class Requests: + """create request session for reuse across appcontext""" + + def __init__(self, app: Flask = None): + # alternatively, https://flask.palletsprojects.com/en/2.3.x/appcontext/#storing-data + self.app = app + self.session = requests.Session() + + if self.app is not None: + self.init_app(app) + + def init_app(self, app: Flask): + app.teardown_appcontext(self.teardown) + + def teardown(self, exc: BaseException | None): + self.session.close() migrate = Migrate() security = Security() csrf = CSRFProtect() +reqs = Requests() diff --git a/app/templates/analytics.html b/app/templates/analytics.html index bd6d406..36474b1 100644 --- a/app/templates/analytics.html +++ b/app/templates/analytics.html @@ -62,58 +62,55 @@

{% endblock %} diff --git a/app/templates/yahoo.html b/app/templates/yahoo.html new file mode 100644 index 0000000..98638cf --- /dev/null +++ b/app/templates/yahoo.html @@ -0,0 +1,114 @@ +{% extends "base.html" %} +{% block title %}finance{% endblock %} +{% block head_css %} + +{% endblock %} +{% block head_scripts %} + + + +{% endblock %} +{% block body %} +
+
+

+ Finance +

+
+
+
+
+ +
+
+ +
+
+
+ +
+
+
+
+
+
+
+ + +{% endblock %}