From 64ff6796ad311385ce5c16c4a0488ea9ee758db2 Mon Sep 17 00:00:00 2001 From: Bram Date: Mon, 20 Apr 2026 14:30:57 +0200 Subject: [PATCH] aandelen watcher --- Dockers/aandelen-watcher-bas/.dockerignore | 13 + Dockers/aandelen-watcher-bas/.env.example | 11 + Dockers/aandelen-watcher-bas/Dockerfile | 19 + Dockers/aandelen-watcher-bas/aandelen.py | 380 ++++++++++++++++++ .../aandelen-watcher-bas/docker-compose.yml | 17 + Dockers/aandelen-watcher-bas/requirements.txt | 3 + Dockers/aandelen-watcher-bas/version | 1 + .../watchlist.json.example | 5 + 8 files changed, 449 insertions(+) create mode 100644 Dockers/aandelen-watcher-bas/.dockerignore create mode 100644 Dockers/aandelen-watcher-bas/.env.example create mode 100644 Dockers/aandelen-watcher-bas/Dockerfile create mode 100644 Dockers/aandelen-watcher-bas/aandelen.py create mode 100644 Dockers/aandelen-watcher-bas/docker-compose.yml create mode 100644 Dockers/aandelen-watcher-bas/requirements.txt create mode 100644 Dockers/aandelen-watcher-bas/version create mode 100644 Dockers/aandelen-watcher-bas/watchlist.json.example diff --git a/Dockers/aandelen-watcher-bas/.dockerignore b/Dockers/aandelen-watcher-bas/.dockerignore new file mode 100644 index 0000000..fda018f --- /dev/null +++ b/Dockers/aandelen-watcher-bas/.dockerignore @@ -0,0 +1,13 @@ +__pycache__/ +*.pyc +*.pyo +*.pyd +.Python +*.log +.env +.venv/ +venv/ +env/ +.git/ +.idea/ +.vscode/ diff --git a/Dockers/aandelen-watcher-bas/.env.example b/Dockers/aandelen-watcher-bas/.env.example new file mode 100644 index 0000000..3987473 --- /dev/null +++ b/Dockers/aandelen-watcher-bas/.env.example @@ -0,0 +1,11 @@ +# Kopieer naar .env en vul de waarden in. +GROQ_API_KEY= +GMAIL_ADRES= +GMAIL_APP_WACHTWOORD= +ONTVANGER= + +# Optioneel +VERSTUUR_OM=08:00 + +# Optioneel: mount een JSON file naar /data/watchlist.json (zie docker-compose.yml) +# WATCHLIST_FILE=/data/watchlist.json diff --git a/Dockers/aandelen-watcher-bas/Dockerfile b/Dockers/aandelen-watcher-bas/Dockerfile new file mode 100644 index 0000000..c216627 --- /dev/null +++ b/Dockers/aandelen-watcher-bas/Dockerfile @@ -0,0 +1,19 @@ +FROM python:3.12-slim + +ENV PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 + +WORKDIR /app + +RUN apt-get update \ + && apt-get install -y --no-install-recommends tzdata ca-certificates \ + && rm -rf /var/lib/apt/lists/* + +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +RUN mkdir -p /data + +COPY aandelen.py . + +CMD ["python", "aandelen.py"] diff --git a/Dockers/aandelen-watcher-bas/aandelen.py b/Dockers/aandelen-watcher-bas/aandelen.py new file mode 100644 index 0000000..12d7f6c --- /dev/null +++ b/Dockers/aandelen-watcher-bas/aandelen.py @@ -0,0 +1,380 @@ +""" +๐Ÿ“ฐ Aandelen Nieuwsbrief via AI + E-mail (Groq - gratis) +--------------------------------------------------------- +Haalt elke ochtend om 8u nieuws op over je aandelen, +laat AI een samenvatting maken via Groq, en stuurt dit per mail. +Toont ook het analistenadvies, de P/E ratio, en 5 AI-gekozen low-risk aandelen. + +Vereisten: + pip install yfinance schedule groq + +Groq API key aanmaken (gratis): + Ga naar https://console.groq.com โ†’ "API Keys" + Plak je key hieronder bij GROQ_API_KEY +""" + +import yfinance as yf +import schedule +import time +import smtplib +import logging +import json +import os +from groq import Groq +from email.mime.text import MIMEText +from email.mime.multipart import MIMEMultipart +from datetime import datetime + +# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +# ๐Ÿ“ LOGBESTAND +# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + +logging.basicConfig( + filename=os.getenv("LOG_FILE", "/data/nieuws_log.txt"), + level=logging.INFO, + format="%(asctime)s %(message)s", + datefmt="%d/%m/%Y %H:%M:%S", + encoding="utf-8", +) + +def log(bericht: str): + logging.info(bericht) + print(bericht) + +# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +# โš™๏ธ CONFIGURATIE โ€” pas dit aan +# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + +GROQ_API_KEY = os.getenv("GROQ_API_KEY", "").strip() # verplicht +GMAIL_ADRES = os.getenv("GMAIL_ADRES", "").strip() # verplicht +GMAIL_APP_WACHTWOORD = os.getenv("GMAIL_APP_WACHTWOORD", "").strip() # verplicht (Google App Password) +ONTVANGER = os.getenv("ONTVANGER", "").strip() # verplicht + +DEFAULT_WATCHLIST = { + "HIMS": "Hims & Hers Health", + "AMD": "Advanced Micro Devices", + "AGNC": "AGNC Investment", + "TSLA": "Tesla", + "EUNL.DE": "iShares Core MSCI World ETF", + "CCEP.AS": "Coca-Cola Europacific Partners", +} + +WATCHLIST_FILE = os.getenv("WATCHLIST_FILE", "").strip() + +def _normaliseer_watchlist(data) -> dict[str, str]: + if isinstance(data, dict): + out = {} + for k, v in data.items(): + ticker = str(k).strip() + naam = str(v).strip() if v is not None else "" + if not ticker: + continue + out[ticker] = naam or ticker + return out + + if isinstance(data, list): + out = {} + for item in data: + if not isinstance(item, dict): + continue + ticker = str(item.get("ticker", "")).strip() + naam = str(item.get("naam", "")).strip() + if not ticker: + continue + out[ticker] = naam or ticker + return out + + return {} + +def laad_watchlist() -> dict[str, str]: + if not WATCHLIST_FILE: + return DEFAULT_WATCHLIST + try: + with open(WATCHLIST_FILE, "r", encoding="utf-8") as f: + data = json.load(f) + wl = _normaliseer_watchlist(data) + if wl: + return wl + log(f"โš ๏ธ WATCHLIST_FILE bevat geen geldige tickers, gebruik DEFAULT_WATCHLIST. Pad: {WATCHLIST_FILE}") + return DEFAULT_WATCHLIST + except FileNotFoundError: + log(f"โš ๏ธ WATCHLIST_FILE niet gevonden, gebruik DEFAULT_WATCHLIST. Pad: {WATCHLIST_FILE}") + return DEFAULT_WATCHLIST + except Exception as e: + log(f"โš ๏ธ Fout bij lezen WATCHLIST_FILE, gebruik DEFAULT_WATCHLIST. Pad: {WATCHLIST_FILE} fout: {e}") + return DEFAULT_WATCHLIST + +WATCHLIST = laad_watchlist() + +VERSTUUR_OM = os.getenv("VERSTUUR_OM", "08:00").strip() + +if __name__ != "__main__": + # Bij importeren (bv. tests) willen we niet hard falen op ontbrekende envs. + pass +else: + ontbrekend = [naam for naam, waarde in { + "GROQ_API_KEY": GROQ_API_KEY, + "GMAIL_ADRES": GMAIL_ADRES, + "GMAIL_APP_WACHTWOORD": GMAIL_APP_WACHTWOORD, + "ONTVANGER": ONTVANGER, + }.items() if not waarde] + if ontbrekend: + raise SystemExit( + "Ontbrekende environment variables: " + + ", ".join(ontbrekend) + + ". Zet ze in je omgeving of via docker-compose (.env)." + ) + +# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +# ๐Ÿ“Š ANALISTENADVIES +# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + +ADVIES_KLEUREN = { + "strong buy": ("#1a7a1a", "๐ŸŸข Strong Buy"), + "buy": ("#4caf50", "๐ŸŸฉ Buy"), + "hold": ("#f5a623", "๐ŸŸก Hold"), + "underperform": ("#e67e22", "๐ŸŸ  Underperform"), + "sell": ("#c0392b", "๐Ÿ”ด Sell"), + "strong sell": ("#7b0000", "๐Ÿ”ด Strong Sell"), +} + +def haal_advies_op(ticker: str) -> tuple: + try: + info = yf.Ticker(ticker).info + advies = info.get("recommendationKey", "").lower() + if advies in ADVIES_KLEUREN: + return ADVIES_KLEUREN[advies] + return ("#888888", "โšช Geen advies") + except: + return ("#888888", "โšช Niet beschikbaar") + +# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +# ๐Ÿ“‰ P/E RATIO +# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + +def haal_pe_op(ticker: str) -> str: + try: + info = yf.Ticker(ticker).info + pe = info.get("trailingPE", None) + if pe is None: + return 'P/E: niet beschikbaar' + if pe < 0: + kleur, uitleg = "#c0392b", "verlies" + elif pe < 15: + kleur, uitleg = "#1a7a1a", "goedkoop" + elif pe < 30: + kleur, uitleg = "#f5a623", "gemiddeld" + else: + kleur, uitleg = "#c0392b", "duur" + return f'P/E ratio: {pe:.1f} ({uitleg})' + except: + return 'P/E: niet beschikbaar' + +# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +# ๐Ÿ“ฐ NIEUWS OPHALEN +# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + +def haal_nieuws_op(ticker: str, max_artikels: int = 5) -> list: + try: + nieuws = yf.Ticker(ticker).news + koppen = [] + for artikel in nieuws[:max_artikels]: + titel = artikel.get("content", {}).get("title", "") + if titel: + koppen.append(titel) + return koppen + except Exception as e: + log(f"Fout bij nieuws ophalen voor {ticker}: {e}") + return [] + +# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +# ๐Ÿค– AI SAMENVATTING +# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + +def maak_samenvatting(naam: str, ticker: str, koppen: list) -> str: + if not koppen: + return "Geen recent nieuws gevonden." + koppen_tekst = "\n".join(f"- {k}" for k in koppen) + prompt = f""" +Dit zijn recente nieuwskoppen over het aandeel {naam} ({ticker}): + +{koppen_tekst} + +Schrijf een korte samenvatting van 2-3 zinnen in het Nederlands. +Wees concreet en to-the-point. Geen inleiding of afsluiting nodig. +""" + client = Groq(api_key=GROQ_API_KEY) + response = client.chat.completions.create( + model="llama-3.3-70b-versatile", + messages=[{"role": "user", "content": prompt}], + max_tokens=300, + ) + return response.choices[0].message.content.strip() + +# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +# ๐Ÿ’ก AI KIEST 5 LOW-RISK AANDELEN +# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + +def haal_lowrisk_aandelen() -> list: + """ + Vraagt aan Groq om 5 low-risk aandelen te selecteren. + Geeft een lijst van dicts terug: [{ticker, naam, reden}, ...] + """ + log(" AI selecteert 5 low-risk aandelen...") + datum = datetime.now().strftime("%d %B %Y") + prompt = f""" +Vandaag is het {datum}. + +Selecteer 5 interessante, low-risk aandelen voor een voorzichtige belegger. +Criteria: stabiele bedrijven, voorkeur voor dividend, lage volatiliteit, sterke balans. +Denk aan sectoren zoals consumentengoederen, gezondheidszorg, nutsbedrijven, ETFs. + +Geef je antwoord ALLEEN als een JSON-array, zonder uitleg of extra tekst, in dit formaat: +[ + {{"ticker": "JNJ", "naam": "Johnson & Johnson", "reden": "Stabiel dividendaandeel met sterke cashflow."}}, + {{"ticker": "PG", "naam": "Procter & Gamble", "reden": "Defensief consumentengoederen bedrijf."}}, + ... +] +""" + client = Groq(api_key=GROQ_API_KEY) + response = client.chat.completions.create( + model="llama-3.3-70b-versatile", + messages=[{"role": "user", "content": prompt}], + max_tokens=500, + ) + tekst = response.choices[0].message.content.strip() + + try: + # Verwijder eventuele markdown backticks + tekst = tekst.replace("```json", "").replace("```", "").strip() + aandelen = json.loads(tekst) + return aandelen[:5] + except Exception as e: + log(f"Fout bij parsen van low-risk aandelen: {e}") + return [] + +def bouw_lowrisk_sectie(aandelen: list) -> str: + """Bouwt de HTML-sectie op voor de 5 low-risk aandelen.""" + if not aandelen: + return "

Kon geen aanbevelingen ophalen vandaag.

" + + rijen = "" + for a in aandelen: + ticker = a.get("ticker", "") + naam = a.get("naam", ticker) + reden = a.get("reden", "") + kleur, advies_label = haal_advies_op(ticker) + pe_badge = haal_pe_op(ticker) + + rijen += f""" +
+
+
+ {naam} + {ticker} +
+ + {advies_label} + +
+
{pe_badge}
+

{reden}

+
+ """ + + return f""" +
+

๐Ÿ’ก AI-tip: 5 Low-Risk Aandelen van Vandaag

+

Dagelijks geselecteerd door AI op basis van stabiliteit en dividendkracht

+ {rijen} +
+ """ + +# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +# ๐Ÿ“ง NIEUWSBRIEF SAMENSTELLEN EN STUREN +# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + +def stuur_nieuwsbrief(): + log("โ”€โ”€ Nieuwsbrief samenstellen โ”€โ”€") + datum = datetime.now().strftime("%A %d %B %Y") + + secties_html = "" + for ticker, naam in WATCHLIST.items(): + log(f" Verwerken: {naam} ({ticker})") + koppen = haal_nieuws_op(ticker) + samenvatting = maak_samenvatting(naam, ticker, koppen) + kleur, advies_label = haal_advies_op(ticker) + pe_badge = haal_pe_op(ticker) + + secties_html += f""" +
+
+
+

{naam}

+

{ticker}

+
+ + {advies_label} + +
+
{pe_badge}
+

{samenvatting}

+
+ """ + + # Low-risk sectie + lowrisk_aandelen = haal_lowrisk_aandelen() + lowrisk_html = bouw_lowrisk_sectie(lowrisk_aandelen) + + legenda = """ +
+ P/E ratio legenda:
+ โ–  Onder 15 = goedkoop  |  + โ–  15โ€“30 = gemiddeld  |  + โ–  Boven 30 = duur  |  + โ–  Negatief = verlies +
+ """ + + html = f""" + +
+

๐Ÿ“ฐ Jouw Dagelijkse Aandelenupdate

+

{datum}

+
+ {secties_html} + {lowrisk_html} + {legenda} +

+ Samengevat door Groq AI ยท Analistenadvies & P/E via Yahoo Finance ยท Geen financieel advies +

+ + """ + + onderwerp = f"๐Ÿ“ฐ Aandelenupdate {datetime.now().strftime('%d/%m/%Y')}" + bericht = MIMEMultipart("alternative") + bericht["Subject"] = onderwerp + bericht["From"] = GMAIL_ADRES + bericht["To"] = ONTVANGER + bericht.attach(MIMEText(html, "html")) + + with smtplib.SMTP_SSL("smtp.gmail.com", 465) as server: + server.login(GMAIL_ADRES, GMAIL_APP_WACHTWOORD) + server.sendmail(GMAIL_ADRES, ONTVANGER, bericht.as_string()) + + log("โœ… Nieuwsbrief verstuurd!") + +# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +# ๐Ÿš€ STARTEN +# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + +if __name__ == "__main__": + log(f"๐Ÿ“ฐ Nieuwsbrief-bot gestart! Verstuurt elke ochtend om {VERSTUUR_OM}.") + + # Meteen 1x uitvoeren voor de test (verwijder # hieronder om te testen) + #stuur_nieuwsbrief() + + schedule.every().day.at(VERSTUUR_OM).do(stuur_nieuwsbrief) + while True: + schedule.run_pending() + time.sleep(30) \ No newline at end of file diff --git a/Dockers/aandelen-watcher-bas/docker-compose.yml b/Dockers/aandelen-watcher-bas/docker-compose.yml new file mode 100644 index 0000000..aa1f570 --- /dev/null +++ b/Dockers/aandelen-watcher-bas/docker-compose.yml @@ -0,0 +1,17 @@ +services: + aandelen-watcher: + build: . + container_name: aandelen-watcher + env_file: + - .env + environment: + - TZ=Europe/Amsterdam + - LOG_FILE=/data/nieuws_log.txt + - WATCHLIST_FILE=/data/watchlist.json + volumes: + - aandelen_data:/data + - ./watchlist.json:/data/watchlist.json:ro + restart: unless-stopped + +volumes: + aandelen_data: diff --git a/Dockers/aandelen-watcher-bas/requirements.txt b/Dockers/aandelen-watcher-bas/requirements.txt new file mode 100644 index 0000000..42222d4 --- /dev/null +++ b/Dockers/aandelen-watcher-bas/requirements.txt @@ -0,0 +1,3 @@ +yfinance +schedule +groq diff --git a/Dockers/aandelen-watcher-bas/version b/Dockers/aandelen-watcher-bas/version new file mode 100644 index 0000000..b9bc2fd --- /dev/null +++ b/Dockers/aandelen-watcher-bas/version @@ -0,0 +1 @@ +latest \ No newline at end of file diff --git a/Dockers/aandelen-watcher-bas/watchlist.json.example b/Dockers/aandelen-watcher-bas/watchlist.json.example new file mode 100644 index 0000000..705ffbb --- /dev/null +++ b/Dockers/aandelen-watcher-bas/watchlist.json.example @@ -0,0 +1,5 @@ +{ + "HIMS": "Hims & Hers Health", + "AMD": "Advanced Micro Devices", + "EUNL.DE": "iShares Core MSCI World ETF" +}