- Add `get_fx_rate()` function with caching to fetch foreign exchange rates from open.er-api.com - Introduce `get_currency()` helper to map market codes to currency identifiers - Update price parsing regex to support multiple currency symbols (£, $, €) - Convert shares to float to accommodate fractional holdings - Add currency, fx_rate, and total_value_gbp fields to output JSON - Support fractional share counts (e.g., 3.6185 AAPL shares)
67 lines
1.9 KiB
Python
67 lines
1.9 KiB
Python
import re
|
|
import json
|
|
import csv
|
|
import sys
|
|
import requests
|
|
from bs4 import BeautifulSoup
|
|
|
|
FX_CACHE = {}
|
|
|
|
def get_fx_rate(currency):
|
|
if currency in FX_CACHE:
|
|
return FX_CACHE[currency]
|
|
if currency == "GBP":
|
|
return 1.0
|
|
url = f"https://open.er-api.com/v6/latest/{currency}"
|
|
r = requests.get(url, timeout=20)
|
|
rate = r.json()["rates"]["GBP"]
|
|
FX_CACHE[currency] = rate
|
|
return rate
|
|
|
|
def get_price(market, ticker):
|
|
url = f"https://web.freetrade.io/universe/{market}/{ticker}"
|
|
response = requests.get(url, headers={
|
|
"User-Agent": "Mozilla/5.0"
|
|
}, timeout=20)
|
|
text = BeautifulSoup(response.text, "html.parser").get_text(" ", strip=True)
|
|
m = re.search(r"Latest price\s*:\s*[£$€]([0-9,.]+)", text)
|
|
if m:
|
|
return float(m.group(1).replace(",", ""))
|
|
return None
|
|
|
|
def get_currency(market):
|
|
return {"GB": "GBP", "US": "USD"}.get(market, "GBP")
|
|
|
|
holdings_file = sys.argv[1] if len(sys.argv) > 1 else "holdings.csv"
|
|
|
|
results = []
|
|
with open(holdings_file) as f:
|
|
reader = csv.reader(f)
|
|
for row in reader:
|
|
ticker, market, shares = row[0].strip(), row[1].strip(), float(row[2].strip())
|
|
currency = get_currency(market)
|
|
price = get_price(market, ticker)
|
|
if price is None:
|
|
results.append({
|
|
"ticker": ticker,
|
|
"market": market,
|
|
"currency": currency,
|
|
"shares": shares,
|
|
"price": None,
|
|
"fx_rate": None,
|
|
"total_value_gbp": None
|
|
})
|
|
continue
|
|
fx = get_fx_rate(currency)
|
|
total_gbp = round(price * shares * fx, 2)
|
|
results.append({
|
|
"ticker": ticker,
|
|
"market": market,
|
|
"currency": currency,
|
|
"shares": shares,
|
|
"price": price,
|
|
"fx_rate": fx,
|
|
"total_value_gbp": total_gbp
|
|
})
|
|
|
|
print(json.dumps(results, indent=2)) |