Final Verion of Stock WebService
This commit is contained in:
parent
091b2f3502
commit
79029bdcd9
1 changed files with 12 additions and 17 deletions
|
|
@ -12,7 +12,7 @@ app = Flask(__name__)
|
||||||
# ---- Config ----
|
# ---- Config ----
|
||||||
SHARED_SECRET = os.environ.get("PROXY_SECRET", "")
|
SHARED_SECRET = os.environ.get("PROXY_SECRET", "")
|
||||||
DB_PATH = os.environ.get("DB_PATH", "/data/cache.db")
|
DB_PATH = os.environ.get("DB_PATH", "/data/cache.db")
|
||||||
CURRENT_TTL_SECONDS = 15 * 60 # re-check "today" every 15 min in case NAV just>
|
CURRENT_TTL_SECONDS = 15 * 60 # re-check "today" every 15 min in case NAV just posted
|
||||||
|
|
||||||
_db_lock = threading.Lock()
|
_db_lock = threading.Lock()
|
||||||
|
|
||||||
|
|
@ -32,12 +32,6 @@ def get_db():
|
||||||
_current_cache = {} # ticker -> (price, resolved_date, fetched_at)
|
_current_cache = {} # ticker -> (price, resolved_date, fetched_at)
|
||||||
_current_cache_lock = threading.Lock()
|
_current_cache_lock = threading.Lock()
|
||||||
|
|
||||||
@app.after_request
|
|
||||||
def add_cors_headers(response):
|
|
||||||
response.headers["Access-Control-Allow-Origin"] = "*"
|
|
||||||
response.headers["Access-Control-Allow-Methods"] = "GET, OPTIONS"
|
|
||||||
response.headers["Access-Control-Allow-Headers"] = "Content-Type"
|
|
||||||
return response
|
|
||||||
|
|
||||||
def check_auth():
|
def check_auth():
|
||||||
key = request.args.get("key", "")
|
key = request.args.get("key", "")
|
||||||
|
|
@ -50,8 +44,8 @@ def fetch_yahoo_price(ticker, target_date):
|
||||||
period1 = int((target_date - timedelta(days=10)).timestamp())
|
period1 = int((target_date - timedelta(days=10)).timestamp())
|
||||||
|
|
||||||
url = f"https://query1.finance.yahoo.com/v8/finance/chart/{ticker}"
|
url = f"https://query1.finance.yahoo.com/v8/finance/chart/{ticker}"
|
||||||
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWe>
|
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"}
|
||||||
r = requests.get(url, params={"period1": period1, "period2": period2, "inte>
|
r = requests.get(url, params={"period1": period1, "period2": period2, "interval": "1d"}, headers=headers, timeout=10)
|
||||||
|
|
||||||
if r.status_code != 200:
|
if r.status_code != 200:
|
||||||
return None, f"yahoo http {r.status_code}"
|
return None, f"yahoo http {r.status_code}"
|
||||||
|
|
@ -76,7 +70,7 @@ def fetch_yahoo_price(ticker, target_date):
|
||||||
if best is None:
|
if best is None:
|
||||||
return None, "no trading day found in window"
|
return None, "no trading day found in window"
|
||||||
|
|
||||||
return {"resolved_date": best[0].strftime("%Y-%m-%d"), "price": round(best[>
|
return {"resolved_date": best[0].strftime("%Y-%m-%d"), "price": round(best[1], 4)}, None
|
||||||
|
|
||||||
|
|
||||||
@app.route("/current")
|
@app.route("/current")
|
||||||
|
|
@ -92,7 +86,7 @@ def current_price():
|
||||||
with _current_cache_lock:
|
with _current_cache_lock:
|
||||||
cached = _current_cache.get(ticker)
|
cached = _current_cache.get(ticker)
|
||||||
if cached and (now - cached[2]) < CURRENT_TTL_SECONDS:
|
if cached and (now - cached[2]) < CURRENT_TTL_SECONDS:
|
||||||
return jsonify({"ticker": ticker, "price": cached[0], "resolved_dat>
|
return jsonify({"ticker": ticker, "price": cached[0], "resolved_date": cached[1], "cached": True})
|
||||||
|
|
||||||
result, err = fetch_yahoo_price(ticker, datetime.utcnow())
|
result, err = fetch_yahoo_price(ticker, datetime.utcnow())
|
||||||
if err:
|
if err:
|
||||||
|
|
@ -101,7 +95,8 @@ def current_price():
|
||||||
with _current_cache_lock:
|
with _current_cache_lock:
|
||||||
_current_cache[ticker] = (result["price"], result["resolved_date"], now)
|
_current_cache[ticker] = (result["price"], result["resolved_date"], now)
|
||||||
|
|
||||||
return jsonify({"ticker": ticker, "price": result["price"], "resolved_date">
|
return jsonify({"ticker": ticker, "price": result["price"], "resolved_date": result["resolved_date"], "cached": False})
|
||||||
|
|
||||||
|
|
||||||
@app.route("/historical")
|
@app.route("/historical")
|
||||||
def historical_price():
|
def historical_price():
|
||||||
|
|
@ -118,20 +113,20 @@ def historical_price():
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return jsonify({"error": "date must be YYYY-MM-DD"}), 400
|
return jsonify({"error": "date must be YYYY-MM-DD"}), 400
|
||||||
|
|
||||||
# If someone asks "historical" for today/future, treat it like /current ins>
|
# If someone asks "historical" for today/future, treat it like /current instead
|
||||||
if target_date.date() >= datetime.utcnow().date():
|
if target_date.date() >= datetime.utcnow().date():
|
||||||
return current_price()
|
return current_price()
|
||||||
|
|
||||||
with _db_lock:
|
with _db_lock:
|
||||||
conn = get_db()
|
conn = get_db()
|
||||||
row = conn.execute(
|
row = conn.execute(
|
||||||
"SELECT resolved_date, price FROM historical_cache WHERE ticker=? A>
|
"SELECT resolved_date, price FROM historical_cache WHERE ticker=? AND requested_date=?",
|
||||||
(ticker, date_str),
|
(ticker, date_str),
|
||||||
).fetchone()
|
).fetchone()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
if row:
|
if row:
|
||||||
return jsonify({"ticker": ticker, "requested_date": date_str, "resolved>
|
return jsonify({"ticker": ticker, "requested_date": date_str, "resolved_date": row[0], "price": row[1], "cached": True})
|
||||||
|
|
||||||
result, err = fetch_yahoo_price(ticker, target_date)
|
result, err = fetch_yahoo_price(ticker, target_date)
|
||||||
if err:
|
if err:
|
||||||
|
|
@ -140,13 +135,13 @@ def historical_price():
|
||||||
with _db_lock:
|
with _db_lock:
|
||||||
conn = get_db()
|
conn = get_db()
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"INSERT OR REPLACE INTO historical_cache (ticker, requested_date, r>
|
"INSERT OR REPLACE INTO historical_cache (ticker, requested_date, resolved_date, price) VALUES (?, ?, ?, ?)",
|
||||||
(ticker, date_str, result["resolved_date"], result["price"]),
|
(ticker, date_str, result["resolved_date"], result["price"]),
|
||||||
)
|
)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
return jsonify({"ticker": ticker, "requested_date": date_str, "resolved_dat>
|
return jsonify({"ticker": ticker, "requested_date": date_str, "resolved_date": result["resolved_date"], "price": result["price"], "cached": False})
|
||||||
|
|
||||||
|
|
||||||
@app.route("/health")
|
@app.route("/health")
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue