Files
historical-prices/app.py
T

87 lines
3.0 KiB
Python

from flask import Flask, render_template, jsonify
from datetime import datetime, timedelta
from engine import DataEngine
import concurrent.futures
from flask_caching import Cache
import csv, os, logging
app = Flask(__name__)
cache = Cache(app, config={'CACHE_TYPE': 'SimpleCache'})
import os
import csv
def load_instruments_from_csv(file_path):
instruments = []
# Standard static templates
# For AGI, we use the ISIN-based Tearsheet URL
TEMPLATES = {
'jpm': "https://am.jpmorgan.com/FundsMarketingHandler/historicalData?cusip={cusip}&country=hk&role=per",
'yahoo': "https://query1.finance.yahoo.com/v8/finance/chart/{cusip}?range=5y&interval=1d",
'agi': "https://markets.ft.com/data/funds/tearsheet/historical?s={cusip}"
}
try:
abs_path = os.path.join(os.path.dirname(__file__), file_path)
if not os.path.exists(abs_path):
print(f"Error: {file_path} not found.")
return []
with open(abs_path, mode='r', encoding='utf-8-sig') as csvfile:
reader = csv.DictReader(csvfile)
# Standardize header names to lowercase
reader.fieldnames = [name.strip().lower() for name in reader.fieldnames]
for row in reader:
symbol = row.get('symbol', '').strip()
cusip = row.get('cusip', '').strip()
provider = row.get('provider', 'jpm').strip().lower()
if symbol and cusip:
# Fetch correct template; default to JPM if provider is unknown
template = TEMPLATES.get(provider, TEMPLATES['jpm'])
url = template.format(cusip=cusip)
instruments.append({
"symbol": symbol,
"url": url,
"provider": provider
})
except Exception as e:
print(f"CSV Loading Error: {e}")
return instruments
# Usage
URL_CONFIG = load_instruments_from_csv('instruments.csv')
@cache.memoize(timeout=3600)
def fetch_and_calculate(config):
engine = DataEngine(config['symbol'], config['url'], config['provider'])
df = engine.fetch_data()
if df is not None:
metrics = engine.calculate_table_metrics(df)
if metrics:
metrics['symbol'] = config['symbol']
return metrics
return None
@app.route('/')
def index():
return render_template('index.html')
@app.route('/api/summary')
def get_summary():
results = []
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
futures = [executor.submit(fetch_and_calculate, cfg) for cfg in URL_CONFIG]
for f in concurrent.futures.as_completed(futures):
if f.result(): results.append(f.result())
results.sort(key=lambda x: x['symbol'])
return jsonify(results)
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=5000)