diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 6176ee5..0000000 --- a/.dockerignore +++ /dev/null @@ -1,24 +0,0 @@ -# .dockerignore - -# 忽略 Python 虚拟环境 -venv/ -.venv/ - -# 忽略 Python 缓存文件 -__pycache__/ -*.pyc -*.pyo -*.pyd - -# 忽略 IDE 和编辑器配置文件 -.vscode/ -.idea/ -*.sublime-project -*.sublime-workspace - -# 忽略 Git 目录 -.git/ -.gitignore - -# 忽略 Docker 本地缓存 -.docker/ \ No newline at end of file diff --git a/.env.sample b/.env.sample new file mode 100644 index 0000000..3d3cfbc --- /dev/null +++ b/.env.sample @@ -0,0 +1,84 @@ +# ============================================================================= +# Automated Options Recommendation Bot +# Institutional Environment Configuration Template +# Copy this file to ".env" and populate secrets before runtime. +# ============================================================================= + +# ----------------------------------------------------------------------------- +# I. External Data Provider Credentials +# ----------------------------------------------------------------------------- +FRED_API_KEY=your_fred_api_key_here +SEC_USER_AGENT=YourName YourOrg your_email@example.com + +# ----------------------------------------------------------------------------- +# II. Vector Infrastructure (Qdrant) +# ----------------------------------------------------------------------------- +QDRANT_HOST=https://your-qdrant-endpoint.example.com +QDRANT_API_KEY=your_qdrant_api_key_here + +# ----------------------------------------------------------------------------- +# III. Core Inference Runtime (Ollama) +# ----------------------------------------------------------------------------- +# Use one of OLLAMA_BASE_URL or OLLAMA_HOST according to your runtime scripts. +OLLAMA_BASE_URL=http://localhost:11434 +OLLAMA_HOST=http://localhost:11434 +OLLAMA_KEEP_ALIVE=30m + +# Expert and router tier model routing. +OLLAMA_CUSTOM_MODEL_NAME=options-expert-v1:latest +OLLAMA_ROUTER_MODEL=llama3:latest +OLLAMA_INGESTION_MODEL=llama3:latest + +# Optional per-role overrides. +OLLAMA_ANALYST_MODEL=options-expert-v1:latest +OLLAMA_CHECKER_MODEL=options-expert-v1:latest +OLLAMA_CRITIC_MODEL=options-expert-v1:latest +OLLAMA_FINALIZER_MODEL=options-expert-v1:latest +OLLAMA_FINALIZER_ENRICHMENT_MODEL=llama3:latest + +# ----------------------------------------------------------------------------- +# IV. Retrieval and Embedding Controls +# ----------------------------------------------------------------------------- +EMBEDDING_PROVIDER=huggingface +EMBEDDING_MODEL_NAME=BAAI/bge-large-en-v1.5 +EMBEDDING_DEVICE=cpu +RETRIEVER_DEVICE=cpu +FASTEMBED_THREADS=4 +SPARSE_MODEL_NAME=prithivida/Splade_PP_en_v1 +RERANKER_MODEL_NAME=BAAI/bge-reranker-v2-m3 +DATA_LAKE_ROOT=./Data + +# ----------------------------------------------------------------------------- +# V. Agent Risk and Governance Controls +# ----------------------------------------------------------------------------- +AGENT_MAX_REVISIONS=3 +CHECKER_NUMERIC_TOLERANCE=0.02 +CHECKER_TOOL_RECOVERY=1 +CHECKER_MACRO_EXEMPT_ENABLED=1 +CHECKER_COVERAGE_CHECK_ENABLED=1 +INSIDER_SIGNAL_MIN_COUNT=3 + +# Optional analyst/finalizer tuning. +ANALYST_TEMPERATURE=0.1 +CRITIC_TEMPERATURE=0.0 +FINALIZER_TEMPERATURE=0.0 +FINALIZER_LLAMA3_ENRICHMENT=0 + +# ----------------------------------------------------------------------------- +# VI. Routing and Performance Controls +# ----------------------------------------------------------------------------- +ROUTER_TEMPERATURE=0.0 +GOLD_TIMEOUT=10.0 +SILVER_TIMEOUT=10.0 +SILVER_MAX_TICKERS=5 +HE_NOVEL_TICKERS_CAP=3 +TICKER_EXPLOSION_CAP=8 +TICKER_EXPLOSION_KEEP=5 + +# ----------------------------------------------------------------------------- +# VII. Optional Runtime and Cache Controls +# ----------------------------------------------------------------------------- +PYTHON_ENV=dev +YFINANCE_CACHE_DIR= +XDG_CACHE_HOME= +TMPDIR= diff --git a/.gitignore b/.gitignore index 38f1099..b7faf40 100644 --- a/.gitignore +++ b/.gitignore @@ -1,30 +1,207 @@ -# Python cache and virtual environments +# Byte-compiled / optimized / DLL files __pycache__/ -*.pyc -.venv/ -venv/ +*.py[codz] +*$py.class -# Large model files -# Assuming Ollama stores models in a default or custom directory -.ollama/ -models/ -options-expert +# C extensions +*.so -# Environment variables and secrets -.env -*.env +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py.cover +.hypothesis/ +.pytest_cache/ +cover/ -# Data and Logs -data/ -logs/ +# Translations +*.mo +*.pot + +# Django stuff: *.log -Youtube_channel_ID +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# UV +# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +#uv.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock +#poetry.toml + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python. +# https://pdm-project.org/en/latest/usage/project/#working-with-version-control +#pdm.lock +#pdm.toml +.pdm-python +.pdm-build/ + +# pixi +# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control. +#pixi.lock +# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one +# in the .venv directory. It is recommended not to include this directory in version control. +.pixi + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.envrc +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +# Abstra +# Abstra is an AI-powered process automation framework. +# Ignore directories containing user credentials, local state, and settings. +# Learn more at https://abstra.io/docs +.abstra/ + +# Visual Studio Code +# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore +# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore +# and can be added to the global gitignore or merged into this file. However, if you prefer, +# you could uncomment the following to ignore the entire vscode folder +# .vscode/ + +# Ruff stuff: +.ruff_cache/ + +# PyPI configuration file +.pypirc -# IDE and OS-specific files -.idea/ -.vscode/ -.DS_Store +# Cursor +# Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to +# exclude from AI features like autocomplete and code analysis. Recommended for sensitive data +# refer to https://docs.cursor.com/context/ignore-files +.cursorignore +.cursorindexingignore -# Qdrant data and monitoring folders -qdrant_storage/ -monitoring/ +# Marimo +marimo/_static/ +marimo/_lsp/ +__marimo__/ diff --git a/Data/1_Bronze_Raw/GPR_index/2026-04-10/gpr_preview.csv b/Data/1_Bronze_Raw/GPR_index/2026-04-10/gpr_preview.csv new file mode 100644 index 0000000..8620b3b --- /dev/null +++ b/Data/1_Bronze_Raw/GPR_index/2026-04-10/gpr_preview.csv @@ -0,0 +1,25 @@ +month,gpr,gprt,gpra,gprh,gprht,gprha,share_gpr,n10,share_gprh,n3h,gprh_noew,gpr_noew,gprh_and,gpr_and,gprh_basic,gpr_basic,shareh_cat_1,shareh_cat_2,shareh_cat_3,shareh_cat_4,shareh_cat_5,shareh_cat_6,shareh_cat_7,shareh_cat_8,gprc_arg,gprc_aus,gprc_bel,gprc_bra,gprc_can,gprc_che,gprc_chl,gprc_chn,gprc_col,gprc_deu,gprc_dnk,gprc_egy,gprc_esp,gprc_fin,gprc_fra,gprc_gbr,gprc_hkg,gprc_hun,gprc_idn,gprc_ind,gprc_isr,gprc_ita,gprc_jpn,gprc_kor,gprc_mex,gprc_mys,gprc_nld,gprc_nor,gprc_per,gprc_phl,gprc_pol,gprc_prt,gprc_rus,gprc_sau,gprc_swe,gprc_tha,gprc_tun,gprc_tur,gprc_twn,gprc_ukr,gprc_usa,gprc_ven,gprc_vnm,gprc_zaf,gprhc_arg,gprhc_aus,gprhc_bel,gprhc_bra,gprhc_can,gprhc_che,gprhc_chl,gprhc_chn,gprhc_col,gprhc_deu,gprhc_dnk,gprhc_egy,gprhc_esp,gprhc_fin,gprhc_fra,gprhc_gbr,gprhc_hkg,gprhc_hun,gprhc_idn,gprhc_ind,gprhc_isr,gprhc_ita,gprhc_jpn,gprhc_kor,gprhc_mex,gprhc_mys,gprhc_nld,gprhc_nor,gprhc_per,gprhc_phl,gprhc_pol,gprhc_prt,gprhc_rus,gprhc_sau,gprhc_swe,gprhc_tha,gprhc_tun,gprhc_tur,gprhc_twn,gprhc_ukr,gprhc_usa,gprhc_ven,gprhc_vnm,gprhc_zaf,var_name,var_label,date,gpr_mom_pct,gpr_yoy_pct,gpr_3m_ma,gpr_percentile +2024-04-01,163.95,170.7,165.99,112.01,120.66,119.72,4.92,15801.0,4.04,6014,146.92,154.11,76.6,138.23,164.73,148.76,0.71,0.02,1.41,0.17,0.17,1.43,0.73,0.58,0.04,0.31,0.24,0.09,0.47,0.05,0.01,1.04,0.05,0.72,0.03,0.7,0.17,0.08,0.82,2.0,0.12,0.05,0.08,0.25,2.91,0.19,0.28,0.27,0.13,0.02,0.12,0.07,0.03,0.08,0.32,0.03,1.83,0.39,0.13,0.06,0.0,0.25,0.3,1.67,4.02,0.04,0.08,0.14,0.05,0.28,0.12,0.08,0.27,0.03,0.0,0.63,0.08,0.62,0.05,0.45,0.12,0.03,0.8,1.01,0.03,0.02,0.1,0.17,2.36,0.17,0.27,0.3,0.15,0.02,0.13,0.02,0.07,0.1,0.22,0.03,1.56,0.3,0.15,0.05,0.0,0.27,0.3,1.51,3.84,0.03,0.07,0.15,,,2024-04-01,23.07,53.49,147.92,94.75 +2024-05-01,130.52,131.45,133.15,107.46,128.57,102.5,3.91,16348.0,3.88,6062,153.61,146.35,74.05,128.27,176.29,135.79,0.56,0.03,1.5,0.43,0.13,1.24,0.64,0.4,0.07,0.21,0.22,0.05,0.28,0.09,0.02,0.94,0.03,0.48,0.02,0.71,0.17,0.04,0.64,1.25,0.07,0.07,0.04,0.13,1.75,0.15,0.18,0.26,0.06,0.02,0.13,0.13,0.01,0.02,0.18,0.01,1.72,0.26,0.12,0.01,0.01,0.18,0.23,1.53,3.11,0.07,0.09,0.18,0.08,0.18,0.18,0.03,0.08,0.07,0.02,0.86,0.07,0.56,0.03,0.86,0.2,0.05,0.82,0.61,0.02,0.05,0.03,0.13,1.8,0.25,0.15,0.18,0.1,0.02,0.13,0.13,0.02,0.03,0.18,0.02,1.73,0.33,0.08,0.02,0.02,0.21,0.25,1.53,3.74,0.07,0.1,0.2,,,2024-05-01,-20.39,20.33,142.56,83.64 +2024-06-01,113.09,125.71,109.74,86.77,100.23,89.5,3.39,15772.0,3.13,6006,132.48,124.54,64.03,105.52,166.58,131.14,0.47,0.05,1.13,0.4,0.17,1.13,0.4,0.52,0.04,0.14,0.27,0.08,0.24,0.18,0.01,0.89,0.04,0.45,0.08,0.47,0.11,0.03,0.72,1.22,0.04,0.13,0.04,0.19,1.52,0.34,0.26,0.34,0.06,0.02,0.12,0.11,0.03,0.12,0.14,0.03,1.47,0.15,0.11,0.01,0.05,0.17,0.18,1.27,2.69,0.06,0.11,0.11,0.02,0.13,0.2,0.03,0.08,0.17,0.02,0.68,0.08,0.27,0.02,0.48,0.17,0.0,0.7,0.52,0.03,0.08,0.02,0.1,1.55,0.33,0.2,0.33,0.08,0.02,0.15,0.1,0.05,0.12,0.2,0.02,1.27,0.1,0.03,0.02,0.08,0.22,0.25,1.12,3.08,0.07,0.12,0.1,,,2024-06-01,-13.35,2.32,135.85,74.75 +2024-07-01,92.39,95.16,95.11,71.84,79.6,68.05,2.77,16238.0,2.59,5942,113.29,111.86,66.04,111.78,155.8,107.06,0.45,0.0,0.89,0.25,0.08,0.88,0.45,0.3,0.02,0.07,0.12,0.07,0.17,0.08,0.03,0.73,0.06,0.43,0.03,0.28,0.12,0.03,0.47,1.07,0.08,0.16,0.04,0.16,1.08,0.14,0.16,0.19,0.04,0.02,0.07,0.06,0.01,0.04,0.15,0.02,0.99,0.14,0.09,0.01,0.0,0.15,0.15,0.87,2.09,0.1,0.06,0.06,0.0,0.05,0.12,0.03,0.05,0.08,0.0,0.47,0.07,0.32,0.03,0.35,0.13,0.02,0.54,0.56,0.05,0.15,0.03,0.22,1.16,0.17,0.13,0.2,0.05,0.03,0.07,0.05,0.02,0.07,0.05,0.07,0.74,0.19,0.05,0.02,0.0,0.25,0.1,0.66,2.47,0.1,0.12,0.12,,,2024-07-01,-18.3,-14.01,112.0,49.09 +2024-08-01,140.98,124.8,165.18,105.3,100.77,122.46,4.23,15798.0,3.8,6081,138.91,136.32,72.14,123.21,146.36,126.97,0.66,0.03,1.18,0.15,0.1,1.46,0.79,0.53,0.04,0.17,0.08,0.15,0.19,0.1,0.01,0.64,0.09,0.42,0.08,0.79,0.05,0.08,0.65,1.59,0.09,0.04,0.06,0.23,1.88,0.13,0.1,0.17,0.12,0.04,0.05,0.1,0.02,0.07,0.13,0.02,1.55,0.26,0.07,0.05,0.01,0.22,0.13,1.34,3.21,0.15,0.07,0.07,0.03,0.12,0.03,0.18,0.05,0.1,0.02,0.59,0.13,0.31,0.07,0.9,0.03,0.12,0.69,0.81,0.05,0.02,0.07,0.25,1.94,0.15,0.08,0.25,0.12,0.03,0.02,0.07,0.03,0.1,0.1,0.0,1.38,0.21,0.0,0.05,0.0,0.16,0.2,1.13,3.65,0.18,0.03,0.03,,,2024-08-01,52.58,39.38,115.49,89.09 +2024-09-01,130.36,134.04,135.55,95.7,102.59,100.68,3.91,15371.0,3.45,6025,144.5,133.14,62.65,108.63,183.3,137.65,0.45,0.0,1.13,0.55,0.12,1.08,0.68,0.5,0.03,0.08,0.15,0.11,0.23,0.03,0.03,0.77,0.04,0.49,0.02,0.47,0.08,0.06,0.79,1.64,0.03,0.14,0.04,0.17,1.85,0.12,0.21,0.27,0.1,0.03,0.03,0.04,0.0,0.08,0.12,0.02,1.44,0.15,0.06,0.03,0.0,0.27,0.21,1.3,2.97,0.07,0.05,0.07,0.05,0.08,0.13,0.13,0.13,0.03,0.05,0.7,0.07,0.45,0.02,0.38,0.08,0.1,0.76,0.86,0.02,0.18,0.02,0.18,1.63,0.1,0.17,0.38,0.15,0.0,0.03,0.07,0.0,0.08,0.15,0.03,1.29,0.12,0.03,0.03,0.0,0.3,0.17,1.26,3.3,0.08,0.05,0.03,,,2024-09-01,-7.53,32.16,121.24,83.43 +2024-10-01,130.69,128.41,142.82,90.89,103.32,94.79,3.92,16174.0,3.28,6191,143.66,147.16,63.51,113.23,177.34,143.31,0.73,0.02,1.03,0.57,0.05,1.16,0.68,0.37,0.04,0.11,0.2,0.09,0.22,0.07,0.0,0.98,0.01,0.55,0.05,0.27,0.1,0.11,0.65,1.45,0.11,0.08,0.14,0.27,2.1,0.27,0.22,0.4,0.13,0.04,0.11,0.11,0.01,0.04,0.19,0.01,1.37,0.3,0.1,0.04,0.01,0.28,0.31,1.1,3.03,0.04,0.04,0.15,0.0,0.11,0.24,0.05,0.13,0.05,0.0,0.73,0.0,0.5,0.06,0.21,0.02,0.18,0.65,0.68,0.03,0.06,0.11,0.08,1.74,0.19,0.26,0.42,0.08,0.0,0.08,0.06,0.02,0.1,0.21,0.0,1.24,0.29,0.15,0.02,0.0,0.29,0.39,1.03,3.15,0.05,0.05,0.06,,,2024-10-01,0.25,-33.96,134.01,83.84 +2024-11-01,128.9,139.15,127.43,94.96,123.34,88.91,3.87,15881.0,3.43,6101,129.24,135.68,69.46,112.61,159.19,139.03,0.84,0.05,1.16,0.7,0.03,1.2,0.61,0.31,0.05,0.11,0.2,0.21,0.33,0.06,0.03,1.01,0.03,0.7,0.05,0.21,0.13,0.14,0.69,1.52,0.07,0.16,0.03,0.18,1.41,0.25,0.2,0.85,0.15,0.01,0.11,0.12,0.1,0.03,0.13,0.01,1.97,0.21,0.14,0.03,0.0,0.28,0.19,1.79,3.17,0.08,0.09,0.09,0.03,0.07,0.21,0.25,0.13,0.05,0.03,0.85,0.05,0.54,0.05,0.26,0.07,0.1,0.61,0.69,0.1,0.1,0.02,0.11,1.38,0.26,0.16,0.89,0.1,0.0,0.07,0.05,0.18,0.05,0.13,0.0,1.79,0.2,0.08,0.02,0.0,0.3,0.2,1.7,3.38,0.13,0.08,0.08,,,2024-11-01,-1.37,-17.74,129.98,82.83 +2024-12-01,142.37,128.26,164.81,116.52,113.43,124.54,4.27,14379.0,4.2,5781,154.34,144.1,76.3,115.33,171.37,141.36,0.48,0.03,1.56,0.31,0.1,1.07,1.45,0.38,0.03,0.11,0.16,0.09,0.31,0.06,0.01,0.84,0.03,0.54,0.07,0.26,0.06,0.12,0.55,1.53,0.06,0.07,0.02,0.19,1.61,0.15,0.21,0.54,0.16,0.03,0.1,0.1,0.04,0.03,0.08,0.02,2.3,0.34,0.1,0.01,0.01,1.2,0.18,1.54,3.29,0.04,0.03,0.1,0.02,0.07,0.1,0.1,0.09,0.05,0.0,0.8,0.07,0.45,0.03,0.28,0.03,0.07,0.73,1.04,0.0,0.07,0.05,0.21,1.8,0.17,0.16,0.45,0.14,0.03,0.09,0.07,0.1,0.03,0.1,0.03,2.25,0.29,0.03,0.02,0.02,1.19,0.19,1.54,4.03,0.02,0.05,0.14,,,2024-12-01,10.45,0.06,133.99,89.7 +2025-01-01,113.23,117.09,109.5,100.89,112.79,99.39,3.4,15988.0,3.64,8435,163.71,106.15,76.39,87.77,220.27,158.36,0.31,0.07,1.62,0.13,0.15,1.11,0.56,0.59,0.03,0.08,0.13,0.19,0.34,0.11,0.04,0.86,0.24,0.53,0.18,0.31,0.0,0.1,0.63,1.3,0.1,0.07,0.04,0.24,1.03,0.14,0.14,0.35,0.34,0.01,0.09,0.08,0.03,0.04,0.16,0.02,1.13,0.24,0.08,0.03,0.02,0.21,0.16,0.8,2.75,0.11,0.01,0.08,0.02,0.08,0.12,0.13,0.17,0.12,0.01,0.51,0.18,0.31,0.12,0.31,0.07,0.08,0.52,0.45,0.07,0.01,0.04,0.2,0.91,0.13,0.18,0.28,0.31,0.0,0.07,0.02,0.04,0.05,0.12,0.0,0.85,0.23,0.01,0.02,0.01,0.14,0.15,0.57,2.32,0.09,0.0,0.05,,,2025-01-01,-20.46,-29.39,128.17,75.15 +2025-02-01,136.97,138.76,140.78,94.49,107.73,98.21,4.11,14848.0,3.41,7833,153.84,111.03,80.25,102.73,206.51,173.12,0.4,0.1,1.19,0.28,0.24,1.29,0.37,0.38,0.05,0.18,0.44,0.05,0.65,0.05,0.01,1.1,0.09,1.14,0.23,0.38,0.0,0.19,1.03,1.76,0.06,0.09,0.05,0.21,1.0,0.2,0.18,0.33,0.46,0.01,0.11,0.09,0.0,0.01,0.4,0.02,1.95,0.69,0.14,0.1,0.01,0.29,0.14,1.76,3.54,0.1,0.06,0.07,0.0,0.11,0.17,0.01,0.27,0.08,0.0,0.51,0.08,0.57,0.05,0.27,0.09,0.14,0.52,0.43,0.01,0.08,0.04,0.14,0.66,0.08,0.14,0.19,0.19,0.0,0.04,0.05,0.0,0.01,0.2,0.01,1.0,0.52,0.08,0.04,0.0,0.19,0.09,0.91,2.22,0.06,0.01,0.0,,,2025-02-01,20.96,-6.57,130.86,86.67 +2025-03-01,173.91,193.7,158.23,119.59,143.99,120.67,5.22,16870.0,4.31,8623,164.99,129.84,96.29,119.56,224.89,197.11,0.66,0.06,1.81,0.36,0.15,1.84,0.61,0.36,0.02,0.17,0.39,0.09,0.95,0.08,0.01,1.08,0.05,0.94,0.17,0.43,0.0,0.17,1.32,2.51,0.13,0.14,0.05,0.24,1.2,0.39,0.29,0.39,0.43,0.03,0.11,0.16,0.04,0.02,0.39,0.04,2.46,0.79,0.14,0.09,0.01,0.34,0.17,2.23,4.46,0.18,0.07,0.08,0.0,0.1,0.22,0.05,0.31,0.05,0.0,0.65,0.0,0.53,0.05,0.34,0.07,0.06,0.71,0.85,0.03,0.08,0.02,0.14,0.89,0.15,0.1,0.36,0.17,0.03,0.05,0.06,0.05,0.01,0.2,0.05,1.44,0.58,0.08,0.06,0.0,0.19,0.12,1.32,2.96,0.17,0.06,0.02,,,2025-03-01,26.97,30.55,141.37,95.96 +2025-04-01,140.97,159.26,132.06,111.29,144.29,106.61,4.23,16484.0,4.01,8419,161.8,115.62,88.56,116.33,230.72,174.69,0.58,0.05,1.95,0.46,0.12,1.24,0.52,0.48,0.04,0.1,0.27,0.1,0.39,0.08,0.01,1.06,0.03,0.61,0.08,0.24,0.0,0.08,0.76,1.51,0.07,0.12,0.08,0.42,1.12,0.41,0.32,0.32,0.22,0.05,0.08,0.12,0.02,0.05,0.11,0.01,1.52,0.26,0.08,0.08,0.0,0.27,0.13,1.29,3.52,0.18,0.16,0.12,0.04,0.05,0.21,0.12,0.19,0.05,0.0,0.69,0.04,0.37,0.07,0.12,0.07,0.08,0.64,0.61,0.01,0.15,0.05,0.39,0.88,0.33,0.21,0.2,0.2,0.07,0.06,0.07,0.04,0.06,0.07,0.0,1.12,0.26,0.06,0.1,0.0,0.33,0.12,0.82,2.91,0.19,0.14,0.06,,,2025-04-01,-18.94,-14.01,150.62,88.89 +2025-05-01,165.66,203.55,148.82,128.91,188.27,107.88,4.97,17087.0,4.65,8365,170.42,127.3,87.91,111.31,222.5,168.7,0.96,0.06,2.52,0.53,0.13,1.26,0.26,0.75,0.05,0.18,0.22,0.07,0.74,0.15,0.02,1.12,0.04,0.67,0.08,0.29,0.0,0.08,1.02,1.99,0.1,0.05,0.09,0.76,1.89,0.36,0.17,0.32,0.19,0.03,0.09,0.09,0.03,0.04,0.19,0.02,1.49,0.7,0.2,0.04,0.02,0.69,0.21,1.39,4.1,0.19,0.1,0.09,0.01,0.14,0.1,0.06,0.35,0.08,0.01,0.68,0.06,0.45,0.07,0.17,0.17,0.02,0.77,0.74,0.06,0.02,0.04,0.6,1.29,0.27,0.1,0.27,0.22,0.05,0.04,0.08,0.01,0.04,0.04,0.02,1.04,0.59,0.05,0.05,0.02,0.57,0.12,0.96,3.37,0.31,0.14,0.08,,,2025-05-01,17.51,26.92,160.18,94.95 +2025-06-01,222.38,288.16,183.32,156.37,237.55,122.95,6.67,16087.0,5.64,7942,202.73,162.47,93.58,123.21,225.77,191.56,0.93,0.03,2.58,2.01,0.1,1.61,0.55,0.52,0.03,0.3,0.21,0.09,0.94,0.07,0.01,1.39,0.02,0.92,0.1,0.37,0.0,0.07,1.1,2.76,0.11,0.05,0.02,0.47,4.18,0.24,0.39,0.42,0.2,0.04,0.32,0.19,0.01,0.04,0.17,0.01,2.18,0.46,0.19,0.04,0.01,0.67,0.21,1.77,5.66,0.05,0.11,0.05,0.01,0.19,0.16,0.05,0.38,0.03,0.01,0.87,0.03,0.42,0.03,0.3,0.23,0.04,0.72,0.81,0.0,0.05,0.01,0.3,2.35,0.19,0.29,0.39,0.16,0.04,0.25,0.14,0.03,0.05,0.1,0.01,1.45,0.42,0.13,0.04,0.03,0.48,0.19,1.21,3.79,0.04,0.14,0.03,,,2025-06-01,34.24,96.63,176.34,97.58 +2025-07-01,134.02,156.11,118.93,106.2,136.62,101.12,4.02,16568.0,3.83,8144,136.99,102.86,78.15,100.26,159.54,132.01,0.39,0.04,1.92,0.48,0.11,1.2,0.72,0.36,0.02,0.12,0.17,0.1,0.39,0.08,0.0,0.9,0.02,0.65,0.11,0.32,0.0,0.09,0.71,1.62,0.05,0.03,0.13,0.36,1.8,0.24,0.31,0.35,0.1,0.16,0.11,0.09,0.01,0.1,0.11,0.02,1.39,0.21,0.12,0.14,0.01,0.36,0.11,1.21,3.16,0.05,0.1,0.06,0.0,0.07,0.12,0.04,0.21,0.02,0.0,0.7,0.0,0.44,0.1,0.25,0.05,0.04,0.53,0.72,0.04,0.01,0.06,0.31,1.22,0.09,0.25,0.27,0.06,0.15,0.06,0.09,0.0,0.07,0.06,0.01,0.92,0.14,0.11,0.15,0.0,0.26,0.12,0.76,2.69,0.05,0.07,0.0,,,2025-07-01,-39.73,45.05,174.02,85.66 +2025-08-01,138.56,160.42,120.88,119.71,179.55,92.08,4.16,15640.0,4.32,7873,163.31,115.87,84.53,102.26,193.91,148.39,0.53,0.03,2.71,0.42,0.2,1.33,0.32,0.39,0.02,0.22,0.19,0.11,0.45,0.04,0.01,0.81,0.04,0.91,0.06,0.29,0.0,0.27,0.97,1.71,0.07,0.12,0.03,0.47,1.52,0.33,0.28,0.27,0.1,0.03,0.06,0.1,0.02,0.04,0.17,0.03,1.7,0.18,0.11,0.03,0.01,0.25,0.1,1.57,3.39,0.08,0.1,0.09,0.01,0.19,0.14,0.11,0.19,0.04,0.0,0.55,0.05,0.6,0.03,0.3,0.11,0.25,0.8,0.88,0.03,0.09,0.01,0.46,1.04,0.24,0.25,0.15,0.08,0.03,0.05,0.05,0.01,0.01,0.15,0.01,1.28,0.18,0.06,0.04,0.0,0.22,0.09,1.21,2.96,0.1,0.09,0.06,,,2025-08-01,3.39,-1.71,164.99,88.08 +2025-09-01,125.87,141.81,114.79,113.95,161.89,91.92,3.78,15310.0,4.11,8101,168.33,106.07,85.25,93.06,234.97,159.94,0.58,0.04,2.17,0.33,0.31,1.21,0.41,0.43,0.01,0.25,0.27,0.09,0.41,0.03,0.0,1.01,0.09,0.68,0.12,0.28,0.0,0.1,0.9,1.44,0.03,0.22,0.05,0.4,1.38,0.32,0.19,0.24,0.19,0.03,0.09,0.12,0.01,0.04,0.46,0.1,1.43,0.25,0.1,0.03,0.02,0.28,0.12,1.2,3.11,0.22,0.08,0.08,0.0,0.15,0.1,0.1,0.2,0.02,0.0,0.62,0.11,0.47,0.09,0.21,0.15,0.07,0.67,0.74,0.01,0.12,0.01,0.23,1.02,0.16,0.2,0.17,0.23,0.0,0.1,0.1,0.01,0.05,0.28,0.06,0.93,0.2,0.09,0.04,0.02,0.26,0.09,0.77,2.74,0.3,0.11,0.07,,,2025-09-01,-9.16,-3.44,132.82,82.22 +2025-10-01,154.51,168.0,151.55,132.36,165.64,122.54,4.63,15989.0,4.77,8210,178.21,118.42,91.19,106.61,236.2,171.55,0.58,0.1,2.25,0.29,0.35,1.34,0.6,0.77,0.04,0.21,0.26,0.13,0.27,0.04,0.03,0.94,0.29,0.54,0.21,0.57,0.0,0.05,0.57,1.41,0.12,0.31,0.08,0.29,1.49,0.18,0.29,0.33,0.29,0.1,0.15,0.18,0.02,0.05,0.28,0.02,1.51,0.23,0.14,0.11,0.02,0.51,0.19,1.21,3.75,0.53,0.04,0.1,0.02,0.13,0.17,0.11,0.09,0.0,0.04,0.63,0.35,0.23,0.11,0.33,0.16,0.0,0.35,0.45,0.06,0.27,0.04,0.22,0.91,0.1,0.19,0.3,0.33,0.12,0.1,0.1,0.01,0.06,0.16,0.0,0.85,0.12,0.05,0.07,0.01,0.29,0.17,0.76,3.2,0.62,0.02,0.09,,,2025-10-01,22.76,18.23,139.65,93.13 +2025-11-01,104.34,118.68,88.69,90.52,119.1,77.96,3.13,15913.0,3.27,7717,133.55,95.64,70.88,89.74,184.78,133.71,0.45,0.04,1.71,0.25,0.18,0.79,0.31,0.63,0.04,0.07,0.23,0.09,0.3,0.08,0.02,0.65,0.22,0.55,0.06,0.19,0.0,0.04,0.55,1.0,0.04,0.11,0.09,0.19,0.58,0.11,0.16,0.2,0.23,0.04,0.06,0.12,0.01,0.03,0.25,0.04,1.29,0.2,0.06,0.04,0.01,0.31,0.14,0.99,2.66,0.46,0.05,0.25,0.04,0.04,0.1,0.06,0.18,0.03,0.01,0.51,0.26,0.32,0.05,0.18,0.17,0.03,0.39,0.41,0.04,0.06,0.08,0.22,0.4,0.08,0.12,0.21,0.23,0.03,0.03,0.08,0.03,0.05,0.06,0.04,0.88,0.18,0.03,0.04,0.0,0.19,0.13,0.52,2.16,0.51,0.08,0.09,,,2025-11-01,-32.47,-19.06,128.24,66.67 +2025-12-01,131.39,145.27,122.23,112.33,142.11,99.59,3.94,15250.0,4.05,7527,150.71,111.45,82.47,95.77,218.36,170.89,0.52,0.08,2.02,0.2,0.27,0.89,0.4,0.97,0.08,0.42,0.3,0.09,0.19,0.05,0.03,1.0,0.16,0.7,0.11,0.16,0.0,0.1,0.67,1.29,0.14,0.14,0.03,0.31,0.66,0.15,0.26,0.2,0.1,0.07,0.14,0.19,0.01,0.14,0.24,0.01,1.67,0.15,0.15,0.1,0.01,0.24,0.26,1.35,3.23,0.71,0.03,0.04,0.05,0.21,0.16,0.12,0.08,0.04,0.03,0.81,0.15,0.5,0.07,0.07,0.04,0.07,0.56,0.53,0.05,0.09,0.03,0.2,0.44,0.19,0.2,0.15,0.08,0.08,0.12,0.15,0.01,0.09,0.27,0.0,1.22,0.16,0.12,0.13,0.0,0.16,0.23,0.88,2.87,0.57,0.04,0.04,,,2025-12-01,25.93,-7.71,130.08,84.44 +2026-01-01,167.8,219.48,99.39,128.07,198.12,70.97,5.03,16074.0,4.62,7922,159.57,128.76,96.79,121.54,227.16,182.66,0.96,0.03,2.68,0.45,0.15,0.61,0.42,0.56,0.16,0.11,0.21,0.18,0.67,0.41,0.12,1.5,0.34,0.66,0.52,0.2,0.0,0.11,0.93,1.88,0.09,0.11,0.07,0.32,1.16,0.27,0.32,0.21,0.34,0.05,0.14,0.47,0.05,0.05,0.18,0.02,1.89,0.34,0.15,0.04,0.02,0.37,0.2,1.18,4.55,1.93,0.02,0.06,0.15,0.1,0.14,0.16,0.28,0.38,0.05,1.02,0.25,0.54,0.34,0.15,0.19,0.09,0.67,0.76,0.05,0.09,0.1,0.34,0.81,0.24,0.21,0.14,0.33,0.06,0.1,0.25,0.06,0.06,0.16,0.03,1.31,0.24,0.1,0.08,0.03,0.3,0.15,0.86,3.4,1.44,0.01,0.01,,,2026-01-01,27.71,48.19,134.51,95.35 +2026-02-01,121.62,158.19,82.99,108.26,159.08,74.48,3.65,15160.0,3.91,6555,144.91,115.89,77.22,103.59,197.72,136.04,0.85,0.05,1.98,0.87,0.11,0.88,0.46,0.31,0.09,0.16,0.09,0.09,0.41,0.18,0.02,0.88,0.05,0.46,0.14,0.23,0.0,0.06,0.56,1.19,0.05,0.09,0.04,0.44,1.13,0.14,0.2,0.23,0.28,0.03,0.09,0.09,0.01,0.04,0.13,0.01,1.3,0.32,0.11,0.05,0.0,0.37,0.13,0.9,3.12,0.56,0.06,0.05,0.12,0.15,0.06,0.12,0.21,0.21,0.03,0.55,0.08,0.34,0.2,0.32,0.18,0.05,0.58,0.49,0.02,0.11,0.08,0.35,0.98,0.08,0.18,0.23,0.31,0.03,0.08,0.06,0.0,0.02,0.11,0.02,0.93,0.31,0.09,0.08,0.0,0.32,0.15,0.72,2.87,0.67,0.11,0.02,,,2026-02-01,-27.52,-11.21,140.27,80.81 +2026-03-01,297.27,293.39,404.05,251.38,282.04,312.33,8.92,15668.0,9.07,7642,293.68,227.77,119.33,142.94,411.87,333.81,1.88,0.05,3.08,0.98,0.29,5.61,0.9,0.52,0.05,0.47,0.33,0.17,0.87,0.2,0.04,1.55,0.13,1.21,0.19,0.63,0.0,0.1,1.77,3.56,0.15,0.12,0.11,0.93,6.1,0.56,0.86,0.7,0.26,0.06,0.26,0.33,0.03,0.11,0.13,0.03,2.34,2.23,0.11,0.18,0.0,0.82,0.31,1.9,8.39,1.05,0.25,0.07,0.03,0.24,0.35,0.12,0.39,0.09,0.03,1.54,0.14,0.79,0.18,0.48,0.18,0.09,1.39,1.35,0.14,0.13,0.16,0.88,4.87,0.37,0.96,0.68,0.29,0.09,0.18,0.26,0.01,0.12,0.13,0.04,2.03,1.91,0.07,0.26,0.0,0.58,0.37,1.5,7.03,1.07,0.3,0.04,,,2026-03-01,144.43,70.93,195.56,98.59 diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-08/Full_text/full_text_asset_precious_metals_spot.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-08/Full_text/full_text_asset_precious_metals_spot.jsonl new file mode 100644 index 0000000..99daa7d --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-08/Full_text/full_text_asset_precious_metals_spot.jsonl @@ -0,0 +1,5 @@ +{"url": "https://www.illawarramercury.com.au/story/9217560/everything-you-need-to-know-about-flying-with-pets-in-cabin/", "title": "Everything you need to know about flying with pets in cabin | Illawarra Mercury", "publish_date": "2026-04-09T01:22:35Z", "full_text": "In this article\n\nWhich routes are available?\n\nHow many pets can be booked on each flight?\n\nWhich pets are allowed?\n\nDo pets need to go in a carrier?\n\nHow will security work?\n\nCan pets go to the toilet during the flight?\n\nWhere will you be seated?\n\nWhat if you are allergic to pets - should you fly on these services?\n\nHow much are the services?\n\nDoes this replace your carry-on baggage allowance?"} +{"url": "https://www.itbear.com.cn/html/2026-04/1264928.html", "title": "逆境中破局前行 , 埃安换标推新高端品牌引领行业新变革 - 智能汽车 - ITBear比尔科技", "publish_date": "2026-04-09T01:22:35Z", "full_text": "新能源汽车赛道再掀波澜,埃安品牌近日以一系列大动作引发行业高度关注。继冲刺科创板新能源汽车第一股的消息传出后,这家企业又于9月15日举办全新品牌发布会,通过品牌升级、技术突破与产品创新,向市场投下三枚重磅\"炸弹\"。\n\n发布会上最直观的变革来自品牌视觉系统。埃安正式启用全新\"AI神箭\"LOGO,以极具张力的弓箭造型诠释科技向上的品牌理念。这一设计不仅与航天领域形成视觉呼应,更通过动态线条传递出突破边界的进取姿态。品牌负责人表示,新标识象征着埃安从传统车企向科技企业转型的决心,也预示着品牌将开启高端化发展的新篇章。\n\n在产品矩阵层面,埃安推出全新高端品牌Hyper昊铂,剑指全球智能纯电市场制高点。该品牌首款车型Hyper SSR的亮相堪称全场焦点——这款中国首台量产超跑以1.9秒破百的加速性能刷新行业认知,其搭载的AI轨迹牵引系统、双电机四驱技术等12项核心专利,均实现100%自主知识产权。更值得关注的是,整车采用航天级碳纤维材料与低风阻设计,在性能与美学间达成完美平衡。\n\n此次品牌焕新被业界视为埃安混改进程的关键节点。从启动A轮引战增资到筹备科创板上市,从电池技术突破到超跑量产落地,埃安正通过\"技术+资本\"双轮驱动构建竞争壁垒。行业分析师指出,Hyper昊铂品牌的推出不仅完善了埃安的产品梯度,更通过超跑这类技术标杆产品,为品牌注入高端基因,这种战略布局与特斯拉通过Model S树立品牌形象有着异曲同工之妙。\n\n随着中国航天合作项目的深入,埃安的科技属性持续强化。从电池热失控防护技术到星灵电子电气架构,从弹匣电池到超跑级电驱系统,这家成立仅5年的企业已构建起覆盖\"三电\"核心领域的专利矩阵。此次发布的Hyper品牌,或将通过航天级标准的严苛验证,推动中国新能源汽车产业向更高维度突破。"} +{"url": "https://www.163.com/dy/article/KQ2DKDEO05198UNI.html", "title": "无惧地缘逆风 ! 高盛 : AI支出浪潮汹涌 , 布局 卖铲人 正当时|人工智能", "publish_date": "2026-04-09T01:22:35Z", "full_text": "特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。\n\nNotice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services."} +{"url": "https://www.finanznachrichten.de/nachrichten-2026-04/68152259-alkane-resources-limited-march-2026-quarter-production-update-399.htm", "title": "Alkane Resources Limited : March 2026 Quarter Production Update", "publish_date": "2026-04-09T01:22:35Z", "full_text": "Quarterly Production of 45,776 oz AuEq1\n\nClosing cash and bullion $362 million - $130 million increase from December\n\nQuarterly gold production of 45,776 AuEq1 oz, comprised of:\n\nMine Group Q3\n\n(1 Jan - 31 Mar 2026) Group YTD2\n\n(1 Jul - 31 March 2026) Production Tomingley 21,652 Au oz 62,076 Au oz Costerfield 10,584 Au oz\n\n377 Sb t\n\n11,691 AuEq oz 29,986 Au oz\n\n842 Sb t\n\n32,869 AuEq oz Björkdal 12,433 Au oz 30,901 Au oz Consolidated 44,669 Au oz\n\n377 Sb t\n\n45,776 AuEq oz 122,963 Au oz\n\n842 Sb t\n\n125,846 AuEq oz Sales Consolidated 42,550 Au oz\n\n280 Sb t\n\n43,373 AuEq oz 119,596 Au oz\n\n829 Sb t\n\n122,416 AuEq oz\n\nCash, bullion and listed investment balance of $374 million. Increase of $128 million from the previous quarter. Alkane has cash & bullion of $362 million, and pro forma liquidity of $472 million when including an undrawn $110 million revolving credit facility (subject to satisfaction of conditions precedent, expected June 2026). The company is debt free except for equipment finance of $20 million at 31 March 2026.\n\nSales of 42,550 ounces of gold and 280 tonnes of antimony.\n\nFY2026 Group Guidance of 160,000 to 175,000 AuEq 1 oz production at an AISC of A$2,600 - $2,900 per AuEq oz remains unchanged. 3\n\nOperations have not been interrupted by diesel supply. Alkane has contracts in place with diesel suppliers for regular fuel deliveries, our suppliers have not indicated any disruptions. Diesel represents a small portion of total costs, as we have three underground mines and power is provided from grid suppliers in Australia and Sweden.\n\nPERTH, Australia, April 08, 2026 (GLOBE NEWSWIRE) -- Alkane Resources Ltd ('Alkane') (ASX:ALK, TSX:ALK, OTC:ALKRY) has produced 45,776 ounces of gold equivalent1 over the period from 1 January 2026 to 31 March 2026. Cash ($328m), bullion ($34m) and listed investments ($12m) totaled A$374 million at the end of the quarter. During the quarter hedging of 8,700 ounces of gold was filled and tax instalments of $15 million were made. Further details will be available in the full March 2026 Quarterly Report later this month.\n\nAlkane Managing Director & CEO, Nic Earner, said:\n\n\"Alkane has had an excellent quarter's production from our three operating mines which together produced 44,669 ounces of gold and 377 tonnes of antimony (45,776 ounces of gold equivalent) over the quarter. We have a very strong balance sheet with A$374 million in cash, bullion and listed investments at quarter end and total liquidity of $472 million including undrawn revolving credit facility.\"\n\nThis document has been authorised for release to the market by Nic Earner, Managing Director & CEO.\n\nABOUTALKANE-alkres.com - ASX:ALK | TSX: ALK | OTCQX: ALKRY\n\nAlkane Resources (ASX:ALK; TSX:ALK; OTCQX:ALKRY) is an Australia-based gold and antimony producer with a portfolio of three operating mines across Australia and Sweden. The Company has a strong balance sheet and is positioned for further growth.\n\nAlkane's wholly owned producing assets are the Tomingley open pit and underground gold mine southwest of Dubbo in Central West New South Wales, the Costerfield gold and antimony underground mining operation northeast of Heathcote in Central Victoria, and the Björkdal underground gold mine northwest of Skellefteå in Sweden (approximately 750km north of Stockholm). Ongoing near-mine regional exploration continues to grow resources at all three operations.\n\nAlkane also owns the very large gold-copper porphyry Boda-Kaiser Project in Central West New South Wales and has outlined an economic development pathway in a Scoping Study. The Company has ongoing exploration within the surrounding Northern Molong Porphyry Project and is confident of further enhancing eastern Australia's reputation as a significant gold, copper and antimony production region.\n\nInteractive Analyst Centre\n\nComprehensive financial, operational, resource and reserve information for Alkane Resources is available through the Interactive Analyst Centre located in the Investors section of our website at alkres.com.\n\nCautionary Note Regarding Forward-Looking Information and Statements\n\nThis announcement contains certain forward-looking information and forward-looking statements within the meaning of applicable securities legislation and may include future-oriented financial information or financial outlook information (collectively \"Forward-Looking Information\"). Actual results and outcomes may vary materially from the amounts set out in any Forward-Looking Information. As well, Forward-Looking Information may relate to: future outlook and anticipated events; expectations regarding exploration potential; production capabilities and future financial or operating performance, including AISC, investment returns, margins and share price performance; production and cost guidance and the timing thereof; issuing updated resources and reserves estimate and the timing thereof; the potential of the Company to meet industry targets, public profile and expectations; and future plans, projections, objectives, estimates and forecasts and the timing related thereto. Forward-Looking Information is generally identified by the use of words like \"will\", \"create\", \"enhance\", \"improve\", \"potential\", \"expect\", \"upside\", \"growth\" and similar expressions and phrases or statements that certain actions, events or results \"may\", \"could\", or \"should\", or the negative connotation of such terms, are intended to identify Forward-Looking Information. Although Alkane believes that the expectations reflected in the Forward-Looking Information are reasonable, undue reliance should not be placed on Forward-Looking Information since no assurance can be provided that such expectations will prove to be correct. Forward-Looking Information is based on information available at the time those statements are made and/or good faith belief of the officers and directors of Alkane as of that time with respect to future events and are subject to risks and uncertainties that could cause actual results to differ materially from those expressed in or suggested by the Forward-Looking Information. Forward-Looking Information involves numerous risks and uncertainties. Such factors include, without limitation: risks relating to changes in the gold and antimony price. Forward-Looking Information is designed to help readers understand Alkane's views as of that time with respect to future events and speak only as of the date they are made. Except as required by applicable law, Alkane assumes no obligation to update or to publicly announce the results of any change to any forward-looking statement contained or incorporated by reference herein to reflect actual results, future events or developments, changes in assumptions or changes in other factors affecting the Forward-looking Information. If Alkane updates any one or more forward-looking statements, no inference should be drawn that the company will make additional updates with respect to those or other Forward-looking Information. All Forward-Looking Information contained in this announcement is expressly qualified in its entirety by this cautionary statement.\n\nDisclaimer\n\nAlkane has prepared this announcement based on information available to it. No representation or warranty, express or implied, is made as to the fairness, accuracy, completeness or correctness of the information, opinions or conclusions contained in this announcement. To the maximum extent permitted by law, none of Alkane, its directors, officers, employees, associates, advisers and agents, nor any other person accepts any liability, including, without limitation, any liability arising from fault or negligence on the part of any of them or any other person, for any loss arising from the use of this announcement or its contents or otherwise arising in connection with it. This announcement is not an offer, invitation, solicitation, or other recommendation with respect to the subscription for, purchase or sale of any security, and neither this announcement nor anything in it shall form the basis of any contract or commitment whatsoever.\n\nCONTACT: NIC EARNER, MANAGING DIRECTOR & CEO, ALKANE RESOURCES LTD, TEL +61 8 9227 5677\n\nINVESTORS & MEDIA: NATALIE CHAPMAN, CORPORATE COMMUNICATIONS MANAGER, TEL +61 418 642 556\n\n\n\n1 Gold equivalent ounces calculated by multiplying quantities of gold and antimony in period by respective average market price of commodities in period, adding the two amounts to get \"total contained value based on market price,\" and dividing total contained value by average market price of gold in period. I.e., AuEq = ((Au Produced x Au $/oz) + (Sb Produced pre-payability x 70% payability x Sb $/t)) / (Au $/oz). Average market prices for gold and antimony sourced respectively from LMBA daily PM price (www.lmba.org.uk) and Shanghai Metal Market Price (www.metal.com). Average market prices for March quarter were A$7,015/oz Au and A$29,449/t Sb, average market prices for December quarter were A$6,299/oz Au and A$30,245/t Sb and for September quarter A$5,283/oz Au and A$33,508/t Sb using an AUD: USD exchange rate of 0.6946, 0.6565 and 0.6544 respectively.\n\n2 Group YTD Production calculated on basis of 100% contribution from Tomingley, Costerfield and Björkdal for relevant period. As the merger with Mandalay Resources completed on 5 August 2025, Alkane's FY2026 statutory reported production will reflect production from Costerfield and Björkdal only from that date. See ALK announcement dated 9 Sep 2025 and titled 'Alkane Announces Financial Year 2026 Guidance'.\n\n3 See ALK Announcement dated 9 Sep 2025 and titled 'Alkane Announces Financial Year 2026 Guidance' for calculation of Au Eq ounces and definition of Group Guidance. Production guidance on a statutory reported basis ('Attributable Guidance') is 155,000 - 168,000 AuEq ounces for FY2026. Note AISC is a non-IFRS measure and does not have a standardised meaning under IFRS and might not be comparable to similar financial measures disclosed by other companies. Refer to \"Non-IFRS Performance Measures\" at the end of this announcement."} +{"url": "https://www.163.com/dy/article/KQ2E94OS05118O8G.html", "title": "早报|B站推出播放页暂停广告 / GoPro启动大规模裁员 / Meta时隔9个月再发大模型 , 被指 「 图表造假 」 ", "publish_date": "2026-04-09T01:22:35Z", "full_text": "特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。\n\nNotice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services."} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-08/Full_text/full_text_macro_central_banks.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-08/Full_text/full_text_macro_central_banks.jsonl new file mode 100644 index 0000000..d74f819 --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-08/Full_text/full_text_macro_central_banks.jsonl @@ -0,0 +1,9 @@ +{"url": "https://www.clactonandfrintongazette.co.uk/news/national/26005807.rising-mortgage-costs-dent-buyer-demand-amid-housing-market-mood-shift/", "title": "Rising mortgage costs dent buyer demand amid housing market mood shift ", "publish_date": "2026-04-09T01:19:11Z", "full_text": "The Royal Institution of Chartered Surveyors (Rics) said the housing market was losing momentum in March as rising borrowing costs and wider geopolitical uncertainty weighed heavily on buyer confidence and sales activity.\n\nA net balance of 39% of professionals saw new buyer inquiries falling rather than rising, deteriorating from a balance of 29% who saw this in February.\n\nThis was the weakest reading since August 2023, as housing market optimism seen earlier in the year faded.\n\nAgreed sales also deteriorated, with a net balance of 34% of professionals seeing falls, down from a balance of 13% who saw this the previous month.\n\nRics said the report points to a market increasingly pressured by inflationary concerns and higher mortgage costs.\n\nA net balance of 33% of professionals expect sales activity to weaken further over the next few months.\n\nLooking 12 months ahead, a net balance of just 1% of professionals expect sales to weaken, indicating a broadly flat market.\n\nA balance of 23% of professionals saw house prices falling rather than rising in March.\n\nPrice expectations for the next three months also weakened, with a net balance of 43% of professionals expecting falls. Looking a year ahead, a balance of 2% of professionals expect price increases, pointing to little overall price growth over the year ahead.\n\nLooking across the UK, London, East Anglia, the South East and the South West all posted weaker price readings than the national average, while Scotland and Northern Ireland continued to report rising prices.\n\n(PA Graphics)\n\nOn the supply side, new instructions to sell remained subdued and the amount of unsold stock on estate agents’ books rose to an average of 47 properties, up from around 45 at the start of the year.\n\nIn the lettings market, a mismatch between demand and supply continued, with demand for homes from tenants rising while landlord instructions continued to decrease, Rics said.\n\nTarrant Parsons, Rics head of market research and analysis, said: “The mood across the UK housing market has shifted markedly over the past couple of months.\n\n“What had been a cautiously improving picture for activity has been knocked off course by the wider macro fallout from the Middle East conflict, as the renewed deterioration in the mortgage rate outlook has proved particularly challenging.\n\n“Indeed, with average fixed rates climbing back above 5% according to some sources, it is unsurprising that buyer demand has softened.\n\n“The path ahead hinges on whether or not recent surges in oil and energy costs begin to reverse in what remains a highly uncertain geopolitical environment.”\n\nOn Wednesday, financial information website Moneyfacts said mortgage rates are likely to remain higher for “some time yet” despite some signs of the upward pressure easing.\n\nGlobal stock markets have been recovering after the US and Iran agreed a two-week ceasefire, and Moneyfacts said that calming markets should have a stabilising impact on the mortgage market.\n\nAdam French, head of consumer finance at Moneyfacts, said: “The longer the ceasefire holds and markets calm, the more the mortgage market will stabilise, and rates could even begin to edge lower.\n\n“But for now, it’s more likely to slow or pause increases rather than trigger any sharp falls.”\n\nJinesh Vohra, chief executive of mortgage app Sprive, said: “Strategies like regular overpayments or reducing your balance earlier can have an outsized impact – potentially saving homeowners thousands over the term of their mortgage.\n\n“In today’s environment, it’s not just about getting on the ladder, but managing the cost of staying on it.”"} +{"url": "https://www.northwichguardian.co.uk/news/national/26005807.rising-mortgage-costs-dent-buyer-demand-amid-housing-market-mood-shift/", "title": "Rising mortgage costs dent buyer demand amid housing market mood shift ", "publish_date": "2026-04-09T01:19:11Z", "full_text": "The Royal Institution of Chartered Surveyors (Rics) said the housing market was losing momentum in March as rising borrowing costs and wider geopolitical uncertainty weighed heavily on buyer confidence and sales activity.\n\nA net balance of 39% of professionals saw new buyer inquiries falling rather than rising, deteriorating from a balance of 29% who saw this in February.\n\nThis was the weakest reading since August 2023, as housing market optimism seen earlier in the year faded.\n\nAgreed sales also deteriorated, with a net balance of 34% of professionals seeing falls, down from a balance of 13% who saw this the previous month.\n\nRics said the report points to a market increasingly pressured by inflationary concerns and higher mortgage costs.\n\nA net balance of 33% of professionals expect sales activity to weaken further over the next few months.\n\nLooking 12 months ahead, a net balance of just 1% of professionals expect sales to weaken, indicating a broadly flat market.\n\nA balance of 23% of professionals saw house prices falling rather than rising in March.\n\nPrice expectations for the next three months also weakened, with a net balance of 43% of professionals expecting falls. Looking a year ahead, a balance of 2% of professionals expect price increases, pointing to little overall price growth over the year ahead.\n\nLooking across the UK, London, East Anglia, the South East and the South West all posted weaker price readings than the national average, while Scotland and Northern Ireland continued to report rising prices.\n\n(PA Graphics)\n\nOn the supply side, new instructions to sell remained subdued and the amount of unsold stock on estate agents’ books rose to an average of 47 properties, up from around 45 at the start of the year.\n\nIn the lettings market, a mismatch between demand and supply continued, with demand for homes from tenants rising while landlord instructions continued to decrease, Rics said.\n\nTarrant Parsons, Rics head of market research and analysis, said: “The mood across the UK housing market has shifted markedly over the past couple of months.\n\n“What had been a cautiously improving picture for activity has been knocked off course by the wider macro fallout from the Middle East conflict, as the renewed deterioration in the mortgage rate outlook has proved particularly challenging.\n\n“Indeed, with average fixed rates climbing back above 5% according to some sources, it is unsurprising that buyer demand has softened.\n\n“The path ahead hinges on whether or not recent surges in oil and energy costs begin to reverse in what remains a highly uncertain geopolitical environment.”\n\nOn Wednesday, financial information website Moneyfacts said mortgage rates are likely to remain higher for “some time yet” despite some signs of the upward pressure easing.\n\nGlobal stock markets have been recovering after the US and Iran agreed a two-week ceasefire, and Moneyfacts said that calming markets should have a stabilising impact on the mortgage market.\n\nAdam French, head of consumer finance at Moneyfacts, said: “The longer the ceasefire holds and markets calm, the more the mortgage market will stabilise, and rates could even begin to edge lower.\n\n“But for now, it’s more likely to slow or pause increases rather than trigger any sharp falls.”\n\nJinesh Vohra, chief executive of mortgage app Sprive, said: “Strategies like regular overpayments or reducing your balance earlier can have an outsized impact – potentially saving homeowners thousands over the term of their mortgage.\n\n“In today’s environment, it’s not just about getting on the ladder, but managing the cost of staying on it.”"} +{"url": "https://www.dunya.com/kose-yazisi/gunde-ortalama-18-milyar-tl/820965", "title": "Günde ortalama 18 milyar TL - Naki BAKIR", "publish_date": "2026-04-09T01:19:11Z", "full_text": "Devletin ana gelir ve harca­malarına ait nakit denge­si bu yıl ilk çeyrekte geçen yıla göre daha düşük bir açık verdi. Ancak, bu açığın finansmanı­nın yanı sıra vadesi gelen es­ki borçların yüksek orandaki geri ödeme yükü, Hazine’nin brüt borçlanmasını geçen yı­la göre bir kata yakın büyüttü.\n\nHazine ve Maliye Bakanlı­ğı’nın açıkladığı verilere göre ocak-mart döneminde Hazi­ne’nin nakit bazda gelirleri ön­ceki yıla göre yüzde 64,9 artış­la 3 trilyon 995,3 milyar liraya ulaşırken, harcamaları yüzde 38,4 artışla 4 trilyon 614,6 mil­yar lira oldu. Böylece Hazine nakit dengesi ilk üç ayda 618,3 milyar lira açıkla bağlandı. Nakit açığı geçen yılın aynı dö­nemindekinin yüzde 31,4 al­tında gerçekleşti. İlk çeyrekler itibarıyla 2022 yılında sadece 23,1 milyar lira olan Hazine nakit açığı, 2023’te 257,9 milyar, 2024’te 570,4 milyar ve 2025 yılında 901,6 milyar lira ile yüksek düzeylere ulaşmıştı. Buna göre ilk çey­rekler bazında büyümesi gö­rece hız kesmekle birlikte açık yüksek düzeyini korudu.\n\nFaiz ödemelerinde hızlı artış\n\nİlk çeyrekte verilen yüksek nakit açığında yüklü faiz öde­meleri etkili oldu. Hazine’nin bu dönemdeki nakit harcama­larının 3 trilyon 747 milyarını önceki yıla göre yüzde 28,9 ar­tan faiz dışı harcamalar oluş­tururken, faiz ödemeleri yüz­de 103’lük artışla 867,7 milyar liraya ulaştı.\n\nAncak faiz yükündeki büyü­me de önceki yıllara göre ivme kazandı. Faiz ödemeleri 2025 yılı ilk çeyrekte önceki yı­lın aynı dönemine göre yüzde 89,8 artışla 427,4 milyar lira olmuştu. İlk çeyrekler itiba­rıyla faiz ödemelerinin nakit bazda toplam giderler içinde­ki payı yüzde 12,8’den yüzde 18,8’e yükseldi.\n\nİç borçta itfa yükü 7 kat arttı\n\nÖnceki yıllarda bütçe açıkları ve borç çevirme ihtiyacı dolayısıyla yüksek faizle gidilen ve esas olarak içeriden yapılan yoğun borç­lanmaların mirası olarak Ha­zine bu yıl ilk çeyreğe yığılmış rekor düzeyde bir itfa yükü ile karşı karşıya kaldı.\n\nHazine ilk üç ayda vadesi ge­len iç borçlar dolayısıyla 918,3 milyar ve dış borçlar için de 178,7 milyar lira olmak üze­re toplam 1 trilyon 97 milyar liralık borç geri ödemesi ger­çekleştirdi. Dış borç geri öde­meleri geçen yılın ilk çeyre­ğindekinin yüzde 22,4 altında kalırken, iç borç geri ödemele­rinde yüzde 684,3’le adeta pat­lama yaşandı. Böylece toplam geri ödeme miktarı geçen yılın ilk çeyreğine göre yüzde 215,8 oranında bir artış kaydetti.\n\nÜç ayda 1,6 trilyonluk borçlanma\n\nHazine, ilk çeyrekteki na­kit açığın finansmanı ve vade­si gelen borçların çevrilmesi için brüt 1 trilyon 630 milyar liralık yeni borçlanmaya git­ti. Bunun da yine büyük bö­lümü iç borçlanma şeklinde gerçekleşti. Brüt borçlanma tutarı geçen yılın eş dönemine göre yüzde 91,4’le yaklaşık bir kat büyüdü. Geçen yıl ilk çeyrekte günlük ortalaması 9,4 milyar lira olan Hazine brüt borçlanması, bu yıl aynı dönemde 18,1 milyar lira ile ikiye katlandı.\n\nOcak-mart dönemindeki brüt borçlanmanın 1 tril­yon 376,9 milyar liralık bölü­mü devlet iç borçlanma sene­di (DİBS) ihraçları yoluyla iç borçlanma şeklinde ya­pıldı. Üç aylık iç borçlanma geçen yıla gö­re yüzde 82 art­tı. Aynı dönem­deki itfalardan sonra Hazine’nin üç aylık net iç borçlanması 458,6 milyar lira ile geçen yılın aynı dönemin­dekinin yüzde 28,3 al­tında gerçekleşti.\n\nAynı dönemde dış borç geri ödemesi geçen yılın al­tında kalan Hazine, 178,7 mil­yar lira ile geçen yıla göre yüz­de 172,5 daha fazla dış borç kullanımına gitti. Böylece Ha­zine ilk üç aydaki net dış borç­lanması 74,4 milyar lira olarak gerçekleşti. Bu gelişmelerle Hazine’nin üç aydaki iç ve dış toplam borçlanması, başka de­yişle geri ödemeler sonrası ka­sasında kalan net miktar 533 milyar lira olarak gerçekleşti.\n\nHazine, ilk çeyrekteki fi­nansmanın büyük bölümünü toplam net borçlanmadan el­de ederken, net borçlanmanın üstüne kasasından 50,3 mil­yar liralık kullanım, Tasarruf Mevduatı Sigorta Fonu’ndan (TMSF) gelen 33,9 milyar li­ralık aktarım ve devirli-ga­rantili borçlardan 1 milyar li­ra civarındaki bir geri dönüşle nakit açığını finanse etti. Kur farklarından gelen 31,4 mil­yar liralık gelir sayesinde Ha­zine’nin kasa-banka bakiyesi 31,4 milyar lira oldu."} +{"url": "https://www.fnnews.com/news/202604090630516306", "title": "경기 불황에 카드 돌려막기 6개월 만에 반등 … 연체율도 20년새 최고", "publish_date": "2026-04-09T01:19:11Z", "full_text": "\n\n\n\n(서울=뉴스1) 정지윤 기자 = '카드 돌려막기'를 의미하는 대환대출 잔액이 지난해 8월 이후 6개월 만에 1조 5000억 원을 넘어선 것으로 나타났다. 일반은행의 신용카드 대출 연체율도 20년 8개월 만에 최고치를 경신했다. 경기 불황에 은행권 신용대출 문턱까지 높아지며 급전이 필요한 수요가 카드론으로 이동한 것으로 풀이된다.8일 여신금융협회에 따르면 국내 8개 전업 카드사(신한·삼성·현대·KB국민·롯데·우리·하나·BC카드)의 2월 카드론 대환대출 잔액은 1조 5001억 원을 기록했다.이는 카드론 대환대출 잔액이 1조 5404억 원을 기록했던 지난해 8월 이후 가장 높은 수준이다.지난 9월 1조 3214억 원을 기록했던 것과 비교하면 5개월 새 13.5% 증가했다.카드론 대환대출은 카드론 차주들이 대출 만기 전 빌린 돈을 갚지 못할 상황에 놓일 경우 카드사에 다시 심사를 신청해 대출을 받는 '돌려막기'를 의미한다. 금리가 낮은 상품으로 갈아타는 은행의 일반적인 대환대출과는 다르게 만기를 연장하는 성격이 강하다.카드론 대환대출을 이용할 경우 만기가 늘어나긴 하지만 신용이 재평가되면서 신용등급이 떨어지고 기존 대출보다 높은 금리를 감당해야 한다. 이 때문에 금융권에서는 카드론 대환대출 확대를 서민경제에 적신호로 해석한다.최근 카드론 대환대출은 경기 불황과 은행권 대출 규제와 수요 변화가 맞물리며 늘어난 것으로 해석된다. 은행 창구가 좁아지면서 신용대출이 막히자 급히 자금이 필요한 차주들이 카드론으로 이동했고 대출 상환 부담이 컸던 차주들이 이를 제때 갚지 못하면서 다시 대환대출로 이어지는 악순환이 형성됐다는 분석이다.이 같은 대환대출 증가는 차주의 상환 능력 저하를 보여주는 지표로도 해석돼 이러한 흐름이 계속 이어질 경우 연체율 증가로 이어질 가능성이 크다.실제로 한국은행에 따르면 지난 1월 말 기준 일반은행의 신용카드 대출 연체율은 4.1%를 기록하며 전월 대비 무려 0.9%포인트(p) 상승했다. 이는 약 20년 8개월 만에 최고치로, 카드 사태가 있던 지난 2005년 5월(5.0%) 이후 가장 높은 수준이다.카드 결제대금을 이월하는 리볼빙 잔액도 증가 추세다.리볼빙은 결제 금액 일부를 다음 달로 넘기는 방식으로 대출과는 다르지만 상환 부담을 뒤로 미룬다는 점에서 카드론 대환대출과 비슷하다.지난 2월 8개 카드사의 리볼빙 잔액은 6조 7336억 원을 기록했다.리볼빙 잔액이 6조 7000억 원대로 다시 올라선 건 지난해 하반기부터 줄곧 6조 6000억 원대를 기록해온 이후 8개월 만이다.\n\n※ 저작권자 ⓒ 뉴스1코리아, 무단전재-재배포 금지"} +{"url": "https://newsradio1290wtks.iheart.com/content/2026-04-08-stocks-close-the-day-higher-as-oil-prices-plummet-over-iran-war-cease-fire/", "title": "Stocks Close The Day Higher As Oil Prices Plummet Over Iran War Cease Fire", "publish_date": "2026-04-09T01:19:11Z", "full_text": "Stocks surged and oil prices plunged Wednesday (April 8) after a fragile two-week ceasefire between the United States and Iran took effect, raising hopes for renewed oil shipments through the Strait of Hormuz and easing global market fears. The S&P 500 soared 2.5%, the Dow Jones Industrial Average jumped 1,325 points, and the Nasdaq composite rallied 2.8% after President Donald Trump announced the temporary ceasefire.\n\nBenchmark U.S. crude oil prices dropped more than 16%, falling below $95 per barrel, while Brent crude also saw a sharp decline. The drop reversed some of the increases that came after five weeks of conflict, which had blocked the vital oil passage and pushed prices above $119 per barrel at their peak. Iran’s foreign minister stated that oil tankers would be allowed to pass for the next two weeks under Iranian military supervision.\n\nAirline and travel stocks rebounded strongly, with United Airlines up 7.9% and Carnival cruise lines climbing 9.6%. Delta Air Lines reported better-than-expected quarterly results, citing continued strong demand despite recent fuel price hikes. The positive momentum also spread globally, with Asia’s Nikkei 225 and Kospi indexes soaring over 5%, and major European markets such as Germany’s DAX and France’s CAC 40 rising over 4% each.\n\nDespite the optimism, analysts urged caution. The ceasefire remains fragile, with continued attacks reported in Iran, Israel, and Lebanon. The market’s upbeat response faded somewhat later in the day as questions lingered about whether the truce would hold and if shipping through the Strait of Hormuz would fully normalize.\n\nIn the bond market, Treasury yields fell, reflecting hopes that lower oil prices could allow the Federal Reserve to resume interest rate cuts later in the year. The yield on the 10-year Treasury note slipped to 4.29% from 4.33%."} +{"url": "https://www.watfordobserver.co.uk/news/national/26005807.rising-mortgage-costs-dent-buyer-demand-amid-housing-market-mood-shift/", "title": "Rising mortgage costs dent buyer demand amid housing market mood shift ", "publish_date": "2026-04-09T01:19:11Z", "full_text": "The Royal Institution of Chartered Surveyors (Rics) said the housing market was losing momentum in March as rising borrowing costs and wider geopolitical uncertainty weighed heavily on buyer confidence and sales activity.\n\nA net balance of 39% of professionals saw new buyer inquiries falling rather than rising, deteriorating from a balance of 29% who saw this in February.\n\nThis was the weakest reading since August 2023, as housing market optimism seen earlier in the year faded.\n\nAgreed sales also deteriorated, with a net balance of 34% of professionals seeing falls, down from a balance of 13% who saw this the previous month.\n\nRics said the report points to a market increasingly pressured by inflationary concerns and higher mortgage costs.\n\nA net balance of 33% of professionals expect sales activity to weaken further over the next few months.\n\nLooking 12 months ahead, a net balance of just 1% of professionals expect sales to weaken, indicating a broadly flat market.\n\nA balance of 23% of professionals saw house prices falling rather than rising in March.\n\nPrice expectations for the next three months also weakened, with a net balance of 43% of professionals expecting falls. Looking a year ahead, a balance of 2% of professionals expect price increases, pointing to little overall price growth over the year ahead.\n\nLooking across the UK, London, East Anglia, the South East and the South West all posted weaker price readings than the national average, while Scotland and Northern Ireland continued to report rising prices.\n\n(PA Graphics)\n\nOn the supply side, new instructions to sell remained subdued and the amount of unsold stock on estate agents’ books rose to an average of 47 properties, up from around 45 at the start of the year.\n\nIn the lettings market, a mismatch between demand and supply continued, with demand for homes from tenants rising while landlord instructions continued to decrease, Rics said.\n\nTarrant Parsons, Rics head of market research and analysis, said: “The mood across the UK housing market has shifted markedly over the past couple of months.\n\n“What had been a cautiously improving picture for activity has been knocked off course by the wider macro fallout from the Middle East conflict, as the renewed deterioration in the mortgage rate outlook has proved particularly challenging.\n\n“Indeed, with average fixed rates climbing back above 5% according to some sources, it is unsurprising that buyer demand has softened.\n\n“The path ahead hinges on whether or not recent surges in oil and energy costs begin to reverse in what remains a highly uncertain geopolitical environment.”\n\nOn Wednesday, financial information website Moneyfacts said mortgage rates are likely to remain higher for “some time yet” despite some signs of the upward pressure easing.\n\nGlobal stock markets have been recovering after the US and Iran agreed a two-week ceasefire, and Moneyfacts said that calming markets should have a stabilising impact on the mortgage market.\n\nAdam French, head of consumer finance at Moneyfacts, said: “The longer the ceasefire holds and markets calm, the more the mortgage market will stabilise, and rates could even begin to edge lower.\n\n“But for now, it’s more likely to slow or pause increases rather than trigger any sharp falls.”\n\nJinesh Vohra, chief executive of mortgage app Sprive, said: “Strategies like regular overpayments or reducing your balance earlier can have an outsized impact – potentially saving homeowners thousands over the term of their mortgage.\n\n“In today’s environment, it’s not just about getting on the ladder, but managing the cost of staying on it.”"} +{"url": "https://newsradiowkcy.iheart.com/content/2026-04-08-stocks-close-the-day-higher-as-oil-prices-plummet-over-iran-war-cease-fire/", "title": "Stocks Close The Day Higher As Oil Prices Plummet Over Iran War Cease Fire | NewsRadio WKCY", "publish_date": "2026-04-09T01:19:11Z", "full_text": "Stocks surged and oil prices plunged Wednesday (April 8) after a fragile two-week ceasefire between the United States and Iran took effect, raising hopes for renewed oil shipments through the Strait of Hormuz and easing global market fears. The S&P 500 soared 2.5%, the Dow Jones Industrial Average jumped 1,325 points, and the Nasdaq composite rallied 2.8% after President Donald Trump announced the temporary ceasefire.\n\nBenchmark U.S. crude oil prices dropped more than 16%, falling below $95 per barrel, while Brent crude also saw a sharp decline. The drop reversed some of the increases that came after five weeks of conflict, which had blocked the vital oil passage and pushed prices above $119 per barrel at their peak. Iran’s foreign minister stated that oil tankers would be allowed to pass for the next two weeks under Iranian military supervision.\n\nAirline and travel stocks rebounded strongly, with United Airlines up 7.9% and Carnival cruise lines climbing 9.6%. Delta Air Lines reported better-than-expected quarterly results, citing continued strong demand despite recent fuel price hikes. The positive momentum also spread globally, with Asia’s Nikkei 225 and Kospi indexes soaring over 5%, and major European markets such as Germany’s DAX and France’s CAC 40 rising over 4% each.\n\nDespite the optimism, analysts urged caution. The ceasefire remains fragile, with continued attacks reported in Iran, Israel, and Lebanon. The market’s upbeat response faded somewhat later in the day as questions lingered about whether the truce would hold and if shipping through the Strait of Hormuz would fully normalize.\n\nIn the bond market, Treasury yields fell, reflecting hopes that lower oil prices could allow the Federal Reserve to resume interest rate cuts later in the year. The yield on the 10-year Treasury note slipped to 4.29% from 4.33%."} +{"url": "https://www.stourbridgenews.co.uk/news/national/26005807.rising-mortgage-costs-dent-buyer-demand-amid-housing-market-mood-shift/", "title": "Rising mortgage costs dent buyer demand amid housing market mood shift ", "publish_date": "2026-04-09T01:19:11Z", "full_text": "The Royal Institution of Chartered Surveyors (Rics) said the housing market was losing momentum in March as rising borrowing costs and wider geopolitical uncertainty weighed heavily on buyer confidence and sales activity.\n\nA net balance of 39% of professionals saw new buyer inquiries falling rather than rising, deteriorating from a balance of 29% who saw this in February.\n\nThis was the weakest reading since August 2023, as housing market optimism seen earlier in the year faded.\n\nAgreed sales also deteriorated, with a net balance of 34% of professionals seeing falls, down from a balance of 13% who saw this the previous month.\n\nRics said the report points to a market increasingly pressured by inflationary concerns and higher mortgage costs.\n\nA net balance of 33% of professionals expect sales activity to weaken further over the next few months.\n\nLooking 12 months ahead, a net balance of just 1% of professionals expect sales to weaken, indicating a broadly flat market.\n\nA balance of 23% of professionals saw house prices falling rather than rising in March.\n\nPrice expectations for the next three months also weakened, with a net balance of 43% of professionals expecting falls. Looking a year ahead, a balance of 2% of professionals expect price increases, pointing to little overall price growth over the year ahead.\n\nLooking across the UK, London, East Anglia, the South East and the South West all posted weaker price readings than the national average, while Scotland and Northern Ireland continued to report rising prices.\n\n(PA Graphics)\n\nOn the supply side, new instructions to sell remained subdued and the amount of unsold stock on estate agents’ books rose to an average of 47 properties, up from around 45 at the start of the year.\n\nIn the lettings market, a mismatch between demand and supply continued, with demand for homes from tenants rising while landlord instructions continued to decrease, Rics said.\n\nTarrant Parsons, Rics head of market research and analysis, said: “The mood across the UK housing market has shifted markedly over the past couple of months.\n\n“What had been a cautiously improving picture for activity has been knocked off course by the wider macro fallout from the Middle East conflict, as the renewed deterioration in the mortgage rate outlook has proved particularly challenging.\n\n“Indeed, with average fixed rates climbing back above 5% according to some sources, it is unsurprising that buyer demand has softened.\n\n“The path ahead hinges on whether or not recent surges in oil and energy costs begin to reverse in what remains a highly uncertain geopolitical environment.”\n\nOn Wednesday, financial information website Moneyfacts said mortgage rates are likely to remain higher for “some time yet” despite some signs of the upward pressure easing.\n\nGlobal stock markets have been recovering after the US and Iran agreed a two-week ceasefire, and Moneyfacts said that calming markets should have a stabilising impact on the mortgage market.\n\nAdam French, head of consumer finance at Moneyfacts, said: “The longer the ceasefire holds and markets calm, the more the mortgage market will stabilise, and rates could even begin to edge lower.\n\n“But for now, it’s more likely to slow or pause increases rather than trigger any sharp falls.”\n\nJinesh Vohra, chief executive of mortgage app Sprive, said: “Strategies like regular overpayments or reducing your balance earlier can have an outsized impact – potentially saving homeowners thousands over the term of their mortgage.\n\n“In today’s environment, it’s not just about getting on the ladder, but managing the cost of staying on it.”"} +{"url": "https://www.dunya.com/kose-yazisi/fiyat-artisini-ihracat-kisitlamasi-ile-onlemenin-verdigi-zarar/820975", "title": "Fiyat artışını ihracat kısıtlaması ile önlemenin verdiği zarar … ", "publish_date": "2026-04-09T01:19:11Z", "full_text": "Arz yetersizliği nedeniyle, bazı ürün­lerde ihracatı kısıtlıyoruz…\n\nAncak…\n\nİhracatı kısıtlamanın, rakiplerimize avantaj sağladığını, büyük çaba ile kazanı­lan pazarların “bu nedenle” kaybedildiği­ni/kaybedilebileceğini unutuyoruz…\n\n★★★\n\nYanı sıra…\n\nİhracat kısıtlamasıyla, düşük kapasite ile üretime kapı aralıyoruz…\n\nZaten yüksek olan üretim maliyetlerinin “bu nedenle” daha da yükseldiğini/yükse­lebileceğini de unutuyoruz…\n\n★★★\n\nYok mu; hem üretimi, hem ihracatı “bir­likte” artırabilmenin yolu?\n\nYok mu; üreterek, ithalatı ve dolayısıy­la ortaya çıkan döviz açığını ve dolayısıyla ortaya çıkan borçlanma ihtiyacını ve dola­yısıyla ortaya çıkan yüksek faizleri düşüre­bilmenin yolu?\n\n★★★\n\nÖrneğin krediler…\n\n“Enflasyonu yükseltir” kaygısı ile sınır­lıyoruz…\n\nHaklı olarak, “geçmiş deneyimlerin kor­kusu”, “üretim için kredi kullananların, tü­ketimi tetikleme alışkanlıkları” gibi ne­denlerle bu kısıtlamaya gidiyoruz…\n\n★★★\n\nAncak…\n\nBu yolla, sermaye yetersizliği yaşa­yan “gerçek üreticilerin” geliştirmele­rini, üretimini, ihracatını artırabilme­sini de engelliyoruz…\n\nVe…\n\nEnflasyonla mücadelenin, kalkınmanın, yüksek refahın tek adresi olan “verimli üreticilerimizi” de, üretimden/geliştir­meden uzaklaştırıyoruz…\n\nKurunun yanında yaşı da yakıyoruz…\n\nVELHASIL\n\nYok mu, verilen kredileri doğru kul­landırmanın yolu?\n\n★★★\n\nÇimento, Cam, Seramik ve Toprak Ürünleri İhracatçıları Birliği Başkanı Erdem Çenesiz, o yollardan birini anlattı:\n\n“Üretim kapasitelerimizi korumak, yatırımlarımızı sürdürmek ve pazar­daki yerimizi kaybetmemek için ihra­catçımızın uygun maliyetli finansmana erişimi reeskont ihracat kredisi ile sağ­lanabilir…\n\nBu kredi tipinde vadelerinin uzatıl­ması ve faizlerinin düşürülmesi, enf­lasyonu tetiklemeden yatırımların, üretimin ve ihracatın artmasına vesile olur…”\n\n★★★\n\nYüzde 82’lik yerlilik payı ve ekonomiye sağladığı yüksek katma değer ile geçtiği­miz yıl 5 milyar dolarlık ihracat rakamına ulaşan;\n\nKonut açığı nedeniyle, düşük maliyetle, daha fazla üretimine ihtiyaç duyduğumuz;\n\nVe savaşların sona ermesiyle, komşu ül­kelerden talep patlaması yaşayacak bir sektörü ve diğerlerini harekete geçirecek politikalara öncelik vermeliyiz…"} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-08/Full_text/full_text_macro_inflation_employment.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-08/Full_text/full_text_macro_inflation_employment.jsonl new file mode 100644 index 0000000..9a1eb35 --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-08/Full_text/full_text_macro_inflation_employment.jsonl @@ -0,0 +1,6 @@ +{"url": "https://finance.yahoo.com/markets/stocks/articles/why-carnival-ccl-stock-soaring-000547814.html", "title": "Why Is Carnival ( CCL ) Stock Soaring Today", "publish_date": "2026-04-09T01:20:13Z", "full_text": "What Happened?\n\nShares of cruise ship company Carnival (NYSE:CCL) jumped 10.3% in the afternoon session after President Trump's Truth Social post confirmed a suspension of military action in Iran for two weeks.\n\nThis breakthrough, coupled with a 17% plunge in oil prices, sent cruise operator stocks surging. The sector had been heavily suppressed by the conflict, but the prospect of a negotiated settlement and safer maritime passage triggered a powerful relief rally. Cruise lines benefit immensely from lower \"bunker\" fuel costs, which spiked due to the war.\n\nAdditionally, the ceasefire eases travel concerns regarding safety on Mediterranean and Middle Eastern itineraries, which are high-margin routes for the industry. With the U.S. also discussing sanctions relief for Iran, the broader macro environment for global tourism appeared far more stable.\n\nIs now the time to buy Carnival? Access our full analysis report here, it’s free.\n\nWhat Is The Market Telling Us\n\nCarnival’s shares are very volatile and have had 21 moves greater than 5% over the last year. But moves this big are rare even for Carnival and indicate this news significantly impacted the market’s perception of the business.\n\nThe previous big move we wrote about was 1 day ago when the stock dropped 4.3% on the news that geopolitical tensions spiked following a strict deadline set for Iran.\n\nPresident Trump set a high-stakes deadline for Iran to reopen the Strait of Hormuz, a vital oil shipping route. Investors were worried about a potential military strike if deadline passes without a deal. The tension also pushed oil prices to their highest levels in years. This could increase costs for businesses, trigger inflation and slow down global growth.\n\nCarnival is down 9.5% since the beginning of the year, and at $27.98 per share, it is trading 17.7% below its 52-week high of $33.99 from February 2026. Investors who bought $1,000 worth of Carnival’s shares 5 years ago would now be looking at only $979.83.\n\nONE MORE THING: The $21 AI Application Stock Wall Street Forgot. While Wall Street obsesses over who’s building AI, one company is already using it to print money. And nobody’s paying attention.\n\nAI chip stocks trade at ridiculous valuations. This company processes a trillion consumer signals monthly using AI and trades at a third of the price. The gap won’t last. The institutions will figure it out. You need to see this first. Read the FREE Report Before They Notice."} +{"url": "https://www.fnnews.com/news/202604090857326831", "title": "호르무즈 계속 막은 이란 … 하루 통과 10여척으로 제한 계획 ", "publish_date": "2026-04-09T01:20:13Z", "full_text": "암호화폐·중국 위안화로 통행료 지급해야…\"혁명수비대 승인 필수\" 통행량 하루 135척→한 자릿수 급감…원유 공급망·물가 압박 우려 확산\n\n\n\n\n\n호르무즈 계속 막은 이란…\"하루 통과 10여척으로 제한 계획\"암호화폐·중국 위안화로 통행료 지급해야…\"혁명수비대 승인 필수\"통행량 하루 135척→한 자릿수 급감…원유 공급망·물가 압박 우려 확산(서울=연합뉴스) 김승욱 기자 = 이란이 미국과의 휴전 합의 후에도 세계 핵심 에너지 수송로인 호르무즈 해협 통제를 유지하면서 하루 통과 선박 수를 약 10여척 수준으로 제한하는 방안을 추진 중인 것으로 전해졌다.월스트리트저널(WSJ)은 8일(현지시간) 아랍권 중재자들을 인용해 이란이 최근 체결된 2주간의 휴전 기간에도 이 같이 선박 통행을 엄격히 제한하고 통행료를 부과할 계획을 밝혔다고 보도했다.보도에 따르면 이란은 호르무즈 해협을 지나는 선박이 자국 정예 군사조직인 이슬람혁명수비대(IRGC)와 사전 조율을 거치도록 요구하고 있다. 통과 선박은 사전에 통행료를 협의한 뒤 암호화폐나 중국 위안화로 비용을 지급해야 한다.호르무즈 해협 통행량은 지난 2월 28일 전쟁 개시 이후 급감했다.에너지 정보업체 S&P 글로벌 마켓 인텔리전스에 따르면 휴전 선언 직후인 이날도 호르무즈 해협을 통과한 선박은 4척에 불과해, 전쟁 이전 하루 약 135척이 오가던 것과 비교할 수 없다.전격적인 휴전 합의로 호르무즈를 둘러싼 긴장이 완화되는 듯했지만, 발표 후에도 이스라엘의 레바논 공습 지속과 이란 측의 '보복 검토' 소식이 전해지면서 해협 통행은 다시 중단된 상태라고 현지 매체들은 전했다.전쟁 기간 이란은 허가 없이 통과하려는 선박을 공격하면서 해협에 대한 사실상의 통제권을 확보했으며, 이번 휴전 국면에서는 이를 아예 제도화하려는 움직임을 보인다.특히 이란은 자국 또는 우호국 선박에는 통행을 허용하거나 낮은 비용을 부과하는 반면, 미국이나 이스라엘과 연계된 국가 선박은 차단하는 차등 체계를 구축 중인 것으로 알려졌다.선박 운항 경로도 제한된다. 통과가 허용된 선박들은 기존 항로 대신 이란 게슘섬과 라라크섬 사이, 이란 연안을 따라 오만만으로 빠져나가는 좁은 통로를 이용해야 한다.통행료는 선박 규모에 따라 차등 적용되며, 초대형 유조선의 경우 최대 200만 달러(약 30억 원)에 이를 수 있다는 게 해운업계 전언이다.이란 의회도 통행 승인과 수수료 부과를 포함한 새로운 해협 관리 방안을 승인한 것으로 전해졌다. 이란은 통행료 수익을 오만과 분담하는 방안도 제시했지만, 오만은 아직 동의하지 않은 상태라고 WSJ은 전했다.이란의 이 같은 조치는 국제사회에 큰 파장을 낳고 있다.호르무즈 해협은 세계 원유·LNG 공급 물량의 약 20%가 지나는 요충지다. 이란이 통제권을 행사할 경우 글로벌 에너지 시장과 물가에 직접적인 충격이 불가피하다는 우려가 나온다.미국은 여전히 '자유로운 항행'을 요구하고 있지만, 이란은 물러설 기미를 보이지 않고 있다. 실제로 이란은 무선 교신을 통해 혁명수비대 승인 없이 해협을 통과할 경우 공격 대상이 될 수 있다고 경고한 것으로 전해졌다.이란이 통과 선박들이 혁명수비대 승인을 받아야 하는 이유 중 하나로 내세우는 건 자국이 설치한 기뢰다. 기뢰를 피하기 위해서는 이란군과 조율해 안내를 받아야 한다는 게 이란 측 입장이다.하지만 이란의 해협 통제는 국제법 위반이라는 지적이 나온다. 자연 해협에 해당하는 호르무즈는 운하와 달리 통행료 부과가 허용되지 않는다는 점에서 이란의 조치는 유엔해양법협약(UNCLOS)에 위반된다는 것이다.중동 산유국들과 주요 에너지 수입국들은 강하게 반발하고 있다.특히 일부 통행료가 위안화로 부과되는 점은 서방의 원유 시장 영향력 약화를 초래할 수 있다는 점에서 우려를 키우고 있다고 WSJ은 짚었다.전문가들은 휴전이 유지되더라도 이란이 명확한 안전 보장 방안을 제시하지 않는 한 선박 운항이 정상화되기까지는 상당한 시간이 걸릴 것으로 보고 있다.해운업계 관계자는 \"현재로서는 선박별로 허가 여부가 달라지는 상황이라 사실상 원유 수송 흐름이 거의 멈춘 상태\"라며 \"불확실성이 해소되기 전까지 선사들이 운항 재개를 주저할 수밖에 없다\"고 말했다.ksw08@yna.co.kr(끝)<저작권자(c) 연합뉴스, 무단 전재-재배포, AI 학습 및 활용 금지>\n\n※ 저작권자 ⓒ 연합뉴스, 무단전재-재배포 금지"} +{"url": "https://baotintuc.vn/thi-truong-tien-te/gia-dau-giam-manh-khi-ky-vong-khoi-thong-eo-bien-hormuz-gia-tang-20260409072028597.htm", "title": "Giá dầu giảm mạnh khi kỳ vọng khơi thông eo biển Hormuz gia tăng", "publish_date": "2026-04-09T01:20:13Z", "full_text": "Tháp khoan dầu tại Luling, Texas, Mỹ. Ảnh: THX/TTXVN\n\nDiễn biến này thắp lên hy vọng khôi phục hoàn toàn dòng chảy năng lượng qua eo biển Hormuz - nơi trung chuyển khoảng 20% lượng dầu toàn cầu - và giúp xoa dịu đáng kể những lo ngại về lạm phát tăng cao cho kinh tế thế giới.\n\nTheo đó, giá dầu Brent giao kỳ hạn sụt giảm 14,52 USD (tương đương 13,29%) và chốt phiên ở mức 94,75 USD/thùng. Giá dầu thô ngọt nhẹ Mỹ (WTI) lao dốc 18,54 USD (16,41%) xuống mức 94,41 USD/thùng.\n\nGiới chuyên gia phân tích nhận định đà giảm sốc này xuất phát từ tâm lý lạc quan rằng nguồn cung năng lượng toàn cầu sẽ sớm được khơi thông, sau thông báo về thỏa thuận ngừng bắn kéo dài 2 tuần giữa phía Mỹ và Iran. Phía Mỹ xác nhận một phái đoàn ngoại giao sẽ tới Pakistan vào cuối tuần này để tiến hành đàm phán với phía Iran.\n\nTuy nhiên, giới giao dịch vẫn duy trì sự thận trọng nhất định trước những rủi ro đổ vỡ thỏa thuận. Công ty nghiên cứu Capital Economics nhận định vấn đề then chốt đối với thị trường hiện nay vẫn là tình trạng thực tế tại eo biển Hormuz. Dù khuôn khổ thỏa thuận cho phép tàu chở dầu lưu thông, các điều khoản bảo đảm an toàn vẫn chưa rõ ràng, khiến nhiều hãng vận tải ngần ngại."} +{"url": "http://www.californiatelegraph.com/news/278972410/frp-holdings-inc-announces-release-date-for-its-2025-fourth-quarter-and-full-year-earnings-and-details-for-the-earnings-conference-call", "title": "FRP Holdings , Inc . Announces Release Date for Its 2025 Fourth Quarter and Full Year Earnings and Details for the Earnings Conference Call", "publish_date": "2026-04-09T01:20:13Z", "full_text": "On March 31, 2026, FRP Holdings, Inc. (NASDAQ:FRPH) announced that it had filed a Form 12b-25, Notification of Late Filing, with the Securities and Exchange Commission in connection with its Annual Report on Form 10-K for the fiscal year ended December 31, 2025. The Company and its independent auditors needed the additional time to complete the year end audit process and the delay in filing was not the result of any disagreements with the Company's independent auditors on any matter of accounting principles or practices, financial statement disclosure, or auditing scope or procedure.\n\nToday the Company announces that it anticipates issuing its fourth quarter and full year earnings results on Friday, April 10, 2026, and that it will file its Annual Report on Form 10-K for the fiscal year ended December 31, 2025 on or before April 15, 2026.\n\nThe Company will host a conference call on Friday, April 10, 2026, at 4:30 p.m. (ET). Analysts, stockholders and other interested parties may access the teleconference live by calling 1-888-506-0062 (passcode 751153) within the United States or by joining the webcast here. International callers may dial 1-973-528-0011 (passcode 751153). Webcast replay will be available until April 10, 2027, by accessing it here. The webcast replay will also be available on the Company's investor relations page (https://www.frpdev.com/investor-relations/) following the call.\n\nFRP Holdings, Inc. is a holding company engaged in the real estate business, namely (i) leasing and management of commercial properties owned by the Company, (ii) leasing and management of mining royalty land owned by the Company, (iii) real property acquisition, entitlement, development and construction primarily for apartment, retail, warehouse, and office, (iv) leasing and management of residential apartment buildings.\n\nInvestors are cautioned that any statements in this press release which relate to the future are, by their nature, subject to risks and uncertainties that could cause actual results and events to differ materially from those indicated in such forward-looking statements. These include, but are not limited to: the possibility that we may be unable to find appropriate investment opportunities; levels of construction activity in the markets served by our mining properties; demand for flexible warehouse/office facilities in the Baltimore- Washington-Northern Virginia area; demand for apartments in Washington D.C. and Greenville, South Carolina; our ability to obtain zoning and entitlements necessary for property development; the impact of lending and capital market conditions on our liquidity; our ability to finance projects or repay our debt; general real estate investment and development risks; vacancies in our properties; risks associated with developing and managing properties in partnership with others; competition; our ability to renew leases or re-lease spaces as leases expire; illiquidity of real estate investments; bankruptcy or defaults of tenants; the impact of restrictions imposed by our credit facility; the level and volatility of interest rates; environmental liabilities; inflation risks; cybersecurity risks; as well as other risks listed from time to time in our SEC filings; including but not limited to; our annual and quarterly reports. We have no obligation to revise or update any forward-looking statements, other than as imposed by law, as a result of future events or new information. Readers are cautioned not to place undue reliance on such forward-looking statements.\n\nContact: Matthew C. McNulty, Chief Financial Officer\n\n(904) 858-9100\n\nSOURCE: FRP Holdings, Inc."} +{"url": "https://africanmanager.com/wall-street-cloture-en-nette-hausse-soulagee-par-le-cessez-le-feu-en-iran/", "title": "Wall Street clôture en nette hausse , soulagée par le cessez - le - feu en Iran", "publish_date": "2026-04-09T01:20:13Z", "full_text": "La Bourse de New York a clôturé en franche hausse mercredi, les investisseurs continuant de saluer l’annonce d’un cessez-le-feu de deux semaines entre les Etats-Unis et l’Iran.\n\nLe Dow Jones a gagné 2,85%, l’indice Nasdaq a progressé de 2,80% et l’indice élargi S&P 500 s’est octroyé 2,51%.\n\n« Un sentiment de soulagement traverse le marché », commente auprès de l’AFP Angelo Kourkafas, analyste d’Edward Jones.\n\nWashington et Téhéran se sont accordés dans la nuit de mardi à mercredi pour une trêve de deux semaines qui laisse espérer une reprise du trafic dans le détroit d’Ormuz, par où transite habituellement un cinquième du brut mondial.\n\nLes prix du pétrole ont décroché dans la foulée, repassant sous le « seuil psychologique » des 100 dollars le baril. Cela « contribue à apaiser les craintes de récession, à revoir à la hausse les prévisions de croissance mondiale et à réduire les anticipations d’inflation », résume un analyste d’Interactive Brokers, d’où l’optimisme de Wall Street.\n\nSur le marché obligataire, après s’être détendu en début de séance, le rendement à dix ans des emprunts de l’Etat américain restait finalement stable. Vers 20H15 GMT, il évoluait autour de 4,29%.\n\nA la cote, le secteur de l’énergie s’est replié, entraîné par la chute des cours du pétrole.\n\nLe géant pétrolier Chevron a perdu 4,34%, ConocoPhillips a reculé de 4,93% et EOG Resources, de 3,61%.\n\nAutre grand nom du secteur des hydrocarbures, ExxonMobil a lâché 4,70% à 156,21 dollars. Le groupe a indiqué mercredi que les perturbations causées par la guerre au Moyen-Orient allaient réduire d’environ 6% sa production mondiale de pétrole au premier trimestre, par rapport au trimestre précédent.\n\nA l’inverse, les entreprises grandes consommatrices de pétrole ont soufflé."} +{"url": "https://www.lavanguardia.com/participacion/cartas/20260409/11508990/actualitzar-l-irpf.html", "title": "Actualitzar lIRPF", "publish_date": "2026-04-09T01:20:13Z", "full_text": "Ara que la inflació ha baixat i que la recaptació de l’Estat s’ha incrementat notablement, per què el Govern espanyol no abaixa l’impost de la renda, que no s’ha actualitzat des del 2007? Una baixada, encara que fos petita, ajudaria els consumidors i el gruix de la població a millorar el seu poder adquisitiu. Caldria que, abans d’emprendre una reforma global de l’IRPF, s’apliqués com a mesura transitòria una baixada d’aquest impost. Penso que seria bo per a tothom.\n\nRosa Martí Conill\n\nSubscriptora Parets del Vallès"} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-08/Full_text/full_text_macro_yields_dollar.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-08/Full_text/full_text_macro_yields_dollar.jsonl new file mode 100644 index 0000000..ffa495a --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-08/Full_text/full_text_macro_yields_dollar.jsonl @@ -0,0 +1,10 @@ +{"url": "https://lasillarota.com/hidalgo/estado/2026/4/8/encuentro-nacional-de-bordado-reune-mas-de-cien-artesanos-en-tenango-de-doria-593743.html", "title": "Encuentro Nacional de Bordado reúne a más de cien artesanos en Tenango de Doria", "publish_date": "2026-04-09T01:21:11Z", "full_text": "Comparta este artículo\n\nTenango.— Con la participación de más de un centenar de expositores provenientes de estados como Sinaloa, Querétaro, Puebla, Guerrero, Oaxaca e Hidalgo, Tenango de Doria fue cede del Encuentro Nacional de Bordadoras y Bordadores, que inició este miércoles 8, Día del Tenango, y concluirá el viernes 10 de abril.\n\nEn la Plaza de Armas, en la cabecera municipal de Tenango, se instalaron más de cien expositores, con una oferta variada de textiles bordados desde blusas, vestidos camisas en distintas técnicas, y cincuenta espacios destinados a cocineras y cocineros tradicionales de Hidalgo y los estados invitados.\n\nCrédito: Jessica Manilla\n\nLa secretaria de Turismo de Hidalgo, Elizabeth Quintanar Gómez, recordó que los bordados de tenangos son piezas elaboradas por manos de artesanas otomí-tepehua que han logrado posicionarse a nivel internacional, e insistió en que aún es necesario reforzar su denominación de origen.\n\nCrédito: Jessica Manilla\n\n“Ese bordado multicolor nació en Tenango de Doria, y es fundamental que el mundo lo sepa. Es una expresión que cuenta la historia de nuestros antepasados y representa la riqueza viva de nuestras comunidades”.\n\nCrédito: Jessica Manilla\n\nExpuso que el encuentro de bordadores y bordadoras permite generar enlace entre artesanos de distintas regiones del país, quienes comparten técnicas, historias y significados detrás de cada pieza, dignificando el trabajo artesanal.\n\nCrédito: Jessica Manilla\n\nLa presidenta municipal, Martha López Patricio, celebró que el encuentro se realizara en el marco de la conmemoración del Día del Tenango. “Hoy es un día especial porque mostramos al mundo la grandeza de nuestras artesanas y artesanos, quienes con sus manos crean verdaderas obras de arte que nos dan identidad”.\n\nCrédito: Jessica Manilla\n\nA lo largo de tres días, los asistentes podrán adquirir piezas únicas, participar en actividades culturales y conocer de cerca el proceso creativo detrás del bordado tradicional, con un programa que se complementa con presentaciones de danza, música, conferencias, conversatorios con artesanas, pasarelas, demostraciones.\n\n“Debemos sentirnos muy orgullosos de lo que se crean en las localidades del municipio; debemos celebrar el talento, la creatividad y todo aquello que nos da identidad. Todos son bienvenidos a vivir esta fiesta de color, en la tierra del donde se borda y se toma café. ¡Que viva el arte que nos da identidad! ¡Viva Los Bordados Tenangos! ¡Bienvenidos todos!”.\n\nsjl"} +{"url": "https://africanmanager.com/wall-street-cloture-en-nette-hausse-soulagee-par-le-cessez-le-feu-en-iran/", "title": "Wall Street clôture en nette hausse , soulagée par le cessez - le - feu en Iran", "publish_date": "2026-04-09T01:21:11Z", "full_text": "La Bourse de New York a clôturé en franche hausse mercredi, les investisseurs continuant de saluer l’annonce d’un cessez-le-feu de deux semaines entre les Etats-Unis et l’Iran.\n\nLe Dow Jones a gagné 2,85%, l’indice Nasdaq a progressé de 2,80% et l’indice élargi S&P 500 s’est octroyé 2,51%.\n\n« Un sentiment de soulagement traverse le marché », commente auprès de l’AFP Angelo Kourkafas, analyste d’Edward Jones.\n\nWashington et Téhéran se sont accordés dans la nuit de mardi à mercredi pour une trêve de deux semaines qui laisse espérer une reprise du trafic dans le détroit d’Ormuz, par où transite habituellement un cinquième du brut mondial.\n\nLes prix du pétrole ont décroché dans la foulée, repassant sous le « seuil psychologique » des 100 dollars le baril. Cela « contribue à apaiser les craintes de récession, à revoir à la hausse les prévisions de croissance mondiale et à réduire les anticipations d’inflation », résume un analyste d’Interactive Brokers, d’où l’optimisme de Wall Street.\n\nSur le marché obligataire, après s’être détendu en début de séance, le rendement à dix ans des emprunts de l’Etat américain restait finalement stable. Vers 20H15 GMT, il évoluait autour de 4,29%.\n\nA la cote, le secteur de l’énergie s’est replié, entraîné par la chute des cours du pétrole.\n\nLe géant pétrolier Chevron a perdu 4,34%, ConocoPhillips a reculé de 4,93% et EOG Resources, de 3,61%.\n\nAutre grand nom du secteur des hydrocarbures, ExxonMobil a lâché 4,70% à 156,21 dollars. Le groupe a indiqué mercredi que les perturbations causées par la guerre au Moyen-Orient allaient réduire d’environ 6% sa production mondiale de pétrole au premier trimestre, par rapport au trimestre précédent.\n\nA l’inverse, les entreprises grandes consommatrices de pétrole ont soufflé."} +{"url": "https://newsradio1290wtks.iheart.com/content/2026-04-08-stocks-close-the-day-higher-as-oil-prices-plummet-over-iran-war-cease-fire/", "title": "Stocks Close The Day Higher As Oil Prices Plummet Over Iran War Cease Fire", "publish_date": "2026-04-09T01:21:11Z", "full_text": "Stocks surged and oil prices plunged Wednesday (April 8) after a fragile two-week ceasefire between the United States and Iran took effect, raising hopes for renewed oil shipments through the Strait of Hormuz and easing global market fears. The S&P 500 soared 2.5%, the Dow Jones Industrial Average jumped 1,325 points, and the Nasdaq composite rallied 2.8% after President Donald Trump announced the temporary ceasefire.\n\nBenchmark U.S. crude oil prices dropped more than 16%, falling below $95 per barrel, while Brent crude also saw a sharp decline. The drop reversed some of the increases that came after five weeks of conflict, which had blocked the vital oil passage and pushed prices above $119 per barrel at their peak. Iran’s foreign minister stated that oil tankers would be allowed to pass for the next two weeks under Iranian military supervision.\n\nAirline and travel stocks rebounded strongly, with United Airlines up 7.9% and Carnival cruise lines climbing 9.6%. Delta Air Lines reported better-than-expected quarterly results, citing continued strong demand despite recent fuel price hikes. The positive momentum also spread globally, with Asia’s Nikkei 225 and Kospi indexes soaring over 5%, and major European markets such as Germany’s DAX and France’s CAC 40 rising over 4% each.\n\nDespite the optimism, analysts urged caution. The ceasefire remains fragile, with continued attacks reported in Iran, Israel, and Lebanon. The market’s upbeat response faded somewhat later in the day as questions lingered about whether the truce would hold and if shipping through the Strait of Hormuz would fully normalize.\n\nIn the bond market, Treasury yields fell, reflecting hopes that lower oil prices could allow the Federal Reserve to resume interest rate cuts later in the year. The yield on the 10-year Treasury note slipped to 4.29% from 4.33%."} +{"url": "https://newsradiowkcy.iheart.com/content/2026-04-08-stocks-close-the-day-higher-as-oil-prices-plummet-over-iran-war-cease-fire/", "title": "Stocks Close The Day Higher As Oil Prices Plummet Over Iran War Cease Fire | NewsRadio WKCY", "publish_date": "2026-04-09T01:21:11Z", "full_text": "Stocks surged and oil prices plunged Wednesday (April 8) after a fragile two-week ceasefire between the United States and Iran took effect, raising hopes for renewed oil shipments through the Strait of Hormuz and easing global market fears. The S&P 500 soared 2.5%, the Dow Jones Industrial Average jumped 1,325 points, and the Nasdaq composite rallied 2.8% after President Donald Trump announced the temporary ceasefire.\n\nBenchmark U.S. crude oil prices dropped more than 16%, falling below $95 per barrel, while Brent crude also saw a sharp decline. The drop reversed some of the increases that came after five weeks of conflict, which had blocked the vital oil passage and pushed prices above $119 per barrel at their peak. Iran’s foreign minister stated that oil tankers would be allowed to pass for the next two weeks under Iranian military supervision.\n\nAirline and travel stocks rebounded strongly, with United Airlines up 7.9% and Carnival cruise lines climbing 9.6%. Delta Air Lines reported better-than-expected quarterly results, citing continued strong demand despite recent fuel price hikes. The positive momentum also spread globally, with Asia’s Nikkei 225 and Kospi indexes soaring over 5%, and major European markets such as Germany’s DAX and France’s CAC 40 rising over 4% each.\n\nDespite the optimism, analysts urged caution. The ceasefire remains fragile, with continued attacks reported in Iran, Israel, and Lebanon. The market’s upbeat response faded somewhat later in the day as questions lingered about whether the truce would hold and if shipping through the Strait of Hormuz would fully normalize.\n\nIn the bond market, Treasury yields fell, reflecting hopes that lower oil prices could allow the Federal Reserve to resume interest rate cuts later in the year. The yield on the 10-year Treasury note slipped to 4.29% from 4.33%."} +{"url": "https://whp580.iheart.com/content/2026-04-08-stocks-close-the-day-higher-as-oil-prices-plummet-over-iran-war-cease-fire/", "title": "Stocks Close The Day Higher As Oil Prices Plummet Over Iran War Cease Fire", "publish_date": "2026-04-09T01:21:11Z", "full_text": "Stocks surged and oil prices plunged Wednesday (April 8) after a fragile two-week ceasefire between the United States and Iran took effect, raising hopes for renewed oil shipments through the Strait of Hormuz and easing global market fears. The S&P 500 soared 2.5%, the Dow Jones Industrial Average jumped 1,325 points, and the Nasdaq composite rallied 2.8% after President Donald Trump announced the temporary ceasefire.\n\nBenchmark U.S. crude oil prices dropped more than 16%, falling below $95 per barrel, while Brent crude also saw a sharp decline. The drop reversed some of the increases that came after five weeks of conflict, which had blocked the vital oil passage and pushed prices above $119 per barrel at their peak. Iran’s foreign minister stated that oil tankers would be allowed to pass for the next two weeks under Iranian military supervision.\n\nAirline and travel stocks rebounded strongly, with United Airlines up 7.9% and Carnival cruise lines climbing 9.6%. Delta Air Lines reported better-than-expected quarterly results, citing continued strong demand despite recent fuel price hikes. The positive momentum also spread globally, with Asia’s Nikkei 225 and Kospi indexes soaring over 5%, and major European markets such as Germany’s DAX and France’s CAC 40 rising over 4% each.\n\nDespite the optimism, analysts urged caution. The ceasefire remains fragile, with continued attacks reported in Iran, Israel, and Lebanon. The market’s upbeat response faded somewhat later in the day as questions lingered about whether the truce would hold and if shipping through the Strait of Hormuz would fully normalize.\n\nIn the bond market, Treasury yields fell, reflecting hopes that lower oil prices could allow the Federal Reserve to resume interest rate cuts later in the year. The yield on the 10-year Treasury note slipped to 4.29% from 4.33%."} +{"url": "https://lecourrier.vn/wall-street-cloture-en-nette-hausse-soulagee-par-le-cessez-le-feu-en-iran/1345035.html", "title": "Wall Street clôture en nette hausse , soulagée par le cessez - le - feu en Iran", "publish_date": "2026-04-09T01:21:11Z", "full_text": "Wall Street clôture en nette hausse, soulagée par le cessez-le-feu en Iran\n\nLa Bourse de New York a clôturé en franche hausse mercredi 8 avril, les investisseurs continuant de saluer l'annonce d'un cessez-le-feu de deux semaines entre les États-Unis et l'Iran.\n\n>> Wall Street termine en hausse, espère une fin du conflit au Moyen-Orient\n\n>> Wall Street termine sans direction claire après les propos de Trump sur l'Iran\n\n>> Wall Street termine en hausse, espère une trêve entre Washington et Téhéran\n\nPhoto : AFP/VNA/CVN\n\nLe Dow Jones a gagné 2,85%, l'indice Nasdaq a progressé de 2,80% et l'indice élargi S&P 500 s'est octroyé 2,51%.\n\n\"Un sentiment de soulagement traverse le marché\", commente auprès de l'AFP, Angelo Kourkafas, analyste d'Edward Jones.\n\nWashington et Téhéran se sont accordés dans la nuit de mardi 7 avril à mercredi 8 avril pour une trêve de deux semaines qui laisse espérer une reprise du trafic dans le détroit d'Ormuz, par où transite habituellement un cinquième du brut mondial.\n\nLes prix du pétrole ont décroché dans la foulée, repassant sous le \"seuil psychologique\" des 100 dollars le baril, remarque Kourkafas.\n\nCela \"contribue à apaiser les craintes de récession, à revoir à la hausse les prévisions de croissance mondiale et à réduire les anticipations d'inflation\", résume Jose Torres, d'Interactive Brokers, d'où l'optimisme de Wall Street.\n\nMalgré l'annonce d'une réouverture du détroit d'Ormuz, rares étaient les navires mercredi 8 avril à se risquer dans ce passage, signe d'une prudence encore extrême sur la suite du conflit.\n\n\"En fonction des gros titres (...) la volatilité pourrait revenir\" sur la place new-yorkaise, estime Angelo Kourkafas.\n\n\"Wall Street n'est pas encore tirée d'affaire\", abonde Jose Torres.\n\nSur le marché obligataire, après s'être détendu en début de séance, le rendement à dix ans des emprunts de l'Etat américain restait finalement stable. Vers 20h15 GMT, il évoluait autour de 4,29%.\n\nÀ la cote, le secteur de l'énergie s'est replié, entraîné par la chute des cours du pétrole.\n\nLe géant pétrolier Chevron a perdu 4,34%, ConocoPhillips a reculé de 4,93% et EOG Resources, de 3,61%.\n\nAutre grand nom du secteur des hydrocarbures, ExxonMobil a lâché 4,70% à 156,21 dollars. Le groupe a indiqué mercredi 8 avril que les perturbations causées par le conflit au Moyen-Orient allaient réduire d'environ 6% sa production mondiale de pétrole au premier trimestre, par rapport au trimestre précédent.\n\nÀ l'inverse, les entreprises grandes consommatrices de pétrole ont soufflé.\n\nParticulièrement malmenées ces dernières semaines, les compagnies aériennes ont été recherchées, à l'image de Delta Air Lines (+3,78%), American Airlines (+5,55%) ou Alaska Air Group (+8,11%).\n\nLe croisiériste Carnival a été propulsé de 11,23% et son concurrent Royal Caribbean a gagné 4,38%.\n\nLes groupes de livraison de plis et de colis (FedEx +4,59%, UPS +2,94%), également minés par le conflit, ont aussi pris de la vitesse mercredi 8 avril.\n\nDans un contexte d'appétit pour le risque, les valeurs liées au secteur des cryptomonnaies ont profité du rebond du bitcoin.\n\nLa plateforme d'échange Robinhood a pris 3,13% à 71,83 dollars et le \"mineur\" (créateur de monnaie numérique) Riot Platforms s'est envolé de 13,53% à 16,11 dollars.\n\nAFP/VNA/CVN"} +{"url": "https://www.dailyexcelsior.com/rupee-likely-to-stabilise-at-92-93-level-eac-pm-chairman/", "title": "Rupee likely to stabilise at 92 - 93 level : EAC - PM chairman", "publish_date": "2026-04-09T01:21:11Z", "full_text": "KOLKATA, Apr 8 : Chairman of the Economic Advisory Council to the Prime Minister (EAC-PM), S Mahendra Dev, on Wednesday said that Indian Rupee is expected to stabilise at the 92-93 level against the US dollar and expressed optimism that foreign investment flows will improve in the near future as geopolitical tensions ease and macroeconomic fundamentals remain strong.\n\nDev said the currency had faced pressure due to global uncertainties, including the recent conflict between the United States and Iran, and the withdrawal of foreign institutional investors (FII).\n\nHis remarks come after a temporary ceasefire between the US and Iran has helped calm global markets, easing fears of supply disruptions in the oil market and reducing volatility in currencies, including the Rupee.\n\n“Rupee is stabilising at 92-93. Because of global war-related headwinds and FII withdrawals, there was pressure. But despite these odds, Rupee will stabilise at these levels. One should not worry,” Dev said on the sidelines of the Bharat Chamber of Commerce interactive session.\n\nRupee had recently crossed more than 95 against the US dollar.\n\nThe chairman of the EAC-PM noted that India’s economic resilience and sound macroeconomic fundamentals provide the capacity to absorb external shocks.\n\n“The resilience of the Indian economy is strong. Our macro fundamentals are good, and we have fiscal space to absorb shocks. Many countries do not have that advantage,” he said.\n\nAccording to Dev, India’s fiscal position allows continued spending on infrastructure and welfare even during global uncertainty.\n\n“We can continue capital expenditure and social spending, which many countries cannot do. Our fiscal management is also good,” he said.\n\nHe also highlighted structural factors such as improvements in the debt-to-GDP ratio, ongoing economic reforms and technological advancements as elements that would encourage private sector investment and support higher growth.\n\nDev added that the current account deficit could go up to 2 per cent of the GDP, and our present level is about 1.3 per cent, so that is not posing a major concern.\n\nThe current account deficit can go up to around 2 per cent from the current level of 1.3 per cent, and “so we have headroom”, he said.\n\nHe also described the decision of the Reserve Bank of India’s Monetary Policy Committee (MPC) to keep policy rates unchanged as appropriate in the current economic environment.\n\nOn growth prospects, Dev said he remains optimistic that India will achieve 6.9 per cent and even 7 per cent growth in 2026-27 despite global uncertainties.\n\nWhile the RBI has projected growth at 6.9 per cent, the chairman of the EAC-PM said he was “more positive” about the outlook.\n\n“I am more positive. I was saying we can achieve even 7 per cent growth,” he said, citing recent economic performance as evidence of sustained momentum as India moves towards its goal of becoming a developed nation by 2047. (PTI)"} +{"url": "https://1019bigwaax.iheart.com/content/2026-04-08-stocks-close-the-day-higher-as-oil-prices-plummet-over-iran-war-cease-fire/", "title": "Stocks Close The Day Higher As Oil Prices Plummet Over Iran War Cease Fire", "publish_date": "2026-04-09T01:21:11Z", "full_text": "Stocks surged and oil prices plunged Wednesday (April 8) after a fragile two-week ceasefire between the United States and Iran took effect, raising hopes for renewed oil shipments through the Strait of Hormuz and easing global market fears. The S&P 500 soared 2.5%, the Dow Jones Industrial Average jumped 1,325 points, and the Nasdaq composite rallied 2.8% after President Donald Trump announced the temporary ceasefire.\n\nBenchmark U.S. crude oil prices dropped more than 16%, falling below $95 per barrel, while Brent crude also saw a sharp decline. The drop reversed some of the increases that came after five weeks of conflict, which had blocked the vital oil passage and pushed prices above $119 per barrel at their peak. Iran’s foreign minister stated that oil tankers would be allowed to pass for the next two weeks under Iranian military supervision.\n\nAirline and travel stocks rebounded strongly, with United Airlines up 7.9% and Carnival cruise lines climbing 9.6%. Delta Air Lines reported better-than-expected quarterly results, citing continued strong demand despite recent fuel price hikes. The positive momentum also spread globally, with Asia’s Nikkei 225 and Kospi indexes soaring over 5%, and major European markets such as Germany’s DAX and France’s CAC 40 rising over 4% each.\n\nDespite the optimism, analysts urged caution. The ceasefire remains fragile, with continued attacks reported in Iran, Israel, and Lebanon. The market’s upbeat response faded somewhat later in the day as questions lingered about whether the truce would hold and if shipping through the Strait of Hormuz would fully normalize.\n\nIn the bond market, Treasury yields fell, reflecting hopes that lower oil prices could allow the Federal Reserve to resume interest rate cuts later in the year. The yield on the 10-year Treasury note slipped to 4.29% from 4.33%."} +{"url": "https://santamariatimes.com/ap/business/oil-plunges-below-95-as-the-dow-surges-1-300-in-a-worldwide-rally-following/article_a54e11c8-bfe7-4866-8e05-38da805d67ae.html", "title": "Oil plunges below $95 as the Dow surges 1 , 300 in a worldwide rally following a ceasefire with Iran", "publish_date": "2026-04-09T01:21:11Z", "full_text": "Copyright 2026 The Associated Press. All rights reserved. This material may not be published, broadcast, rewritten or redistributed without permission."} +{"url": "https://www.gobankingrates.com/taxes/refunds/suze-orman-best-ways-use-large-tax-refund-to-become-financially-secure/", "title": "Suze Orman : 6 Best Ways To Use Tax Refund", "publish_date": "2026-04-09T01:21:11Z", "full_text": "Suze Orman: 6 Best Ways To Use a Large Tax Refund To Become Financially Secure\n\nMediapunch / Shutterstock.com\n\nCommitment to Our Readers GOBankingRates' editorial team is committed to bringing you unbiased reviews and information. We use data-driven methodologies to evaluate financial products and services - our reviews and ratings are not influenced by advertisers. You can read more about our editorial guidelines and our products and services review methodology. 20 Years\n\nHelping You Live Richer Reviewed\n\nby Experts Trusted by\n\nMillions of Readers\n\nTax refunds hit differently this year. Financial expert Suze Orman said that economists expect households to receive significantly larger refunds than usual due to new tax rules Congress passed last year.\n\nThe average federal tax refund of around $3,000 might rise by another $1,000 or more, according to some estimates. Orman’s concern is that people will spend the windfall rather than strengthen their financial position.\n\n“I want you to use any tax refund as an opportunity to build financial security, not just buy things,” Orman wrote in a recent blog post. She called the advice “extra important right now” given economic stress signals including slowed job growth and businesses increasingly using artificial intelligence for jobs previously requiring human staff.\n\nOrman recommended six specific uses for an unexpectedly large tax refund.\n\n1. Emergency Savings Gets Priority\n\nBuilding emergency reserves ranks first on Orman’s list. “Every dollar here gives you peace of mind and protection,” she said.\n\nThe recommendation makes particular sense given current economic uncertainty. Job security concerns have risen across multiple industries as companies explore AI replacements for human workers. An emergency fund covering three to six months of expenses provides breathing room if employment situations change suddenly.\n\nHigh-yield savings accounts currently offer around 4% to 5% annual percentage yields, meaning a $4,000 tax refund deposit immediately starts earning $160 to $200 yearly in interest while remaining accessible for emergencies.\n\nLearn More: Maximize Your Tax Refund by Avoiding This Common Mistake\n\n2. Attack Credit Card Debt Strategically\n\nOrman suggested paying down high-interest credit card debt but added an important qualifier. “First, see if you qualify for a zero-rate balance transfer credit card offer, then attack that balance,” she said.\n\nBalance transfer cards typically offer 0% APR for 12 to 21 months on transferred balances. Moving a $4,000 balance from a card charging 22% interest to a 0% promotional card saves approximately $880 in interest over a year while the entire payment goes toward principal.\n\nThe strategy requires discipline to pay off the balance before the promotional period ends. Missing that deadline means facing deferred interest charges or high ongoing rates.\n\n3. Maintenance Spending That Saves Money\n\nCar and home maintenance made Orman’s list as smart refund uses. “Avoiding costly repairs and extending the life of your current car means not having to deal with today’s insanely expensive new and used-car market,” she wrote.\n\nThe math supports this approach. Regular maintenance like oil changes, tire rotations and brake inspections costs hundreds of dollars but prevents thousands in major repairs. New car prices average over $48,000 while used cars that would have cost $20,000 a few years ago now run $30,000 or more.\n\nHome maintenance follows similar logic. “It not only can mean avoiding bigger repair costs down the line, but it also keeps the value of your home stronger,” Orman said. A $500 roof repair now prevents a $15,000 roof replacement later.\n\n4. Retirement Account Contributions\n\nBoosting retirement savings made the list with specific numbers. “For 2026, the Roth IRA contribution limit has increased to $7,500 ($8,600 if you’re 50 or older),” Orman noted.\n\nA $4,000 tax refund deposited into a Roth IRA grows tax-free for decades. Assuming 7% average annual returns, that $4,000 becomes approximately $31,000 in 30 years without any additional contributions. The Roth structure means withdrawals in retirement come out completely tax-free.\n\nThe strategy works particularly well for younger workers who have time for compound growth to work its magic. Someone in their 30s depositing tax refunds annually into a Roth IRA builds substantial tax-free retirement wealth.\n\n5. Invest In Skills\n\nOrman’s final recommendation addressed job security concerns directly. “If you are worried about job security, especially in a field where artificial intelligence is already being used, consider how to make your resume as up-to-date as possible,” she said.\n\nShe suggested online courses or community college classes if current employers don’t cover continuing education costs. Spending $1,000 from a tax refund on professional certifications or skill development can mean the difference between staying employed or facing job searches in competitive markets.\n\nFields facing AI disruption including customer service, data entry, basic accounting and content creation all require workers to develop higher-level skills that complement rather than compete with automation.\n\n6. The Need Versus Want Question\n\nOrman wrapped her advice with a philosophical challenge. “Is this a need, or a want?” she asked readers to consider before spending refunds.\n\n“If there is any part of your financial life that gnaws at you right now, the kindest and smartest move you can make today is to limit your spending–be it a tax refund or your regular income–on wants,” Orman wrote. She emphasized that financial peace of mind represents the greatest need.\n\nThe discipline to direct windfall money toward security rather than consumption separates those who build wealth from those who perpetually struggle financially. Tax refunds represent found money that doesn’t appear in monthly budgets, making them psychologically easier to save or invest rather than spend.\n\nOrman’s hope is simple: “I hope you prove them wrong” about economists’ expectations that households will simply spend larger refunds this year."} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-08/Raw/raw_gdelt_asset_precious_metals_spot.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-08/Raw/raw_gdelt_asset_precious_metals_spot.jsonl new file mode 100644 index 0000000..aa1946e --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-08/Raw/raw_gdelt_asset_precious_metals_spot.jsonl @@ -0,0 +1,10 @@ +{"url": "https://www.nbd.com.cn/articles/2026-04-08/4329502.html", "url_mobile": "https://m.nbd.com.cn/articles/2026-04-08/4329502.html", "title": "4月以来公募基金调研超500次 ; 社保组合 、 养老金产品最新持仓曝光", "seendate": "20260409T010000Z", "socialimage": "", "domain": "nbd.com.cn", "language": "Chinese", "sourcecountry": "China"} +{"url": "https://www.cqnews.net/web/content_1491699358938636288.html", "url_mobile": "", "title": "生态优势转为发展胜势 - 华龙网", "seendate": "20260409T010000Z", "socialimage": "", "domain": "cqnews.net", "language": "Chinese", "sourcecountry": "China"} +{"url": "https://baijiahao.baidu.com/s?id=1861950725418214601", "url_mobile": "", "title": "黄金白银 , 大幅波动 ! 水贝市场 , 新变化→", "seendate": "20260409T010000Z", "socialimage": "", "domain": "baijiahao.baidu.com", "language": "Chinese", "sourcecountry": "China"} +{"url": "https://www.illawarramercury.com.au/story/9217560/everything-you-need-to-know-about-flying-with-pets-in-cabin/", "url_mobile": "", "title": "Everything you need to know about flying with pets in cabin | Illawarra Mercury", "seendate": "20260409T010000Z", "socialimage": "https://www.illawarramercury.com.au/images/transform/v1/crop/frm/QQwHRnUv9qYdvjDNLdqaup/896b97f1-f66e-4b4f-8523-cb5c1ac83776.jpg/r0_562_7952_4737_w1200_h630_fmax.jpg", "domain": "illawarramercury.com.au", "language": "English", "sourcecountry": "Australia"} +{"url": "https://finance.sina.com.cn/stock/hyyj/2026-04-09/doc-inhtwaie2175693.shtml", "url_mobile": "", "title": "中信建投 : 继续看好AI板块 尤其是光通信环节", "seendate": "20260409T004500Z", "socialimage": "https://n.sinaimg.cn/spider20260409/341/w800h341/20260409/4045-7cce34c97a4d09d83eb60e5509314cd5.jpg", "domain": "finance.sina.com.cn", "language": "Chinese", "sourcecountry": "China"} +{"url": "https://www.itbear.com.cn/html/2026-04/1264928.html", "url_mobile": "", "title": "逆境中破局前行 , 埃安换标推新高端品牌引领行业新变革 - 智能汽车 - ITBear比尔科技", "seendate": "20260409T004500Z", "socialimage": "", "domain": "itbear.com.cn", "language": "Chinese", "sourcecountry": "China"} +{"url": "https://www.163.com/dy/article/KQ2DKDEO05198UNI.html", "url_mobile": "https://m.163.com/dy/article/KQ2DKDEO05198UNI.html", "title": "无惧地缘逆风 ! 高盛 : AI支出浪潮汹涌 , 布局 卖铲人 正当时|人工智能", "seendate": "20260409T004500Z", "socialimage": "", "domain": "163.com", "language": "Chinese", "sourcecountry": "China"} +{"url": "https://news.ycwb.com/ikimvkotkb/content_54054001.htm", "url_mobile": "", "title": "广州发布专业市场转型升级三年行动方案 508家专业市场将焕新", "seendate": "20260409T004500Z", "socialimage": "https://www.ycwb.com/images/jyw_QQWeChat_transmit.jpg", "domain": "news.ycwb.com", "language": "Chinese", "sourcecountry": "China"} +{"url": "https://www.finanznachrichten.de/nachrichten-2026-04/68152259-alkane-resources-limited-march-2026-quarter-production-update-399.htm", "url_mobile": "", "title": "Alkane Resources Limited : March 2026 Quarter Production Update", "seendate": "20260409T004500Z", "socialimage": "https://ml.globenewswire.com/media/ZTYzMjdhMWUtZGVhNC00N2U4LThjYTAtZWUyN2M1NThjMjEwLTEzMTU5NzYtMjAyNi0wNC0wOC1lbg==/tiny/Alkane-Resources-Limited.png", "domain": "finanznachrichten.de", "language": "English", "sourcecountry": "Germany"} +{"url": "https://www.163.com/dy/article/KQ2E94OS05118O8G.html", "url_mobile": "https://m.163.com/dy/article/KQ2E94OS05118O8G.html", "title": "早报|B站推出播放页暂停广告 / GoPro启动大规模裁员 / Meta时隔9个月再发大模型 , 被指 「 图表造假 」 ", "seendate": "20260409T004500Z", "socialimage": "", "domain": "163.com", "language": "Chinese", "sourcecountry": "China"} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-08/Raw/raw_gdelt_macro_central_banks.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-08/Raw/raw_gdelt_macro_central_banks.jsonl new file mode 100644 index 0000000..4b28808 --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-08/Raw/raw_gdelt_macro_central_banks.jsonl @@ -0,0 +1,10 @@ +{"url": "https://www.zonebourse.com/actualite-bourse/royaume-uni-les-acheteurs-immobiliers-marquent-le-pas-face-a-la-remontee-des-taux-selon-la-rics-ce7e50dbda8ef124", "url_mobile": "", "title": "Royaume - Uni : les acheteurs immobiliers marquent le pas face à la remontée des taux , selon la RICS", "seendate": "20260409T010000Z", "socialimage": "https://cdn.zonebourse.com/static/resize/0/0/images/reuters/2026-04/2026-04-08T230420Z_1_LYNXMPEM371CY_RTROPTP_4_BRITAIN-ECONOMY.JPG", "domain": "zonebourse.com", "language": "French", "sourcecountry": "France"} +{"url": "https://www.clactonandfrintongazette.co.uk/news/national/26005807.rising-mortgage-costs-dent-buyer-demand-amid-housing-market-mood-shift/", "url_mobile": "", "title": "Rising mortgage costs dent buyer demand amid housing market mood shift ", "seendate": "20260409T010000Z", "socialimage": "https://www.clactonandfrintongazette.co.uk/resources/images/20763503.jpg?type=og-image", "domain": "clactonandfrintongazette.co.uk", "language": "English", "sourcecountry": "United Kingdom"} +{"url": "https://www.northwichguardian.co.uk/news/national/26005807.rising-mortgage-costs-dent-buyer-demand-amid-housing-market-mood-shift/", "url_mobile": "", "title": "Rising mortgage costs dent buyer demand amid housing market mood shift ", "seendate": "20260409T010000Z", "socialimage": "https://www.northwichguardian.co.uk/resources/images/20763503.jpg?type=og-image", "domain": "northwichguardian.co.uk", "language": "English", "sourcecountry": "United Kingdom"} +{"url": "https://www.dunya.com/kose-yazisi/gunde-ortalama-18-milyar-tl/820965", "url_mobile": "", "title": "Günde ortalama 18 milyar TL - Naki BAKIR", "seendate": "20260409T004500Z", "socialimage": "https://image.dunya.com/rcman/Cw1280h720q95gc/storage/files/images/2026/02/26/para-kiq6_cover.jpg", "domain": "dunya.com", "language": "Turkish", "sourcecountry": "Turkey"} +{"url": "https://www.fnnews.com/news/202604090630516306", "url_mobile": "https://www.fnnews.com/ampNews/202604090630516306", "title": "경기 불황에 카드 돌려막기 6개월 만에 반등 … 연체율도 20년새 최고", "seendate": "20260409T004500Z", "socialimage": "https://image.fnnews.com/resource/media/image/2026/04/09/202604090630489611_l.jpg", "domain": "fnnews.com", "language": "Korean", "sourcecountry": "South Korea"} +{"url": "https://newsradio1290wtks.iheart.com/content/2026-04-08-stocks-close-the-day-higher-as-oil-prices-plummet-over-iran-war-cease-fire/", "url_mobile": "", "title": "Stocks Close The Day Higher As Oil Prices Plummet Over Iran War Cease Fire", "seendate": "20260409T004500Z", "socialimage": "https://i.iheart.com/v3/re/assets.getty/69d6cabbab0909491c4ab0bc?ops=gravity(%22north%22),fit(1200,675),quality(65)", "domain": "newsradio1290wtks.iheart.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://www.watfordobserver.co.uk/news/national/26005807.rising-mortgage-costs-dent-buyer-demand-amid-housing-market-mood-shift/", "url_mobile": "", "title": "Rising mortgage costs dent buyer demand amid housing market mood shift ", "seendate": "20260409T004500Z", "socialimage": "https://www.watfordobserver.co.uk/resources/images/20763503.jpg?type=og-image", "domain": "watfordobserver.co.uk", "language": "English", "sourcecountry": "United Kingdom"} +{"url": "https://newsradiowkcy.iheart.com/content/2026-04-08-stocks-close-the-day-higher-as-oil-prices-plummet-over-iran-war-cease-fire/", "url_mobile": "", "title": "Stocks Close The Day Higher As Oil Prices Plummet Over Iran War Cease Fire | NewsRadio WKCY", "seendate": "20260409T004500Z", "socialimage": "https://i.iheart.com/v3/re/assets.getty/69d6cabbab0909491c4ab0bc?ops=gravity(%22north%22),fit(1200,675),quality(65)", "domain": "newsradiowkcy.iheart.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://www.stourbridgenews.co.uk/news/national/26005807.rising-mortgage-costs-dent-buyer-demand-amid-housing-market-mood-shift/", "url_mobile": "", "title": "Rising mortgage costs dent buyer demand amid housing market mood shift ", "seendate": "20260409T004500Z", "socialimage": "https://www.stourbridgenews.co.uk/resources/images/20763503.jpg?type=og-image", "domain": "stourbridgenews.co.uk", "language": "English", "sourcecountry": "United Kingdom"} +{"url": "https://www.dunya.com/kose-yazisi/fiyat-artisini-ihracat-kisitlamasi-ile-onlemenin-verdigi-zarar/820975", "url_mobile": "", "title": "Fiyat artışını ihracat kısıtlaması ile önlemenin verdiği zarar … ", "seendate": "20260409T004500Z", "socialimage": "https://img.dunya.com/rcman/Cw685h350q95gc/storage/files/images/2024/11/18/ferit-parlak-vahy.jpg", "domain": "dunya.com", "language": "Turkish", "sourcecountry": "Turkey"} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-08/Raw/raw_gdelt_macro_inflation_employment.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-08/Raw/raw_gdelt_macro_inflation_employment.jsonl new file mode 100644 index 0000000..1c7568c --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-08/Raw/raw_gdelt_macro_inflation_employment.jsonl @@ -0,0 +1,10 @@ +{"url": "https://baijiahao.baidu.com/s?id=1861950725418214601", "url_mobile": "", "title": "黄金白银 , 大幅波动 ! 水贝市场 , 新变化→", "seendate": "20260409T010000Z", "socialimage": "", "domain": "baijiahao.baidu.com", "language": "Chinese", "sourcecountry": "China"} +{"url": "https://www.ambito.com/economia/alfonso-prat-gay-no-hay-ningun-programa-economico-que-enamore-si-no-genera-empleo-y-produccion-n6264545", "url_mobile": "", "title": "Alfonso Prat Gay : No hay ningún programa económico que enamore si no genera empleo y producción", "seendate": "20260409T004500Z", "socialimage": "https://media.ambito.com/p/2ba11f6bb70b9497baf7f7b908f63c60/adjuntos/239/imagenes/043/288/0043288098/1200x675/smart/alfonso-prat-gay.jpeg", "domain": "ambito.com", "language": "Spanish", "sourcecountry": "Argentina"} +{"url": "https://finance.yahoo.com/markets/stocks/articles/why-carnival-ccl-stock-soaring-000547814.html", "url_mobile": "", "title": "Why Is Carnival ( CCL ) Stock Soaring Today", "seendate": "20260409T004500Z", "socialimage": "https://s.yimg.com/ny/api/res/1.2/ngn388ko3b08d06tsw2YWQ--/YXBwaWQ9aGlnaGxhbmRlcjt3PTEyMDA7aD02MDA-/https://media.zenfs.com/en/stockstory_922/2b1804a23038eb5d248e624fd4368dea", "domain": "finance.yahoo.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://www.fnnews.com/news/202604090857326831", "url_mobile": "https://www.fnnews.com/ampNews/202604090857326831", "title": "호르무즈 계속 막은 이란 … 하루 통과 10여척으로 제한 계획 ", "seendate": "20260409T004500Z", "socialimage": "https://image.fnnews.com/resource/media/image/2026/04/09/202604090857299888_l.jpg", "domain": "fnnews.com", "language": "Korean", "sourcecountry": "South Korea"} +{"url": "https://baotintuc.vn/thi-truong-tien-te/gia-dau-giam-manh-khi-ky-vong-khoi-thong-eo-bien-hormuz-gia-tang-20260409072028597.htm", "url_mobile": "", "title": "Giá dầu giảm mạnh khi kỳ vọng khơi thông eo biển Hormuz gia tăng", "seendate": "20260409T004500Z", "socialimage": "https://cdnmedia.baotintuc.vn/Upload/YZmStSDTjb0M07hFJ2gA/files/2026/04/01/dau-070426-1.jpg", "domain": "baotintuc.vn", "language": "Vietnamese", "sourcecountry": "Vietnam"} +{"url": "http://www.californiatelegraph.com/news/278972410/frp-holdings-inc-announces-release-date-for-its-2025-fourth-quarter-and-full-year-earnings-and-details-for-the-earnings-conference-call", "url_mobile": "", "title": "FRP Holdings , Inc . Announces Release Date for Its 2025 Fourth Quarter and Full Year Earnings and Details for the Earnings Conference Call", "seendate": "20260409T004500Z", "socialimage": "", "domain": "californiatelegraph.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://africanmanager.com/wall-street-cloture-en-nette-hausse-soulagee-par-le-cessez-le-feu-en-iran/", "url_mobile": "", "title": "Wall Street clôture en nette hausse , soulagée par le cessez - le - feu en Iran", "seendate": "20260409T004500Z", "socialimage": "https://cdnfr.africanmanager.com/wp-content/uploads/2022/12/wall.jpg", "domain": "africanmanager.com", "language": "French", "sourcecountry": "Tunisia"} +{"url": "https://www.kompas.com/tren/read/2026/04/09/063000865/rupiah-tembus-rp-17.100-per-dollar-as-ini-penyebab-pelemahannya-menurut", "url_mobile": "https://amp.kompas.com/tren/read/2026/04/09/063000865/rupiah-tembus-rp-17.100-per-dollar-as-ini-penyebab-pelemahannya-menurut", "title": "Rupiah Tembus Rp 17 . 100 per Dollar AS , Ini Penyebab Pelemahannya Menurut Ekonom", "seendate": "20260409T004500Z", "socialimage": "https://asset.kompas.com/crops/ASaxsAOxNSzkzhQ9fII4PNmEFnI=/0x0:1279x853/1200x675/filters:watermark(data/photo/2026/01/30/697c818d0ca91.png,0,-0,1)/data/photo/2026/03/03/69a634cd41d23.jpg", "domain": "kompas.com", "language": "Indonesian", "sourcecountry": "Indonesia"} +{"url": "https://www.lavanguardia.com/participacion/cartas/20260409/11508990/actualitzar-l-irpf.html", "url_mobile": "https://www.lavanguardia.com/participacion/cartas/20260409/11508990/actualitzar-l-irpf.amp.html", "title": "Actualitzar lIRPF", "seendate": "20260409T004500Z", "socialimage": "https://www.lavanguardia.com/images/default.jpg?b", "domain": "lavanguardia.com", "language": "Catalan", "sourcecountry": "Spain"} +{"url": "https://www.losandes.com.ar/agroindustria/cosechar-la-incertidumbre-la-preocupacion-el-valle-uco-que-obliga-repensar-el-modelo-productivo-n5986673", "url_mobile": "", "title": "Cosechar en la incertidumbre : la preocupación en el Valle de Uco que obliga a repensar el modelo productivo", "seendate": "20260409T004500Z", "socialimage": "https://media.losandes.com.ar/p/3858ec77baa8f4056a9d4f962673683f/adjuntos/368/imagenes/100/185/0100185618/1200x675/smart/vista-vinedos-del-valle-uco-el-final-del-otono-claudio-gutierrez.jpg", "domain": "losandes.com.ar", "language": "Spanish", "sourcecountry": "Argentina"} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-08/Raw/raw_gdelt_macro_yields_dollar.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-08/Raw/raw_gdelt_macro_yields_dollar.jsonl new file mode 100644 index 0000000..79380d8 --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-08/Raw/raw_gdelt_macro_yields_dollar.jsonl @@ -0,0 +1,10 @@ +{"url": "https://lasillarota.com/hidalgo/estado/2026/4/8/encuentro-nacional-de-bordado-reune-mas-de-cien-artesanos-en-tenango-de-doria-593743.html", "url_mobile": "", "title": "Encuentro Nacional de Bordado reúne a más de cien artesanos en Tenango de Doria", "seendate": "20260409T004500Z", "socialimage": "https://lasillarota.com/u/fotografias/m/2026/4/8/f1280x720-850385_982060_5050.jpeg", "domain": "lasillarota.com", "language": "Spanish", "sourcecountry": "Mexico"} +{"url": "https://africanmanager.com/wall-street-cloture-en-nette-hausse-soulagee-par-le-cessez-le-feu-en-iran/", "url_mobile": "", "title": "Wall Street clôture en nette hausse , soulagée par le cessez - le - feu en Iran", "seendate": "20260409T004500Z", "socialimage": "https://cdnfr.africanmanager.com/wp-content/uploads/2022/12/wall.jpg", "domain": "africanmanager.com", "language": "French", "sourcecountry": "Tunisia"} +{"url": "https://newsradio1290wtks.iheart.com/content/2026-04-08-stocks-close-the-day-higher-as-oil-prices-plummet-over-iran-war-cease-fire/", "url_mobile": "", "title": "Stocks Close The Day Higher As Oil Prices Plummet Over Iran War Cease Fire", "seendate": "20260409T004500Z", "socialimage": "https://i.iheart.com/v3/re/assets.getty/69d6cabbab0909491c4ab0bc?ops=gravity(%22north%22),fit(1200,675),quality(65)", "domain": "newsradio1290wtks.iheart.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://newsradiowkcy.iheart.com/content/2026-04-08-stocks-close-the-day-higher-as-oil-prices-plummet-over-iran-war-cease-fire/", "url_mobile": "", "title": "Stocks Close The Day Higher As Oil Prices Plummet Over Iran War Cease Fire | NewsRadio WKCY", "seendate": "20260409T004500Z", "socialimage": "https://i.iheart.com/v3/re/assets.getty/69d6cabbab0909491c4ab0bc?ops=gravity(%22north%22),fit(1200,675),quality(65)", "domain": "newsradiowkcy.iheart.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://whp580.iheart.com/content/2026-04-08-stocks-close-the-day-higher-as-oil-prices-plummet-over-iran-war-cease-fire/", "url_mobile": "", "title": "Stocks Close The Day Higher As Oil Prices Plummet Over Iran War Cease Fire", "seendate": "20260409T004500Z", "socialimage": "https://i.iheart.com/v3/re/assets.getty/69d6cabbab0909491c4ab0bc?ops=gravity(%22north%22),fit(1200,675),quality(65)", "domain": "whp580.iheart.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://lecourrier.vn/wall-street-cloture-en-nette-hausse-soulagee-par-le-cessez-le-feu-en-iran/1345035.html", "url_mobile": "", "title": "Wall Street clôture en nette hausse , soulagée par le cessez - le - feu en Iran", "seendate": "20260409T004500Z", "socialimage": "https://image.lecourrier.vn/MediaUpload/Medium/2026/04/09/062407-1.webp", "domain": "lecourrier.vn", "language": "French", "sourcecountry": "Vietnam"} +{"url": "https://www.dailyexcelsior.com/rupee-likely-to-stabilise-at-92-93-level-eac-pm-chairman/", "url_mobile": "", "title": "Rupee likely to stabilise at 92 - 93 level : EAC - PM chairman", "seendate": "20260409T004500Z", "socialimage": "https://www.dailyexcelsior.com/wp-content/uploads/2025/11/S-Mahendra-Dev.jpg", "domain": "dailyexcelsior.com", "language": "English", "sourcecountry": "India"} +{"url": "https://1019bigwaax.iheart.com/content/2026-04-08-stocks-close-the-day-higher-as-oil-prices-plummet-over-iran-war-cease-fire/", "url_mobile": "", "title": "Stocks Close The Day Higher As Oil Prices Plummet Over Iran War Cease Fire", "seendate": "20260409T004500Z", "socialimage": "https://i.iheart.com/v3/re/assets.getty/69d6cabbab0909491c4ab0bc?ops=gravity(%22north%22),fit(1200,675),quality(65)", "domain": "1019bigwaax.iheart.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://santamariatimes.com/ap/business/oil-plunges-below-95-as-the-dow-surges-1-300-in-a-worldwide-rally-following/article_a54e11c8-bfe7-4866-8e05-38da805d67ae.html", "url_mobile": "", "title": "Oil plunges below $95 as the Dow surges 1 , 300 in a worldwide rally following a ceasefire with Iran", "seendate": "20260409T004500Z", "socialimage": "https://bloximages.chicago2.vip.townnews.com/santamariatimes.com/content/tncms/assets/v3/editorial/a/54/a54e11c8-bfe7-4866-8e05-38da805d67ae/69d6e225ab7df.preview.jpg?crop=1024%2C538%2C0%2C72", "domain": "santamariatimes.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://www.gobankingrates.com/taxes/refunds/suze-orman-best-ways-use-large-tax-refund-to-become-financially-secure/", "url_mobile": "", "title": "Suze Orman : 6 Best Ways To Use Tax Refund", "seendate": "20260409T003000Z", "socialimage": "https://cdn.gobankingrates.com/wp-content/uploads/2023/12/Suze-Orman_shutterstock_editorial_4231729g-1.jpg", "domain": "gobankingrates.com", "language": "English", "sourcecountry": "United States"} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-10/Full_text/full_text_asset_metals_derivatives.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-10/Full_text/full_text_asset_metals_derivatives.jsonl new file mode 100644 index 0000000..11a84fa --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-10/Full_text/full_text_asset_metals_derivatives.jsonl @@ -0,0 +1,6 @@ +{"url": "https://wpdh.com/ixp/854/p/the-4-best-classic-diners-in-new-york-state/", "title": "The Best Classic Diners In New York State", "publish_date": "2026-04-10T19:51:20Z", "full_text": "New York doesn’t mess around when it comes to diners. These are the very best classic diners in the Empire State.\n\nFrom chrome railcars to neighborhood staples that haven’t changed in decades, the Empire State might have the deepest diner culture in the country.\n\nNow, a new breakdown is highlighting the classic diners that stand above the rest.\n\n#1: Historic Village Diner, Red Hook, New York\n\nGoogle Google loading...\n\nThis isn’t just a great diner. It’s a piece of American history. Located along Route 9 in Red Hook, the Historic Village Diner dates back to the 1920s and is a classic Silk City dining car.\n\nIt was originally called the “Halfway Diner” because it sat right between New York City and Albany, and that original name is still painted right on the building.\n\nFor all the news that the Hudson Valley is sharing, make sure to follow Hudson Valley Post on Facebook, and download the Hudson Valley Post Mobile App\n\nGoogle Google loading...\n\nIn 1988, it became the first diner in New York and just the fourth in the entire country to be listed on the National Register of Historic Places. That alone puts it in a different category.\n\nThis eatery is considered the gold standard of New York diner authenticity, a true living landmark.\n\n#2: Tom's Restaurant, New York City\n\nGoogle Google loading...\n\nIf this place looks familiar, there’s a reason.\n\nTom’s Restaurant sits at Broadway and West 112th Street in Manhattan’s Morningside Heights and has been around since the 1940s. It’s been run by the same Greek-American family for decades, which is becoming rare in New York City.\n\nPop culture helped make it famous. The exterior was used as the stand-in for Monk’s Café on Seinfeld, and it also inspired Suzanne Vega’s song “Tom’s Diner.”\n\nBut beyond the pop culture glory, it’s still a real diner. It remains a no-frills, working neighborhood diner that New Yorkers have relied on for generations.\n\n#3: Manory's Restaurant, Troy, New York\n\nGoogle Google loading...\n\nIf you want history, Manory’s delivers. This Troy staple first opened in 1913, making it the oldest restaurant in the city. More than a century later, it’s still doing what it’s always done.\n\nLocated in downtown Troy at Congress and 4th Streets, Manory’s feels like a true neighborhood spot. Nothing flashy, nothing over the top. The menu covers classic American comfort food with beloved signatures like grilled cinnamon rolls and milkshakes.\n\n#4: Cutchogue Diner, Long Island\n\nGoogle Google loading...\n\nOut on Long Island’s North Fork, the Cutchogue Diner feels like stepping into another era.\n\nThis one dates back to 1941 and still operates out of an original Kullman diner car. The structure itself is part of the experience. Chrome exterior, compact layout, and that unmistakable mid-century diner feel.\n\n#5 Eveready Diner, Hyde Park, New York\n\nGoogle Google loading...\n\nThe Eveready Diner in Hyde Park features a retro feeling, an expansive menu, milkshakes made the old-fashioned way, and a drive-thru.\n\nThe family-run business on Route 9 in FDR country was featured on the Food Network's hit show Diners, Drive-Ins and Dives.\n\nHow the Research Was Done\n\nGoogle Google loading...\n\nThis list with a deep dive into travel guides, food shows, historic records, and diner diehards.\n\nFrom there, each spot had to prove it was the real deal. We’re talking legit diner cars or true classic builds, decades of history, and a reputation that goes beyond just locals grabbing coffee.\n\nThe list was based on Roadfood references, Food Network features, Atlas Obscura entries, the National Register of Historic Places, and coverage from regional outlets.\n\nThese diners had to matter to their communities, not just exist in them. And just as important, this couldn’t turn into a New York City-only list. A real statewide “Big 4” had to stretch across the map.\n\n5 Hudson Valley Diners With The Best Portions\n\n5 Hudson Valley Diners With The Best Portions Whether we want something for breakfast, lunch or dinner, we can rely on diners in the Hudson Valley to have all of these options. Their prices, portions and relaxed environment makes it a space that we enjoy returning to.\n\nLet's see if you've been to these fan favorite diners in the Hudson Valley that are known for their best portions. Gallery Credit: Allison Kay, Facebook\n\nThe 10 Most Underrated Places To Live In New York"} +{"url": "https://www.oneidadispatch.com/2026/04/10/strawberry-pots/", "title": "Strawberry pot window make for striking , efficient displays", "publish_date": "2026-04-10T19:51:20Z", "full_text": "By JESSICA DAMIANO\n\nYou’ve seen them — those odd planters that look like buildings with windows and balconies on their sides. Maybe you’ve planted strawberries in them. Or maybe you’ve just never understood them.\n\nTypically made of terracotta, the pots are usually tall and urn-shaped, but shorter, wider options are also available.\n\nThey are, in fact, strawberry pots, and those windows are intended to hold soil and strawberries, keeping them off the ground as they grow and, therefore, protecting them from rotting. But think outside the pot, and you’ll find they make lovely (and efficient) displays for other plants, too.\n\nStriking yet practical displays\n\nThe fenestrated containers can be planted with succulents like hens and chicks. Consider the orange and yellow ‘Gold Nugget’ or the silver-haired ‘Cobweb’ varieties for an eye-catching display. In colder areas, the whole pot can be brought indoors for winter; just ensure the succulents get ample sunlight, and avoid overwatering.\n\nOr create a space-saving culinary herb garden by filling the “balcony” pockets with cooking essentials like parsley, sage, thyme, mint and oregano, placing the smaller species at the bottom of the pot and larger ones higher up. Then plant a tall herb like rosemary or basil in the opening at the top and — voila! — you’ve created an instant centerpiece. You might even incorporate a few dwarf marigolds for color.\n\nHerbs, too, can be brought indoors and grown (and used!) in the kitchen over winter.\n\nColorful trailing florals and vines\n\nTrailing flowers and vines make a statement as they spill from the containers’ openings. Keep it monochrome, or plant a rainbow of colors for a dazzling display.\n\nTrailing geraniums, petunias, and chartreuse or purple sweet potato vines can be alternated around the sides of the pot. A dramatic grass, like Cordyline ‘Festival,’ can be planted at the top of larger planters, black mondo grass in smaller ones.\n\nNasturtiums, million bells, trailing verbena and sweet alyssum also lend themselves nicely to the pots. Green ivies provide a more understated aesthetic.\n\nIf you don’t have a lot of sunlight, consider combining different varieties of caladium and coleus for a colorful display.\n\nKeeping it sufficiently watered\n\nRegardless of what you’re planting, ensuring water reaches the roots of every plant in a strawberry pot can pose a bit of a challenge — but there’s an easy solution.\n\nCut a piece of PVC piping slightly longer than the pot’s height, then drill holes 2 inches (5 centimeters) apart along its sides.\n\nAt planting time, add potting mix up to the pot’s bottom openings, then position the pipe vertically in the center. Insert plants through the holes (from the inside out), add more potting mix to reach the next level of openings and add more plants. Repeat until you reach the top of the pot, packing the soil tightly as you go.\n\nWater and fertilize through the pipe, which will be hidden as the centerpiece plant grows.\n\nStrawberry pots are available in various materials, but the traditional versions are made of clay, which can crack in freezing temperatures. If your area experiences cold winters, bring them indoors in autumn, either emptied of their annuals, cleaned and stored, or still housing tropicals, evergreens or herbs, and treat them as houseplants over winter.\n\nJessica Damiano writes regular gardening columns for The Associated Press. She publishes the award-winning Weekly Dirt Newsletter. Sign up here for weekly gardening tips and advice.\n\nFor more AP gardening stories, go to https://apnews.com/hub/gardening."} +{"url": "https://www.newsday.com/business/healthgrades-long-island-hospitals-patient-safety-ez30ovxf", "title": "Eight Long Island hospitals rank among the nation best for patient safety", "publish_date": "2026-04-10T19:51:20Z", "full_text": "Eight Long Island hospitals ranked among the best in the country for patient safety, according to a new report.\n\nThose Long Island hospitals represented the majority of the 12 New York State hospitals ranked by Healthgrades, a Denver, Colorado-based health care information company. The firm gave 438 hospitals over 40 states patient safety excellence awards based on the infrequency of preventable patient complications, according to Healthgrades.\n\nOf the eight hospitals who won the annual awards, six are in Northwell Health’s network: Plainview and Huntington hospitals, Long Island Jewish Medical Center, North Shore University Hospital, Mather and Glen Cove hospitals. This year was the first time Mather and Glen Cove Hospitals were awarded a patient safety award.\n\nThis year’s list also included Long Island Community Hospital, which is a part of NYU-Langone and was renamed NYU Langone Hospital — Suffolk last year, and, for the first time, Mount Sinai South Nassau hospital based in Oceanside.\n\nThe awards come amid high demand for health care on Long Island. These awards and other rankings can help patients evaluate a hospital, but, experts said, patients should look at multiple hospital rankings and consider their own needs when evaluating their options.\n\nSign up for the Daily Business newsletter Stay in the know on jobs, retail and all things business across Long Island. By clicking Sign up, you agree to our privacy policy.\n\nHealthgrades' ranking methodology\n\nHealthgrades used federal Medicaid and Medicare data from October 2021 through September 2024 to predict the number of patient safety incidents likely to occur at a particular hospital, such as death during surgery, ulcers, or a fall on hospital grounds, according to the company.\n\nHealthgrades tracks 13 different patient safety indicators, said David Bromall, vice president of quality solutions for Healthgrades. Among those is tracking whether foreign objects — like gauze or sponges — are left inside a person during a surgery. Any hospital where that happened in the three-year time frame Healthgrades analyzes is not considered for an award, Bromall said.\n\nThe company gives out its awards to the 10% of roughly 4,400 hospitals with the lowest rate of patient safety incidents, Bromall said.\n\nPeter Silver, chief quality officer and a senior vice president for Northwell Health, credited the health system’s awards to its care practices, which evaluate patients for fall risk to avoid accidental trips and encourage patient mobility to mitigate bed sores, for example.\n\nThe patient safety awards should not be the only criteria a patient uses to pick a hospital, but “part of that assessment process,” Bromall said.\n\nPatients should certainly be focused on safety, said Elisabeth Benjamin, vice president for health initiatives at the Community Service Society of New York. But she encouraged patients to look at other, independent review platforms, such as Leap Frog’s ratings, which she said offered more robust data.\n\n“I’m a big advocate of patients thinking about safety first,” Benjamin. But patients should also ask “who is in network? Do you have health insurance?”\n\nNeed for safety amid high demand\n\nDemand for health care on Long Island has grown on Long Island and nationally as the Baby Boomer generation has aged. As of 2020, those 65 and older represented 16.8% of the population of the U.S., or 55.8 million people, according to the U.S. Census.\n\nEmployment in the health care and social assistance sector has risen as well, to 263,611 people in the third quarter of 2025, the most recent period data is available, according to data from the New York State Department of Labor. That’s a 37% increase from the same period in 2010, 15 years ago.\n\nPatient safety has always been important, but hospital focus on safety has grown, particularly in the wake of the pandemic, Bromall said.\n\nAs demand continues to rise, hospitals need to have procedures in place to keep patients safe, no matter how busy they are, Silver said."} +{"url": "https://www.investorideas.com/news/2026/main/04101-cpi-inflation-energy-surge-market-impact.asp", "title": "March CPI Surges to 3 . 3 % as Iran War Drives Energy Costs Higher ; What It Means for Investors", "publish_date": "2026-04-10T19:51:20Z", "full_text": "March CPI Surges to 3.3% as Iran War Drives Energy Costs Higher; What It Means for Investors Share (Investorideas.com Newswire) a go-to platform for big investing ideas, including gold and silver stocks issues market commentary from deVere. This morning's inflation numbers came in about where most economists expected, and that alone was enough to keep stocks from selling off. The Bureau of Labor Statistics reported that consumer prices jumped 0.9% in March from the prior month — the biggest single-month move since 2022 — pushing the annual rate to 3.3%. Strip out food and energy and the picture is actually calmer: core CPI rose just 0.2% for the month and 2.6% year-over-year, both coming in a tick below what analysts had penciled in. None of this is a mystery. Oil prices ran past $100 a barrel multiple times in March after the Strait of Hormuz effectively shut down. Gas crossed $4 a gallon. Those costs hit household budgets fast and they hit businesses just as hard through transportation and logistics. The gap between headline and core inflation this month is essentially the Iran war showing up in the data. How Markets Are Taking It The Dow, S&P 500, and Nasdaq each opened up around 0.3% after the report dropped. The market's reaction says a lot — investors had already braced for a bad number, so meeting expectations passed as good news. The S&P 500 is now on pace for eight straight winning sessions after weeks of war-driven volatility. The 10-year Treasury yield is sitting around 4.3%. Gold pulled back a bit in early trading after three straight weeks of gains. The Fed Isn't Moving Anytime Soon The Fed has a problem. Headline inflation at 3.3% gives them no cover to cut rates, but core coming in soft means there's no real pressure to hike either. So they sit. Futures markets are pricing roughly a 45% chance of at least one cut before year-end — but that number moves up or down almost entirely based on what happens with the ceasefire and oil. The two-week ceasefire announced earlier this week knocked crude back down near $98. If that holds and the Strait reopens, energy prices ease, inflation cools, and the Fed gets room to act. If it falls apart over the weekend, all of that goes the other way fast. Where Investors Are Looking Energy stocks, gold, and anything commodity-linked have been the obvious plays in this environment, and today's data doesn't change that. Producers are still benefiting from elevated oil prices even with the ceasefire pullback. Gold has had a strong run with central banks buying steadily in the background, and that demand doesn't go away when geopolitical risk eases — it just changes character. For investors watching the broader market, the bigger question now shifts to earnings. JPMorgan, Wells Fargo, Citigroup, Goldman Sachs, and BlackRock all report next week. That's when we find out how much of this year's turbulence actually showed up in corporate results.\n\n\n\nExploring Mining Podcast with Investorideas - get mining stock news from TSX, TSXV, CSE, ASX, NASDAQ, NYSE companies plus interviews with CEO's and leading experts Check out the Exploring Mining podcast at Investorideas.com with host Cali Van Zant for the latest mining stock news and insightful interviews with top industry experts Latest episode: https://www.youtube.com/watch?v=iCe7YVAtHaU About Investorideas.com - Big Investing Ideas Investorideas.com is the go-to platform for big investing ideas. From breaking stock news to top-rated investing podcasts, we cover it all. Our original branded content includes podcasts such as Exploring Mining, Cleantech, Crypto Corner, Cannabis News, and the AI Eye. We also create free investor stock directories for sectors including mining, crypto, renewable energy, gaming, biotech, tech, sports and more. Public companies within the sectors we cover can use our news publishing and content creation services to help tell their story to interested investors. Paid content is always disclosed. Learn more about our news, PR and social media, podcast and content services at Investorideas.com https://www.investorideas.com/Investors/Services.asp Follow us on X @investorideas @stocknewsbites\n\nFollow us on Facebook https://www.facebook.com/Investorideas\n\nFollow us on YouTube https://www.youtube.com/c/Investorideas\n\n\n\nContact Investorideas.com\n\n800 665 0411\n\n\n\nDisclaimer/Disclosure: https://www.investorideas.com/About/Disclaimer.asp\n\nOur site does not make recommendations for the purchase or sale of stocks, services, or products. Nothing on our sites should be construed as an offer or solicitation to buy or sell products or securities. All investing involves risk and possible losses. This site is currently compensated for news publication and distribution, social media and marketing, content creation, and more. Disclosure is posted for each compensated news release and content published /created if required, but otherwise the news was not compensated for and was published for the sole interest of our readers and followers. Contact management and IR of each company directly regarding specific questions. More disclaimer info: More disclaimer and disclosure info is available at https://www.investorideas.com/ About/Disclaimer.asp Global investors must adhere to regulations of each country. Please read Investorideas.com's privacy policy."} +{"url": "https://www.penarthtimes.co.uk/news/26009421.major-airlines-cut-flights-hike-fares-fuel-costs-rise/", "title": "Major airlines cut flights and hike fares as fuel costs rise", "publish_date": "2026-04-10T19:51:20Z", "full_text": "The ongoing conflict in the Middle East between the US, Israel, and Iran has resulted in a recent spike in fuel prices.\n\nSeveral major airlines have already responded to this spike by increasing fares, adding or increasing fuel surcharges, and cutting flights.\n\nUK airline Skybus announced last week it had ceased all flights between Cornwall and London due to \"the huge rise in the global cost of fuel\" and \"a significant drop in new passenger bookings\".\n\nRyanair CEO Michael O'Leary also warned Brits to book their summer holidays “as quickly as you can” to avoid rising costs, due to the ongoing Middle East conflict.\n\nMore major airlines cut flights and increase prices amid rising fuel costs\n\nThree more major airlines have now cut flights and increased prices due to the rising cost of fuel caused by the ongoing conflict in the Middle East:\n\nAir India\n\nAir India this week announced it was increasing its fuel surcharge on domestic and international flights.\n\nThese revised fees came into effect for UK flights on Friday (April 10), although the airline assured passengers who have already booked tickets will be unaffected by the change.\n\nAir India said: \"For the avoidance of doubt, tickets that have already been issued prior to the above times will not attract the new surcharge unless customers seek date or itinerary changes that require a recalculation of the fare.\n\n\"Air India will review its surcharges periodically and make appropriate adjustments as the situation requires.\"\n\nAir India announced this week it was increasing its fuel surcharge. (Image: Getty Images)\n\nAir India usually operates more than 60 weekly flights between India and the UK, connecting cities like Delhi, Mumbai, Bengaluru, Ahmedabad, and Amritsar to London (Heathrow and Gatwick) and Birmingham.\n\nAir New Zealand\n\nAir New Zealand has been forced to cancel more flights due to the conflict in the Middle East, with routes in and out of Auckland, Wellington, and Christchurch impacted, according to the BBC .\n\nAirlines cut flights and hike fares as fuel prices surge https://t.co/p1uad5gOHk — BBC News (UK) (@BBCNews) April 7, 2026\n\nThese flight cancellations follow several others made by the airline last month.\n\nHowever, Air New Zealand said earlier this week that the \"vast majority\" of its customers affected by the cancellations were being offered alternative flights on the same day.\n\nAn airline spokesperson, via the BBC, said: \"Like airlines globally, we're experiencing jet fuel prices that are more than double what they would usually be.\"\n\nAir New Zealand serves the UK through a combination of codeshare partner flights and booking options from Heathrow and Manchester.\n\nIt works with partner airlines, including Singapore Airlines, British Airways, and United Airlines, to connect passengers via major hubs.\n\nDelta Airlines\n\nDelta Airlines also announced this week that it was cutting back the number of seats on its flights due to the rising fuel costs, The Independent reported.\n\nThe Airline, which operates numerous daily nonstop flights from London Heathrow (LHR), London Gatwick (LGW), and Edinburgh (EDI) to various US destinations, has already increased the price of its checked bag fee by US$10 (£7.45).\n\nNow, reduced seat numbers on Delta flights could result in airfare prices rising.\n\nThe 3 airlines that have entered liquidation or administration in 2026 (so far)\n\nSeveral airlines entered liquidation in 2025, according to the UK Civil Aviation Authority , including:\n\nBlue Islands Limited (UK) - November\n\nAir Kilroe Limited t/a Eastern Airways (UK) - November\n\nPlay Airlines (Iceland) - September\n\nThree airlines have entered administration or liquidation in 2026 (so far), resulting in the cancellation of more than 4,000 flights:\n\nMeanwhile, fellow chartered carrier Legend Airlines (Romania) has reportedly shut down.\n\nThe Street reported the airline has \"officially gone dormant\" after retiring two of its A340 planes.\n\nUK travel companies that have closed in 2026 (so far)\n\nFour UK travel companies have also ceased trading in 2026, resulting in the cancellation of flights and holiday packages to destinations around the world.\n\nThe four UK travel companies that have closed down in 2026 (so far) are:\n\nRegen Central Ltd\n\nGold Crest Holidays\n\nAsiara UK Ltd\n\nSimply Florida Travel Ltd\n\nAll four have ceased trading, according to Companies House, and have lost their Air Travel Organiser's Licence (ATOL).\n\nHave you been impacted by the recent flight cancellations or airfare price hikes caused by increased fuel prices? Let us know in the poll above or in the comments below."} +{"url": "https://wrco.com/news/2026/04/10/utilities-seek-federal-pause-on-grid-bidding-amid-ai-driven-power-demand", "title": "Utilities seek federal pause on grid bidding amid AI - driven power demand - WRCO", "publish_date": "2026-04-10T19:51:20Z", "full_text": "A coalition of electrical utilities, including two major players in Wisconsin’s power supply, is seeking federal intervention to pause competitive bidding for transmission projects needed to meet the vast energy needs of the data center boom.\n\nThe coalition filed a complaint with the Federal Energy Regulatory Commission (FERC) on Tuesday asking the agency to exempt at least some major grid upgrades from bidding, arguing “bureaucratic red tape” can tack months onto project timelines and strain the country’s ability to “achieve dominance” in artificial intelligence.\n\n“This complaint is about whether our country will seize, or squander, a generational chance to own the next century,” the utilities wrote.\n\nAmong the companies behind the complaint are Xcel Energy, owner of Northern States Power Company-Wisconsin, and American Transmission Company (ATC), which owns and operates transmission lines across much of Wisconsin.\n\nNational and statewide ratepayer advocacy groups reacted with alarm, casting the utilities’ request as a recipe for higher electricity bills.\n\n“Utilities rushing to catch a ride on the AI investment gold rush need to slow down and think about the impact their proposals are having,” wrote Wisconsin Citizens Utility Board Executive Director Tom Content, as customers “wake up like Groundhog Day to rate hikes well above the cost of living.”\n\nThe complaint and the pushback it prompted mark the latest phase in a long-standing fight over the benefits of opening the transmission market to competition.\n\nStiff competition\n\nFERC first introduced competitive bidding for regional transmission projects in 2011 after ratepayer advocates lobbied for change, arguing that the earlier process — allowing local monopolies to control all projects within their territories — all but guaranteed inflated costs.\n\nThe shift set off a race between developers angling for a piece of the action. When a developer wins a transmission project, it also picks up a new revenue stream: Regulators pre-approve developers’ “return on equity,” or profit on each dollar invested.\n\nDozens of developers have lined up for a piece of the action since the Midcontinent Independent System Operator (MISO), a nonprofit that manages the wholesale electricity market and grid for much of the Midwest, approved more than $10 billion in new transmission projects in 2022. A new round of projects approved in December 2024 added about $22 billion to the total, and the list of prospective bidders grew once again.\n\nConstruction is ongoing at the 350-plus-acre Beaver Dam Commerce Park where a Meta data center is being built, Jan. 20, 2026, in Beaver Dam, Wis. Some experts predict that data center electricity demand could reach up to 25% of the country’s total energy use within the next five years. (Joe Timmerman / Wisconsin Watch)\n\nSome are local utilities hoping to maintain control of their territory; others are powerful national utilities venturing outside of their turf, international developers wading into the U.S. market, and startup transmission developers backed by private equity firms.\n\nWhile the data center rush had already begun in the Midwest by the time MISO approved the latest set of transmission projects in 2024, the approved projects often couldn’t account for the scale and breakneck pace of the data center developments that emerged in the region soon after. With the boom now in full swing, the tenor of competition for transmission projects is changing.\n\nDebate over bidding benefits\n\nMISO, which is also responsible for picking a developer for each project, has favored lower-cost bids with more substantial “cost containment” measures designed to shield customers from budget overruns. Ratepayer advocates say the lower bids are proof the bidding requirements are working, pushing even major national utilities to underbid competitors.\n\nIn their complaint to FERC, the coalition of utilities — which calls itself the “Grid Acceleration Coalition” — argued the benefits of competition are “unproven.”\n\nProjects entirely within one utility’s territory aren’t subject to competitive bidding; those projects routinely exceed initial budgets by millions of dollars. While cheaper bids tend to win competitive projects, the utility group argued that even those projects aren’t immune to budget overruns.\n\nBut the core of the utilities’ case is about time, not money. They argue the bidding process adds months to project timelines without clear benefits.\n\nIn their view, those delays harm customers, in part by slowing the construction of transmission lines that could expand access to cheaper electricity and prevent blackouts, and pose national security risks.\n\n“These projects — expressways for power — are as critical to meeting today’s challenges as the Eisenhower interstate highway system was to prevailing in the Cold War,” the coalition argued in its complaint. “China has devoted itself to overtaking America as the world’s AI leader and is just months behind.”\n\nThe utilities pointed to a recent example in Wisconsin: Last month, MISO reversed its decision to award three substations in Fond du Lac, Ozaukee and Sheboygan counties to private-equity-backed startup Viridon, instead handing the projects to ATC.\n\nATC’s initial bid was more expensive than Viridon’s, but the company successfully argued it alone could build the substations in time to serve the nearby Vantage data center campus in Port Washington.\n\nMISO’s initial plans set a goal to complete the substations by 2033; the Port Washington data center plans to come online in early 2028. Though ATC emerged victorious, it told FERC that the 15-month delay between MISO’s initial approval of the substations and the reversal was “completely unnecessary.”\n\nRatepayer advocates and other observers, however, quickly pointed out that even noncompetitive projects run into delays. ATC’s Cardinal-Hickory Creek transmission line in southwest Wisconsin, for instance, came online in 2024 — more than a decade after MISO approved it — following prolonged legal battles with conservation groups.\n\n“All developers can experience construction delays,” said Claire Wayner, a senior associate with the clean energy nonprofit Rocky Mountain Institute. “It’s not like there’s a silver bullet.”\n\nOpponents also underscored that two competitively bid projects in the Southwest met their in-service date goals last year.\n\n“Competitive transmission projects have been shown to have a better track record of adhering to cost containment and completion schedules than noncompetitive projects,” said Paul Cicio, chair of the national Electricity Transmission Competition Coalition. “A moratorium would move us backward at precisely the wrong time.”\n\nThe back-and-forth over the merits of competition is nothing new, Wayner noted. “The tricky thing with transmission competition is that there are stories of projects from both sides of the aisle that support their positions.”\n\nThe push to pause competition\n\nThe utility group proposed two options to FERC: Allow MISO and a Southwestern regional grid operator to exempt projects from competitive bidding on a case-by-case basis or suspend competition entirely for the next five years — “a period pegged to when our country must begin building the infrastructure that will decide which nation wins the AI race.”\n\nThe utilities added that they don’t intend to “claw back” other projects already awarded or interrupt ongoing bidding processes.\n\nDuring that five-year period, national forecasts estimate data center electricity demand could reach up to 25% of the country’s total energy use. MISO alone projects that it may need to double its current pace of generation growth to avoid shortfalls in the near future.\n\nMISO’s territory, stretching from the Upper Midwest to Louisiana, has seen by far the most dramatic increase in data center capacity since 2020 relative to other regional grid networks.\n\nThe right of first refusal fight\n\nAfter FERC introduced competitive bidding in 2011, utility groups turned to state legislatures. The result: right-of-first-refusal (ROFR) laws that give established local utilities first dibs on transmission projects in their territories, including those planned by regional grid operators like MISO.\n\nUtilities prevailed in Minnesota and Michigan; Iowa’s Supreme Court struck down its ROFR law in 2023 after a national transmission developer challenged its constitutionality, and Illinois Gov. J.B. Pritzker vetoed an ROFR bill the same year.\n\nBut similar efforts have failed in Wisconsin. State lawmakers have consistently rejected ROFR proposals, including a 2025 bill sponsored by Assembly Speaker Robin Vos, R-Rochester.\n\nThe former site of the WE Energies power plant on Nov. 13, 2025, in Pleasant Prairie, Wis. As electric utilities race to build transmission to accommodate the data center boom, consumer advocates worry about affordability and the risk of stranded assets if the boom goes bust. (Joe Timmerman / Wisconsin Watch)\n\nWisconsin ratepayer advocates see the FERC complaint as a work-around. “It is another effort by the utilities to defeat competition,” Todd Stuart, executive director of the Wisconsin Industrial Energy Group, wrote in an email to Wisconsin Watch. “When they lose in state legislatures and then lose out on competitive bids,” he added, “they go back to FERC.”\n\nIn the utilities’ complaint, Xcel Energy cited Wisconsin’s lack of an ROFR law, and the resulting bidding process for projects in the state, as posing a risk of delaying upgrades needed to serve a data center across the border in Minnesota.\n\nThe company wouldn’t comment about the parallels between the options utilities suggested in the FERC complaint and ROFR laws. Instead, spokesman Kevin Coss pointed to permitting reforms in Minnesota — a 2024 law streamlining permitting for clean energy projects — as another example of the company’s efforts to “speed the buildout of critical infrastructure across our systems.” Xcel did not bid on any of the competitive projects in Wisconsin.\n\nIn a statement to Wisconsin Watch, ATC argued the options its coalition suggested to FERC “would not operate as a substitute” for an ROFR law, “even temporarily or on a case-by-case basis.”\n\nBuildout costs fall to ratepayers\n\nRegardless of who builds a transmission line, ratepayers cover the construction and maintenance costs through their electricity bills. We Energies estimates that transmission-related costs account for about 10% of customers’ bills.\n\nCustomers across the Upper Midwest share the costs of MISO-designed projects across multiple states, spreading costs among a larger number of ratepayers.\n\nBut billing practices vary. In some cases, utilities can only bill ratepayers for the costs of building a transmission project after it comes online. When ATC builds a transmission line, FERC allows the developer to begin billing customers while the line is still under construction.\n\nATC says this approach saves customers money in the long term by reducing interest on construction costs.\n\nRatepayer advocates see it differently. “Consumers are paying for projects without receiving the benefits,” Cicio said. Transmission projects take years to complete, and short-term increases in monthly electricity bills don’t square well with concerns about affordability and the risk of stranded assets if the AI boom goes bust.\n\nAdding to the frustration: a planned 9.2% electricity rate increase for We Energies customers in eastern Wisconsin over the next two years. That rate hike in part reflects the addition of generators, including new natural gas plants in Milwaukee and Kenosha counties, needed to meet data center demands.\n\nWisconsin’s Public Service Commission will soon decide how to divvy up costs of powering We Energies-served data centers — a decision that could set a statewide precedent."} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-10/Full_text/full_text_macro_central_banks.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-10/Full_text/full_text_macro_central_banks.jsonl new file mode 100644 index 0000000..e2d01d9 --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-10/Full_text/full_text_macro_central_banks.jsonl @@ -0,0 +1,8 @@ +{"url": "https://hitsfm.net/business/9a906e8ed2f1be1191aa6d7dc2574e4c", "title": "Business - HITS FM", "publish_date": "2026-04-10T19:48:06Z", "full_text": "A view of the vessels passing through the Strait of Hormuz following the two-week temporary ceasefire reached between the United States and Iran on the condition that the strait be reopened, seen in Oman, April 8, 2026. (Anadolu via Getty Images)\n\n(NEW YORK) -- Inflation surged in March after an oil shock triggered by the U.S.-Israeli war with Iran, government data showed on Friday. The inflation report matched economists' expectations.\n\nPrices rose 3.3% in March compared to a year earlier, marking a steep rise from a year-over-year inflation rate of 2.4% in the prior month. Annual inflation jumped to its highest level in two years, U.S. Bureau of Labor Statistics (BLS) data showed.\n\nThe jump in prices owed in large part to a sharp rise in costs for products impacted by the oil shortage. Gasoline prices were 25% higher in March than February, the BLS report said. Overall, energy prices jumped almost 12% from a month earlier.\n\nAirline fares increased 3.4% in March from February, the data showed.\n\nThe rapid acceleration of price increases could complicate interest rate policy at the Federal Reserve, which may be reluctant to lower borrowing costs as inflation climbs.\n\nThe Middle East conflict prompted Iran's effective closure of the Strait of Hormuz, a critical waterway that facilitates the transport of about one-fifth of the global supply of oil and natural gas.\n\nThat energy shortage sent oil and gasoline prices surging worldwide. Gasoline prices in the U.S. stood at $4.15 on average per gallon on Friday, marking a leap of $1.17 since the start of the war, AAA data showed.\n\nThe BLS collected price data over the entire month of March. The inflation report, in turn, reflected prices for 31 of the first 32 days of war, excluding the outbreak of hostilities on Feb. 28. The ceasefire announced on Tuesday came after 40 days of fighting.\n\nAs part of a two-week U.S.-Iran ceasefire announced on Tuesday, Iran says it will allow tankers passage through the Strait of Hormuz as long as they coordinate with the nation's military.\n\nThe resumption of tanker traffic remains uncertain, however. Tanker traffic was suspended on Wednesday after Israeli attacks on Lebanon, Iran's semi-official Fars News Agency reported.\n\nCrude prices fell after the ceasefire announcement but remained highly elevated. U.S. oil prices topped $98 a barrel as of Thursday, standing nearly 50% higher than their pre-war level.\n\nA surge in consumer prices could pose difficulty for the Fed as it weathers a slowdown of economic performance over recent months.\n\nIf the Fed opts to lower borrowing costs, it could spur growth but risk higher inflation. On the other hand, the choice to raise interest rates may slow price increases but raises the likelihood of a cooldown in economic performance.\n\nLast month, Federal Reserve Chairman Jerome Powell said that despite rising energy prices and the potential impact on inflation, he doesn't think the central bank needs to raise interest rates.\n\nPowell noted that central bankers often look past shocks -- such as sudden oil-price increases -- since the upward pressure on consumer prices usually proves temporary.\n\n\"We feel like our policy is in a good place for us to wait and see how that turns out,\" Powell said.\n\nThe benchmark interest rate stands at a level between 3.5% and 3.75%. That figure marks a significant drop from a recent peak attained in 2023, but borrowing costs remain well above a 0% rate established at the outset of the COVID-19 pandemic.\n\nThe Fed will announce its next rate decision on April 29. Investors overwhelmingly expect the Fed to leave rates unchanged, according to the CME FedWatch Tool, a measure of market sentiment.\n\nThe tool pegs a roughly 70% chance that the Fed will maintain interest rates at current levels for the remainder of the year.\n\nCopyright © 2026, ABC Audio. All rights reserved."} +{"url": "https://www.kacu.org/2026-04-10/inflation-surges-to-highest-level-in-nearly-2-years-as-energy-costs-spike", "title": "Inflation surges to highest level in nearly 2 years as energy costs spike", "publish_date": "2026-04-10T19:48:06Z", "full_text": "The U.S. war with Iran and the resulting spike in energy prices have pushed inflation to its highest level in nearly two years.\n\nA report from the Labor Department Friday showed consumer prices in March were up 3.3% from a year ago. That's the biggest annual increase since May of 2024. Prices jumped 0.9% between February and March, with higher gasoline prices accounting for nearly three-quarters of that increase.\n\nGas prices have jumped by more than a dollar a gallon, on average, since the U.S. and Israel launched their attack on Iran. Pump prices have remained high this week, despite a tentative ceasefire.\n\nHigher jet fuel prices also contributed to a jump in the cost of airline tickets last month, although food prices were flat, as rising costs for restaurant meals offset a decline in grocery prices.\n\nExcluding volatile food and energy prices, so-called \"core\" inflation was 2.6% in March.\n\nLoading...\n\nInflation spike reverses stabilizing trend\n\nAlthough inflation is nowhere near the four-decade high it reached in 2022, following Russia's invasion of Ukraine, progress on stabilizing prices fizzled out last year, partly as a result of President Trump's tariffs. The wartime jump in energy prices has pushed inflation even higher.\n\n\"We were making progress, making progress. Then we kind of stalled out and now it's been inching itself up the other way,\" Chicago Federal Reserve Bank President Austan Goolsbee told the Detroit Economic Club this week.\n\nGoolsbee worries that the longer inflation stays above the Federal Reserve's 2% target, the greater the risk that high inflation becomes baked into the economy. But a survey from the New York Fed this week showed that even though people expect higher inflation in the short run, they still believe it will come down in the long run.\n\nFed policymakers try not to overreact to a spike in gasoline prices, which are notorious for bouncing up and down. But core inflation has also been climbing, which is likely to make the central bank cautious about any quick cuts in interest rates.\n\nThe Fed is also keeping a close eye on the job market, which showed some signs of life in March when employers added 178,000 jobs, after cutting workers the previous month. While employers have not been adding a lot of jobs, they've been reluctant to lay people off as well.\n\n\"I think it's from uncertainty,\" Goolsbee said. \"I think that's what happens when businesses are uncertain and they say we're just going to sit on our hands until we figure out, is the war going to be a temporary shock?\"\n\nCopyright 2026 NPR"} +{"url": "https://wgme.com/news/nation-world/trump-summons-banking-chiefs-for-a-closed-door-meeting-about-an-ai-model-report-jerome-powell-scott-bessent", "title": "Trump summons banking chiefs for a closed - door meeting about an AI model : report", "publish_date": "2026-04-10T19:48:06Z", "full_text": "Bank executives have been summoned by President Donald Trump for a meeting about an artificial intelligence model that its makers are worried will breach national defense firewalls.\n\nEarlier this week, Treasury Secretary Scott Bessent and Federal Reserve Chair Jerome Powell convened the session at Treasury Headquarters to address the model called Mythos, according to the Daily Mail.\n\nBloomberg reported that the meeting was classified as “systematically important” but it was short notice.\n\nThose in attendance included Ted Pick from Morgan Stanley, David Solomon from Goldman Sachs and Jane Fraser from Citigroup.\n\nSo far only 40 firms have access to Mythos.\n\nWhen testing was taking place, Anthropic said Mythos found “thousands of high–severity vulnerabilities, including some in every major operating system and web browser.”\n\nSome of the security concerns reportedly went unnoticed by researchers and hackers.\n\n“AI models have reached a level of coding capability where they can surpass all but the most skilled humans at finding and exploiting software vulnerabilities,” Anthropic said in a blog post."} +{"url": "http://www.em.com.br/economia/2026/04/7394973-por-que-governo-trump-voltou-a-atacar-o-pix-e-o-que-eua-podem-fazer-contra-ele.html", "title": "Por que governo Trump voltou a atacar o Pix ( e o que EUA podem fazer contra ele )? ", "publish_date": "2026-04-10T19:48:06Z", "full_text": "Quase dez meses depois de abrirem uma investigação comercial contra o Pix, os Estados Unidos voltaram a alfinetar o sistema de pagamentos instantâneo brasileiro, reacendendo a discussão sobre as investidas do governo Trump contra ele e as possíveis medidas de efeito prático que pode tomar nesse sentido.\n\nO Pix foi mencionado em um relatório de 31 de março em que os EUA listam o que consideram barreiras comerciais de mais de 60 países contra empresas americanas.\n\nO documento foi elaborado pelo Escritório do Representante Comercial dos Estados Unidos (Office of the United States Trade Representative, USTR), a mesma agência que em julho do ano passado abriu um inquérito para apurar se considera o Pix uma \"prática desleal\", que fere a competitividade do setor produtivo americano.\n\nO Pix é citado três vezes nas mais de 500 páginas do National Trade Estimate Report de 2026, em apenas um parágrafo:\n\n\"O Banco Central do Brasil criou, detém, opera e regula o Pix, uma plataforma de pagamentos instantâneos. Partes interessadas dos EUA expressaram preocupação com o fato de o Banco Central do Brasil conceder tratamento preferencial ao pix, o que prejudica os fornecedores de serviços de pagamento eletrônico dos EUA. O Banco Central exige o uso do pix por instituições financeiras com mais de 500.000 contas.\"\n\nO governo brasileiro reagiu e o presidente Luiz Inácio Lula da Silva (PT) voltou a afirmar que o \"o Pix é do Brasil\". \"Ninguém vai fazer a gente mudar o Pix\", ele declarou em entrevista na semana passada.\n\nAté o presidente da Colômbia saiu em defesa do sistema de pagamentos brasileiro. Na segunda-feira (6/4), Gustavo Petro elogiou o modelo e, em uma longa publicação nas redes sociais, pediu que o sistema fosse estendido a seu país.\n\nA investigação da USTR ainda está em andamento e não tem data fechada para ser concluída. Enquanto se aguarda o desfecho, uma das perguntas que surgem no debate em torno do caso é: o que os EUA podem fazer de concreto contra o sistema de pagamentos brasileiro?\n\nGetty Images Especialistas apontam que o pix contraria interesses de big techs e de empresas de cartão\n\nAs armas dos EUA\n\nOs especialistas em comércio exterior e regulação econômica ouvidos pela reportagem frisaram que os EUA não têm jurisdição para agir diretamente contra o Pix.\n\nAs ferramentas à disposição dos americanos se concentram no âmbito comercial e estão descritas na própria legislação que foi usada para abrir a investigação contra o Brasil, a seção 301 do Trade Act de 1974.\n\nVão desde a suspensão de benefícios e acordos comerciais à restrição de importações de produtos e serviços ou imposição de tarifas sobre esses bens e serviços.\n\nOu seja, os EUA poderiam, por exemplo, dar início a um novo tarifaço sobre as exportações brasileiras com destino aos portos americanos ou retirar o Brasil do Sistema Geral de Preferências (SGP), um programa de benefícios tarifários instituído nos anos 1970 para países em desenvolvimento.\n\n\"Trata-se, portanto, mais de um mecanismo de pressão externa e econômica sobre o Estado brasileiro do que um poder regulatório sobre a infraestrutura de pagamentos em si\", destaca Camila Villard Duran, especialista em direito econômico e regulação do mercado monetário.\n\nDuran destaca que no novo relatório do USTR a linguagem usada no capítulo do Brasil é semelhante à que descreve supostas \"práticas desleais\" no setor de pagamentos em diversos outros países que também são criticados pelos EUA.\n\n\"O caso brasileiro, nesse sentido, não é isolado, mas integrado a uma estratégia política mais ampla de contestação de práticas nacionais em serviços financeiros digitais\", diz ela, que é professora associada de direito da ESSCA School of Management, na França, e cofundadora do Instituto Mulheres na Regulação.\n\n\"Assim, a consequência mais plausível não é uma medida direcionada tecnicamente ao Pix, mas sim alguma forma de retaliação comercial mais ampla\", avalia Duran.\n\nNesse sentido, uma fonte brasileira próxima às negociações diz ser difícil arriscar o que exatamente viria, caso a investigação de fato concluísse que as acusações contra o Brasil são pertinentes.\n\nHistoricamente, pondera a fonte, os EUA pouco usaram o instrumento da seção 301 do Trade Act de 1974 e, no caso específico da investigação contra o Brasil, o escopo de temas analisados pelo USTR é amplo e vai bem além do Pix.\n\nTambém inclui, por exemplo, as tarifas a que os produtores de etanol americanos estão submetidos para acessar o mercado brasileiro e até o desmatamento ilegal, acusado de dar vantagem competitiva injusta às exportações agrícolas brasileiras.\n\nRenê Medrado, sócio do escritório Pinheiro Neto Advogados, faz avaliação semelhante e exemplifica: ainda que os EUA por ventura optassem por uma retaliação comercial ampla, é difícil estimar se as eventuais tarifas seriam colocadas para uma lista ampla de produtos ou se seriam seletivas.\n\n\"E tem isso de que o governo americano às vezes fala que vai [fazer alguma coisa], depois volta atrás…\", ele acrescenta, ao comentar sobre o desafio de se traçar possíveis cenários.\n\n\"Agora, o ponto é: o ambiente hoje é bom\", completa Medrado, referindo-se ao estado das relações entre os governos Lula e Trump.\n\nDesde que os dois presidentes se cruzaram nos bastidores da assembleia-geral da ONU em Nova York em setembro do ano passado, há um diálogo bilateral maior entre Brasil e EUA e uma expectativa de que um encontro presencial formal entre os dois aconteça.\n\n\"O alcance dessas medidas dependerá muito mais da dinâmica da política bilateral e da eficácia da diplomacia brasileira\", comenta a professora Camila Villard Duran.\n\nO que está em jogo\n\nPor que então os EUA voltaram a alfinetar o Pix? No relatório do USTR de março do ano passado, o sistema de pagamentos instantâneo brasileiro não havia nem sido mencionado diretamente, ao contrário do que aconteceu no deste ano.\n\nMesmo no documento em que formalizou a investigação contra o Brasil, a agência não citou o Pix nominalmente, apesar de ter feito referência indireta a ele (\"O Brasil também parece se envolver em uma série de práticas desleais com relação a serviços de pagamento eletrônico, incluindo mas não se limitando a favorecer seus serviços de pagamento eletrônico desenvolvidos pelo governo\", diz o texto).\n\nA fonte ouvida pela BBC News Brasil que tem proximidade com as negociações comenta que uma das hipóteses para o endurecimento no tom agora foi o desfecho de uma reunião recente da Organização Mundial do Comércio (OMC) em que o Brasil bloqueou uma proposta dos EUA e outros países para estender a moratória de tarifas aduaneiras sobre transmissões eletrônicas, que inclui serviços digitais como streamings, softwares e jogos.\n\nE há ainda a grande derrota que o tarifaço de Trump sofreu no judiciário americano em fevereiro deste ano, quando a Suprema Corte considerou que o instrumento que vinha sendo usado para embasar as medidas (a Lei de Poderes Econômicos de Emergência Internacional, ou IEEPA, na sigla em inglês), na verdade não autorizava o governo americano a instituir as tarifas.\n\nEm um artigo de março deste ano, duas analistas do centro de pesquisas americano Brookings Institute pontuaram que, diante desse revés, a Seção 301, usada na investigação contra o Brasil, pode entrar no cardápio do governo americano como opção para voltar a taxar seus parceiros comerciais.\n\nDo lado do setor financeiro, a jurista Camila Villard Duran chama atenção para a expansão do Pix no Brasil, \"que altera diretamente o equilíbrio competitivo para empresas americanas, como Visa e Mastercard\", mas especialmente para o fenômeno mais amplo no qual ele está inserido, de transformação estrutural e reorganização da ordem monetária e financeira internacional.\n\n\"O Pix já não é apenas um sistema de pagamentos eficiente. Ele representa um modelo de infraestrutura pública, que reduz a dependência de redes privadas estrangeiras e concentra, no âmbito doméstico, o controle jurisdicional sobre dados e fluxos financeiros\", destaca Duran.\n\nA professora aponta que, no relatório do USTR, os EUA fazem críticas semelhantes às feitas ao Brasil a países como Índia, Tailândia e Paquistão, \"onde políticas públicas nacionais promovem sistemas domésticos de pagamento, impõem requisitos de localização de dados ou criam barreiras regulatórias à atuação de empresas estrangeiras\".\n\n\"Em todos esses casos, o argumento dos EUA é semelhante: tais medidas seriam discriminatórias e restringiriam o acesso de empresas americanas a mercados nacionais\", completa.\n\nReprodução/X/Governo Federal Post do governo federal de julho de 2025: gestão Lula tem procurado usar episódios para tentar melhorar imagem\n\nDa economia à política\n\nDiante desse panorama, Duran avalia que a pressão sobre o Pix e sobre sistemas de pagamentos de outros países também está ligada a uma questão ainda mais ampla, de soberania.\n\nO que está em jogo, diz ela, já não é apenas a concorrência entre empresas, \"mas o controle sobre infraestruturas consideradas como críticas\".\n\n\"Nas minhas pesquisas, tanto sobre a criação do euro digital como sobre os projetos de plataformas alternativas para transações financeiras transfronteiriças, noto que a ideia de 'soberania monetária' está se deslocando muito rapidamente da autonomia da política monetária para o controle jurisdicional sobre as infraestruturas de pagamento e dos dados monetários que elas geram\", afirma Duran.\n\n\"A moeda, na economia digital, torna-se cada vez mais informação e, nesse contexto, o controle jurisdicional sobre esses dados passa a ser um elemento central do poder monetário estatal.\"\n\nIsso ajuda a explicar porque as polêmicas em torno do Pix também mobilizam a arena da política.\n\nDesde o início dos ataques do governo Trump ao sistema de pagamentos a gestão Lula tem procurado usar os episódios para melhorar sua imagem apostando em um discurso focado justamente na soberania nacional.\n\nMembros do governo também têm buscado usar a polêmica para atingir adversários políticos, especialmente aqueles ligados ao bolsonarismo, que têm um histórico de proximidade com a gestão Trump.\n\nApós a divulgação do último relatório do USTR, o deputado federal Lindbergh Farias (PT-RJ) criticou o \"silêncio\" de Flávio Bolsonaro (PL-RJ), dizendo que o senador \"prefere bater palma para americano do que defender o que facilita a vida de milhões de brasileiros\" e que acabaria com Pix.\n\nDiversos vídeos e conteúdos anônimos compartilhados nos últimos dias também faziam afirmações nesse sentido.\n\nFlávio, que é pré-candidato à presidência, chegou a se pronunciar sobre o assunto e negou qualquer intenção de acabar com o sistema de pagamentos.\n\nO assunto promete estar entre os temas de discussão da eleição presidencial de 2026.\n\nSiga nosso canal no WhatsApp e receba notícias relevantes para o seu dia"} +{"url": "https://1037qcountry.com/news/030030-soaring-gas-prices-leads-to-biggest-monthly-inflation-spike-in-four-years-in-march/", "title": "Soaring gas prices leads to biggest monthly inflation spike in four years in March", "publish_date": "2026-04-10T19:48:06Z", "full_text": "By CHRISTOPHER RUGABER AP Economics Writer\n\nWASHINGTON (AP) — The largest monthly jump in gas prices in six decades caused a sharp spike in inflation in March, creating major challenges for the inflation-fighters at the Federal Reserve and heightening the political challenges of rising costs for the White House.\n\nConsumer prices rose 3.3% in March from a year earlier, the Labor Department said Friday, up sharply from just 2.4% in February and the biggest yearly increase since May 2024. On a monthly basis, prices rose 0.9% in March from February, the largest such increase in nearly four years.\n\nIt’s the first read on inflation to capture the effects of the Iran war.\n\nExcluding the volatile food and energy categories, core prices rose 2.6% in March from a year earlier, up from 2.5% in February. But last month core prices rose a modest 0.2%, suggesting that rising gas prices haven’t yet spread to many other categories.\n\nThe gas price shock stemming from the Iran war has shifted inflation’s trajectory, from a slow, gradual decline to a sharp increase further away from the Fed’s 2% target. As a result, the central bank will almost certainly postpone any cut in interest rates for months and many Fed officials have said a rate hike may be needed if inflation doesn’t cool. Gas prices are also a highly visible cost that has outsize impacts on consumer confidence and political sentiment.\n\nHigher gas prices sap consumers’ ability to spend on other goods and services and as a result could also slow economic growth. At least in the short run, many Americans can only make limited changes to their daily driving habits, which are largely determined by where they live, shop, and work. As a result, most people will pay higher prices for gas, and potentially cut back elsewhere.\n\nGas prices averaged $4.15 a gallon nationwide Friday, up from $2.98 on the day before the war began, according to motor club AAA.\n\nThe big question for consumers and the economy is whether the surge in oil and gas prices will create a sustained, broader inflation shock, similar to what occurred in the aftermath of the pandemic in 2021-2022. Inflation reached a peak of 9.1% in June 2022, as COVID-19 snarled supply chains and several rounds of stimulus checks pushed up consumer demand. Prices soared for groceries, furniture, restaurant meals and many other goods and services.\n\nThis time, economists say the job market and consumer spending are weaker, and there are no large government stimulus checks being issued to spur demand. The unemployment rate is low, at 4.3%, but companies aren’t scrambling to hire the way they were when the economy emerged from the pandemic, which led many firms to offer sharp pay increases to attract and keep workers.\n\nRapid pay increases and solid income growth helped consumers weather the higher prices that resulted from the pandemic’s supply chain disruptions, and fueled spikes in demand that led many companies to raise prices further.\n\n“That’s where this really differs, is that we aren’t seeing anywhere near the strength of demand,” Alan Detmeister, an economist at UBS, said. In 2021 and 2022, income growth “was increasing really strongly. We aren’t seeing that now,” he added.\n\nDetmeister thinks the better comparison will likely be to 1990-91, when higher oil and gas prices stemming from Iraq’s invasion of Kuwait contributed to a recession, but didn’t lead to a jump in inflation, in part because of weaker consumer spending.\n\nThe gas price spike’s impact on inflation is, in some ways, similar to President Donald Trump’s tariffs, in that their effect will depend largely on the size and duration of the increase.\n\nFor now, economists expect that in March and April the impact will largely be confined to energy-intensive industries, such as airlines, package delivery services and public transportation. Overall, the U.S. economy is much less dependent on oil and gas than it was in previous decades.\n\nStill, the large jump in inflation — which is almost certain to continue for several months — has already shifted the debate at the Federal Reserve, which began the year expecting to cut its key interest rate at least a couple of times. But a growing number of Fed officials are now willing to consider hiking rates instead if core inflation doesn’t cool noticeably.\n\nMost officials are almost certain to support keeping the Fed’s key interest rate unchanged in the coming months, at about 3.6%, as they evaluate how the economy evolves. Investors now don’t expect the Fed to cut rates until late 2027.\n\nHigher gas prices are tricky for the Fed because they can also slow growth by weighing on consumer spending, potentially causing layoffs. The Fed would typically cut its rate to encourage more spending if unemployment rises, while it raises rates to combat inflation.\n\nMore expensive oil and gas will also likely lift grocery prices, creating more pain for consumers who have already absorbed a roughly 25% jump in food costs since the pandemic. Nearly all groceries are shipped by diesel-fueled trucks, and diesel fuel prices have risen even more than those for regular gas. Still, analysts don’t expect food prices to accelerate for another month or two."} +{"url": "https://www.elsiglodetorreon.com.mx/noticia/2026/precio-del-dolar-hoy-viernes-10-de-abril-peso-mexicano-perfila-su-mejor-semana-en-un-ano.html", "title": "Precio del dólar hoy viernes 10 de abril : peso mexicano perfila su mejor semana en un año", "publish_date": "2026-04-10T19:48:06Z", "full_text": "El precio del dólar hoy en México, viernes 10 de abril de 2026, mantiene una tendencia a la baja, mientras el peso mexicano se fortalece y se encamina a cerrar su mejor semana en más de un año, apoyado por un entorno internacional más favorable.\n\nDe acuerdo con datos de Bloomberg, el tipo de cambio interbancario inicia la jornada en 17.34 pesos por dólar, con una caída de 0.09 por ciento para la divisa estadounidense.\n\nPeso mexicano liga su mejor racha en meses\n\nLa moneda mexicana continúa con su avance y cotiza alrededor de 17.29 unidades por dólar, lo que representa una apreciación de 0.36 por ciento en la jornada.\n\nCon este desempeño, el peso suma seis sesiones consecutivas de ganancias y acumula un avance semanal superior al 3 por ciento, perfilando su mejor resultado desde abril de 2025.\n\nOptimismo global impulsa al peso\n\nEl fortalecimiento del peso ocurre en medio de un cambio en el ánimo de los mercados internacionales. Los inversionistas han comenzado a reducir su exposición al dólar, considerado un activo refugio, ante la expectativa de que se mantenga el alto al fuego en Medio Oriente.\n\nEste escenario ha abierto la posibilidad de una reanudación en los envíos petroleros, lo que ha contribuido a estabilizar los mercados y disminuir la presión inflacionaria global.\n\nAdemás, se espera que durante el fin de semana se lleven a cabo las primeras conversaciones entre Estados Unidos e Irán desde el inicio del conflicto, lo que podría reforzar el optimismo en los mercados.\n\n¿Por qué está subiendo el peso mexicano?\n\nUn análisis de Banco Base señala que el peso inicia la sesión con una apreciación de 0.34 por ciento, equivalente a 5.9 centavos, cotizando alrededor de 17.31 pesos por dólar.\n\nDurante las primeras horas del día, el tipo de cambio ha oscilado entre un máximo de 17.40 y un mínimo de 17.30 pesos, reflejando estabilidad con sesgo positivo.\n\nEn este periodo, el peso acumula un avance de 3.17 por ciento, impulsado por el debilitamiento del dólar, que retrocede ligeramente en su índice ponderado.\n\nInflación en Estados Unidos y política monetaria\n\nEn el frente económico, se dio a conocer que los precios al consumidor en Estados Unidos registraron en marzo su mayor incremento en casi cuatro años, aunque el dato estuvo en línea con las expectativas del mercado.\n\nEste indicador mantiene la atención de la Reserva Federal, que evalúa el ritmo de futuros ajustes en la tasa de interés.\n\nAsí cerró el peso mexicano la jornada anterior\n\nEl jueves 9 de abril, el peso mexicano cerró con una ganancia de 0.45 por ciento, al ubicarse en 17.36 pesos por dólar, extendiendo la racha positiva observada en días previos.\n\nLos mercados se mantienen cautelosos, aunque con un sesgo optimista, atentos a la evolución del alto al fuego en Medio Oriente y a posibles avances diplomáticos."} +{"url": "https://www.risk.net/markets/7963346/the-swap-futures-comeback", "title": "The swap futures comeback - Risk . net", "publish_date": "2026-04-10T19:48:06Z", "full_text": "On March 27, a single directional block trade worth $1.5 billion in notional printed in an interest rate contract that, just two years earlier, few outside a handful of Chicago-based proprietary trading firms were actively quoting.\n\nThe following week on March 31, two more directional block trades hit the logs, with notionals of $500 million and $1 billion, respectively. It helped March become a"} +{"url": "https://abc30.com/post/prices-surged-march-oil-shock-set-off-iran-war/18865879/", "title": "Prices surged in March after oil shock set off by Iran war", "publish_date": "2026-04-10T19:48:06Z", "full_text": "The Middle East conflict triggered one of the largest oil shocks in decades.\n\nPrices surged in March after oil shock set off by Iran war\n\nInflation surged in March after an oil shock triggered by the U.S.-Israeli war with Iran, government data showed on Friday. The inflation report matched economists' expectations.\n\nPrices rose 3.3% in March compared to a year earlier, marking a steep rise from a year-over-year inflation rate of 2.4% in the prior month. Annual inflation jumped to its highest level in two years, U.S. Bureau of Labor Statistics (BLS) data showed.\n\nThe rapid acceleration of price increases could complicate interest rate policy at the Federal Reserve, which may be reluctant to lower borrowing costs as inflation climbs.\n\nThe Middle East conflict prompted Iran's effective closure of the Strait of Hormuz, a critical waterway that facilitates the transport of about one-fifth of the global supply of oil and natural gas.\n\nThat energy shortage sent oil and gasoline prices surging worldwide. Gasoline prices in the U.S. stood at $4.15 on average per gallon on Friday, marking a leap of $1.17 since the start of the war, AAA data showed.\n\nThe BLS collected price data over the entire month of March. The inflation report, in turn, reflected prices for 31 of the first 32 days of war, excluding the outbreak of hostilities on Feb. 28. The ceasefire announced on Tuesday came after 40 days of fighting.\n\nAs part of a two-week U.S.-Iran ceasefire announced on Tuesday, Iran says it will allow tankers passage through the Strait of Hormuz as long as they coordinate with the nation's military.\n\nThe resumption of tanker traffic remains uncertain, however. Tanker traffic was suspended on Wednesday after Israeli attacks on Lebanon, Iran's semi-official Fars News Agency reported.\n\nCrude prices fell after the ceasefire announcement but remained highly elevated. U.S. oil prices topped $98 a barrel as of Thursday, standing nearly 50% higher than their pre-war level.\n\nA surge in consumer prices could pose difficulty for the Fed as it weathers a slowdown of economic performance over recent months.\n\nIf the Fed opts to lower borrowing costs, it could spur growth but risk higher inflation. On the other hand, the choice to raise interest rates may slow price increases but raises the likelihood of a cooldown in economic performance.\n\nLast month, Federal Reserve Chairman Jerome Powell said that despite rising energy prices and the potential impact on inflation, he doesn't think the central bank needs to raise interest rates.\n\nPowell noted that central bankers often look past shocks -- such as sudden oil-price increases -- since the upward pressure on consumer prices usually proves temporary.\n\n\"We feel like our policy is in a good place for us to wait and see how that turns out,\" Powell said.\n\nThe benchmark interest rate stands at a level between 3.5% and 3.75%. That figure marks a significant drop from a recent peak attained in 2023, but borrowing costs remain well above a 0% rate established at the outset of the COVID-19 pandemic.\n\nThe Fed will announce its next rate decision on April 29. Investors overwhelmingly expect the Fed to leave rates unchanged, according to the CME FedWatch Tool, a measure of market sentiment.\n\nThe tool pegs a roughly 70% chance that the Fed will maintain interest rates at current levels for the remainder of the year."} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-10/Full_text/full_text_macro_geopolitics_risk.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-10/Full_text/full_text_macro_geopolitics_risk.jsonl new file mode 100644 index 0000000..04c1024 --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-10/Full_text/full_text_macro_geopolitics_risk.jsonl @@ -0,0 +1,7 @@ +{"url": "https://www.sunstar.com.ph/davao/vp-sara-questions-pbbm-on-aid-amid-energy-crisis", "title": "VP Sara Challenges Marcos on Aid Amid 2026 Energy Crisis", "publish_date": "2026-04-10T19:50:08Z", "full_text": "VICE President Sara Duterte on Thursday questioned what President Ferdinand “Bongbong” Marcos Jr. is doing to assist vulnerable Filipinos affected by the ongoing energy crisis.\n\n“Ano ba ang ginagawa niya para tulungan ang mga kababayan natin na tinatamaan or nahihirapan dahil dito sa epekto ng crisis sa Middle East (What is he doing to help our fellow Filipinos who are affected or struggling because of the Middle East crisis?),” Duterte said during a media interview on April 9, 2026, at the Veterans Memorial Monument in Davao City.\n\nShe said fuel prices could ease once tensions in the Middle East subside or if the Philippines secures alternative fuel sources outside the region. Otherwise, she said, oil prices will continue to rise.\n\nShe added that the Office of the Vice President (OVP) will continue its Libreng Sakay program, citing the growing need for free rides among commuters affected by higher fuel costs.\n\nThe OVP launched the program in 2022 to help the public manage daily expenses, Duterte said.\n\nAmid the fuel crisis, Marcos has ordered government agencies to adopt energy-saving measures, including reducing power and fuel consumption by limiting air-conditioning, lighting, and the use of office equipment.\n\nThe president also declared a State of National Energy Emergency through an executive order to address the situation. RGP"} +{"url": "https://hitsfm.net/business/9a906e8ed2f1be1191aa6d7dc2574e4c", "title": "Business - HITS FM", "publish_date": "2026-04-10T19:50:08Z", "full_text": "A view of the vessels passing through the Strait of Hormuz following the two-week temporary ceasefire reached between the United States and Iran on the condition that the strait be reopened, seen in Oman, April 8, 2026. (Anadolu via Getty Images)\n\n(NEW YORK) -- Inflation surged in March after an oil shock triggered by the U.S.-Israeli war with Iran, government data showed on Friday. The inflation report matched economists' expectations.\n\nPrices rose 3.3% in March compared to a year earlier, marking a steep rise from a year-over-year inflation rate of 2.4% in the prior month. Annual inflation jumped to its highest level in two years, U.S. Bureau of Labor Statistics (BLS) data showed.\n\nThe jump in prices owed in large part to a sharp rise in costs for products impacted by the oil shortage. Gasoline prices were 25% higher in March than February, the BLS report said. Overall, energy prices jumped almost 12% from a month earlier.\n\nAirline fares increased 3.4% in March from February, the data showed.\n\nThe rapid acceleration of price increases could complicate interest rate policy at the Federal Reserve, which may be reluctant to lower borrowing costs as inflation climbs.\n\nThe Middle East conflict prompted Iran's effective closure of the Strait of Hormuz, a critical waterway that facilitates the transport of about one-fifth of the global supply of oil and natural gas.\n\nThat energy shortage sent oil and gasoline prices surging worldwide. Gasoline prices in the U.S. stood at $4.15 on average per gallon on Friday, marking a leap of $1.17 since the start of the war, AAA data showed.\n\nThe BLS collected price data over the entire month of March. The inflation report, in turn, reflected prices for 31 of the first 32 days of war, excluding the outbreak of hostilities on Feb. 28. The ceasefire announced on Tuesday came after 40 days of fighting.\n\nAs part of a two-week U.S.-Iran ceasefire announced on Tuesday, Iran says it will allow tankers passage through the Strait of Hormuz as long as they coordinate with the nation's military.\n\nThe resumption of tanker traffic remains uncertain, however. Tanker traffic was suspended on Wednesday after Israeli attacks on Lebanon, Iran's semi-official Fars News Agency reported.\n\nCrude prices fell after the ceasefire announcement but remained highly elevated. U.S. oil prices topped $98 a barrel as of Thursday, standing nearly 50% higher than their pre-war level.\n\nA surge in consumer prices could pose difficulty for the Fed as it weathers a slowdown of economic performance over recent months.\n\nIf the Fed opts to lower borrowing costs, it could spur growth but risk higher inflation. On the other hand, the choice to raise interest rates may slow price increases but raises the likelihood of a cooldown in economic performance.\n\nLast month, Federal Reserve Chairman Jerome Powell said that despite rising energy prices and the potential impact on inflation, he doesn't think the central bank needs to raise interest rates.\n\nPowell noted that central bankers often look past shocks -- such as sudden oil-price increases -- since the upward pressure on consumer prices usually proves temporary.\n\n\"We feel like our policy is in a good place for us to wait and see how that turns out,\" Powell said.\n\nThe benchmark interest rate stands at a level between 3.5% and 3.75%. That figure marks a significant drop from a recent peak attained in 2023, but borrowing costs remain well above a 0% rate established at the outset of the COVID-19 pandemic.\n\nThe Fed will announce its next rate decision on April 29. Investors overwhelmingly expect the Fed to leave rates unchanged, according to the CME FedWatch Tool, a measure of market sentiment.\n\nThe tool pegs a roughly 70% chance that the Fed will maintain interest rates at current levels for the remainder of the year.\n\nCopyright © 2026, ABC Audio. All rights reserved."} +{"url": "https://www.novosti.rs/planeta/svet/1596010/uskoro-cemo-saznati-tramp-otkrio-kad-biti-poznato-pregovori-sad-irana-biti-uspesni-punimo-brodove-najboljim-oruzjem", "title": " USKORO ĆEMO SAZNATI Tramp otkrio kad će biti poznato da li će pregovori SAD i Irana biti uspešni : Mi punimo brodove najboljim oružjem", "publish_date": "2026-04-10T19:50:08Z", "full_text": "AMERIČKI predsednik Donald Tramp izjavio je danas da će se za 24 sata znati da li će pregovori Sjedinjenih Američkih Država i Irana, koji se za vikend održavaju u Pakistanu, biti uspešni.\n\nFoto: Tanjug/AP Photo/Julia Demaree Nikhinson\n\nTramp je za Njujork post rekao da se američki ratni brodovi ponovo pune \"najboljom municijom\", kako bi nastavili napade na Iran, ako mirovni pregovori u Pakistanu propadnu.\n\n- Saznaćemo za oko 24 sata. Uskoro ćemo saznati - rekao je Tramp u telefonskom intervjuu, odgovarajući na pitanje da li smatra da će razgovori biti uspešni.\n\nOn je kazao da se sprema da vojska ponovo otvori moreuz, ako Iran ne bude poštovao primirje.\n\n- U toku je resetovanje. Ali mi punimo brodove. Punimo brodove najboljim oružjem ikada napravljenim, čak na višem nivou nego što smo to činili da bismo izvršili potpuno desetkovanje (Irana). A ako ne postignemo dogovor, koristićemo ih, i koristićemo ih veoma efikasno - kazao je Tramp.\n\nPotrpedsednik SAD Džej Di Vens predvodi američku delegaciju u Islamabadu, u kojoj su i američki specijalni izaslanik Stiv Vitkof i Trampov zet Džared Kušner, koji će tokom vikenda pregovarati o postizanju trajnog mira, nakon što je u utorak postignut sporazum o dvonedeljnom prekidu vatre sa Iranom.\n\nOčekuje se da će Iran u pakistanskoj prestonici predstavljati ministar spoljnih poslova Abas Arakči i predsednik iranskog parlamenta Mohamed Bager Kalibaf. Tramp je stavio do znanja da je ponovno otvaranje Ormuskog moreuza za slobodan prolaz brodova od strane Irana ključna komponenta svakog sporazuma, a očekuje se da će tema pregovora biti i okončanje iranske podrške militantnim grupama u regionu, status iranskog programa balističkih raketa i zahtev Teherana za ukidanje američkih sankcija.\n\n(Tanjug)\n\nBONUS VIDEO:\n\nGORI BLISKI ISTOK: Eksplozije širom Irana, Izraela, Emirata, Katara..."} +{"url": "http://www.shanghainews.net/news/278975895/china-sees-solid-rise-in-cross-border-travel-in-q1-with-foreign-national-trips-surging", "title": "China sees solid rise in cross - border travel in Q1 , with foreign national trips surging", "publish_date": "2026-04-10T19:50:08Z", "full_text": "BEIJING, April 10 (Xinhua) -- China recorded steady growth in cross-border entries and exits in the first quarter of 2026, with trips by foreign nationals surging amid measures aimed at facilitating inbound travel.\n\nBorder authorities handled 185 million cross-border trips from January to March, up 13.5 percent year on year, the National Immigration Administration announced on Friday.\n\nDuring this period, foreign nationals made 21.33 million border crossings, up 22.3 percent year on year. Visa-free entries for foreign nationals reached 8.32 million, making up 77.9 percent of all inbound foreign trips, up 29.3 percent year on year.\n\nMainland residents took 91.66 million cross-border trips, an increase of 14.2 percent year on year. Residents of Hong Kong, Macao and Taiwan made 72.49 million crossings, up 10.3 percent from the same period last year.\n\nThis growth shows that authorities are continuing to relax entry policies and make travel more convenient for visitors.\n\nIn Xiamen, a coastal city in eastern Fujian province, streamlined customs procedures have helped speed up the arrival process for travelers. \"It's very convenient to come to China,\" said Kate, an Australian tourist traveling with her family. \"After submitting our entry information online, we cleared customs quickly. China is open and welcoming.\"\n\nMeanwhile, in Hainan, a tropical island province and free trade hub, expanded visa-free policies now cover passport holders from 86 countries.\n\n\"The number of inbound and outbound tourists has gone up significantly since the launch of island-wide special customs operations. Russia, Malaysia, Indonesia, Kazakhstan and other countries are major sources of foreign visitors,\" said Rao Jun, a border inspection officer.\n\nIn 2025, China received more than 150 million inbound tourist visits, up over 17 percent year on year, with inbound travelers spending more than 130 billion U.S. dollars, according to the Ministry of Culture and Tourism. Visa-free entries by foreign nationals surpassed 30 million.\n\nBy February this year, China had expanded its unilateral visa-free access to citizens of 50 countries.\n\nBetter infrastructure and services are also encouraging foreign visitors to stay longer and engage more deeply with the country. High-speed rail trips, drone light shows and traditional Chinese medicine massages are among the most popular activities for foreign tourists.\n\nBuilding on this momentum, authorities rolled out measures in March to further boost inbound tourist spending, including refining transit visa-free arrangements and enhancing departure tax refund services. Efforts are also being made to make payment more accessible and strengthen foreign-language services at key venues."} +{"url": "https://udn.com/news/story/7270/9433920", "title": "亞洲最新隱奢海島誕生 ! Club Med沙巴度假村開訂 4天3夜2萬起全包 | 流行消費 | 生活", "publish_date": "2026-04-10T19:50:08Z", "full_text": "全球全包式度假品牌Club Med宣布,全新據點「Club Med Borneo」即日起正式開放預訂,並預計於2026年11月16日迎接首批旅客。度假村座落於馬來西亞沙巴瓜拉潘尤(Kuala Penyu)海岸,被視為近年崛起的「隱奢海島秘境」,開幕同步推出限時優惠,4天3夜食宿全包假期每人最低20,200元起。\n\n隨著疫後旅遊型態轉變,旅客逐漸從城市觀光轉向自然探索與深度度假。Club Med台灣表示,沙巴近年成為亞洲海島新焦點,台灣旅客赴沙巴人次持續成長,品牌因此選擇在婆羅洲打造亞洲重要新據點。\n\n全新度假村占地約17公頃,擁有長達4公里白色沙灘與完整原始海岸線,結合紅樹林濕地、生態雨林與野生動物棲地,被形容為「近距離感受亞馬遜等級的自然場域」。建築設計靈感源自婆羅洲原住民長屋文化,以低密度開發融入環境,並朝亞太首座取得BREEAM永續建築認證的濱海度假村目標邁進。\n\n度假村共規劃400間客房,其中39間「謐境探索系列」套房提供獨立泳池、專屬酒吧與禮賓服務,主打高隱私度與靜奢體驗,鎖定高端度假市場。\n\n除了全包式餐飲與娛樂,旅客也可參與紅樹林獨木舟、生態教育導覽、匹克球運動等活動,或搭乘遊船探索克里亞斯河生態,觀察長鼻猴與螢火蟲奇景;深入文化體驗則可造訪在地村落與原住民族文化聚落。\n\nClub Med指出,全包式假期涵蓋住宿、美食、酒水、運動與娛樂,一價全含的旅遊模式持續受到家庭與自由行旅客青睞,此次婆羅洲新據點將進一步強化品牌在亞洲海島市場的布局。\n\n相關資訊可查:https://www.clubmed.com.tw/。\n\n※ 提醒您:禁止酒駕 飲酒過量有礙健康\n\n造訪Mari-Mari文化村,透過多元互動體驗,品嘗在地竹筒料理。圖/Club Med提供\n\n全包式度假品牌Club Med宣布,全新度假村「馬來西亞沙巴婆羅洲」正式開放預訂。圖/Club Med提供\n\nClub Med全新度假村「馬來西亞沙巴婆羅洲」正式開放預訂,可近距離探索媲美亞馬遜的紅樹林生態與豐富野生動物。圖/Club Med提供"} +{"url": "https://www.bankingnews.gr/diethni/articles/867952/synexizoun-na-eksoplizoun-tous-egklimaties-i-germania-paredose-5-tethorakismena-oximata-mediguard-stin-ethnofroura-tis-oukranias", "title": "Συνεχίζουν να εξοπλίζουν τους εγκληματίες - Η Γερμανία παρέδωσε 5 τεθωρακισμένα οχήματα MEDIGUARD στην Εθνοφρουρά της Ουκρανίας", "publish_date": "2026-04-10T19:50:08Z", "full_text": "Το MEDIGUARD παράγεται από κοινού από τρεις εταιρείες από την Ουκρανία και τη Γερμανία\n\nπαρέδωσε πέντε θωρακισμένα ιατρικά οχήματα MEDIGUARD ουκρανο-γερμανικής παραγωγής στην Εθνοφρουρά της Ουκρανίας.Η γερμανική πρεσβεία στηνΔιπλωμάτες σημείωσαν ότι αυτή είναι η πρώτη παρτίδα οχημάτων στο πλαίσιο μιας νέας, μεγαλύτερης σύμβασης που χρηματοδοτείται πλήρως από τη Γερμανία.Η μεταφορά της προηγούμενης παρτίδας αναφέρθηκε τον Οκτώβριο του 2025.Εκείνη την εποχή, σημειώθηκε ότι τέσσερα τεθωρακισμένα ασθενοφόρα εργάζονταν ήδη στο μέτωπο για τη διάσωση Ουκρανού στρατιωτικού προσωπικού.Αναφέρθηκε ότι η νέα παρτίδα δημιουργήθηκε λαμβάνοντας υπόψη την πολεμική εμπειρία του ουκρανικού στρατού.Έτσι, ένα από τα προηγουμένως μεταφερθέντα οχήματα άντεξε τα χτυπήματα από τρία ρωσικά drones στο μέτωπο. Η καμπίνα παρέμεινε άθικτη και το πλήρωμα δεν υπέστη σοβαρούς τραυματισμούς.Επιπλέον, μπορεί να σημειωθεί ότι, σε αντίθεση με τα οχήματα που παραδόθηκαν τον Οκτώβριο του 2025, η παρτίδα του Απριλίου είναι άμεσα εξοπλισμένη με δίχτυα κατά των drones για προστασία από τα FPV.Το MEDIGUARD παράγεται από κοινού από τρεις εταιρείες από τηνκαι η συναρμολόγηση πραγματοποιείται στην Ουκρανία με χρηματοδότηση από τη γερμανική κυβέρνηση.Υπενθυμίζεται ότι στα τέλη Μαρτίου 2026,Αυτό αναφέρθηκε στον Στρατό από εκπροσώπους αρκετών κατασκευαστών τεθωρακισμένων οχημάτων της Ουκρανίας.www.bankingnews.gr"} +{"url": "https://www.cravenherald.co.uk/news/national/26012377.airports-warn-systemic-jet-fuel-shortage-strait-hormuz-stays-closed/", "title": "Airports warn of systemic jet fuel shortage if Strait of Hormuz stays closed", "publish_date": "2026-04-10T19:50:08Z", "full_text": "Airports Council International (ACI), which represents more than 600 airports, wrote a letter to the European commissioners for energy and transport and tourism.\n\nThe body’s director-general Olivier Jankovec wrote in the letter: “At this stage, we understand that if the passage through the Strait of Hormuz does not resume in any significant and stable way within the next three weeks, systemic jet fuel shortage is set to become a reality for the EU.\n\n“The fact that we are entering the peak summer season… is only adding to those concerns.”\n\nSupplies of jet fuel – which is used to fly planes – from the Middle East have been disrupted since the US-Israel’s war with Iran because of Iran’s effective closure of the Strait of Hormuz, a critical international shipping route.\n\nThis has led to soaring prices and warnings that flights could be affected because of Europe’s reliance on fuel imports from around the world.\n\nAnalysts have also said higher jet fuel prices can be quicker to pass through to airfares than road fuel and household energy costs.\n\nRyanair’s boss Michael O’Leary said earlier this month that if the war continues, then there was a risk of “disruptions in Europe in May and June”, adding that “maybe 10%, 20%, 25% of our supplies might be at risk”.\n\nSir Keir Starmer has been visiting allies in the Gulf for talks on how to support what he described as a “fragile” ceasefire between the US and Iran, which was agreed this week.\n\nHe spoke to US President Donald Trump about the need for a “practical plan” to get shipping going through the Strait of Hormuz amid suggestions Tehran wants to charge vessels for passage.\n\nIn its letter, the ACI says jet fuel supply for the next six months needs to be urgently monitored by the European Commission, including identifying action that can be taken to increase production within the EU.\n\nIt also asks them to consider temporarily lifting restrictions and regulations that limit the ability to import jet fuel.\n\n“This crisis has exposed the reduced refining capacity of the EU for jet fuel production, and its acute dependence on imports from other world regions,” Mr Jankovec warned on behalf of the body.\n\nSusannah Streeter, chief investment strategist for Wealth Club, said: “Carriers have had to deal with a more than doubling of fuel costs since the conflict erupted and the threat of shortages lingers.\n\n“As the war has put a chokehold on supplies from the Middle East, it has caused other nations which produce jet fuel to impose export bans, causing trade to seize up further.\n\n“It will take time to unwind panic positions, and for jet fuel prices to stabilise, so airlines are likely to continue to pass on the cost to passengers for the foreseeable future.”"} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-10/Full_text/full_text_macro_yields_dollar.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-10/Full_text/full_text_macro_yields_dollar.jsonl new file mode 100644 index 0000000..3575178 --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-10/Full_text/full_text_macro_yields_dollar.jsonl @@ -0,0 +1,6 @@ +{"url": "https://www.finanzen.net/nachricht/rohstoffe/rohstoffpreise-am-freitagabend-15604785", "title": "Rohstoffpreise am Freitagabend", "publish_date": "2026-04-10T19:49:15Z", "full_text": "Gold, Öl & Co. aktuell\n\nSo bewegen sich derzeit Goldpreis, Erdgaspreis & Co.\n\nDer Goldpreis ist am Abend geklettert. Um 20:40 Uhr legte der Goldpreis um 0,13 Prozent auf 4.772,40 US-Dollar zu, nachdem er am Vortag noch bei 4.766,02 US-Dollar gehandelt worden war.\n\nWer­bung Wer­bung\n\nDaneben präsentiert sich der Silberpreis mit einem Kursgewinn. Um 20:40 Uhr notiert der Silberpreis 1,80 Prozent stärker bei 76,46 US-Dollar. Am Vortag lag der Preis bei 75,11 US-Dollar.\n\nNach 2.107,00 US-Dollar am Vortag ist der Platinpreis am Freitagabend um -2,18 Prozent auf 2.061,00 US-Dollar gesunken.\n\nZudem zeigt sich der Palladiumpreis im Sinkflug. Um 20:38 Uhr gibt der Palladiumpreis um -2,14 Prozent auf 1.528,50 US-Dollar ab, nachdem am Tag zuvor noch ein Preis von 1.562,00 US-Dollar gemeldet wurde.\n\nInzwischen fällt der Ölpreis (Brent) um -1,39 Prozent auf 95,07 US-Dollar. Am tags zu vor lag der Ölpreis (Brent) bei 96,41 US-Dollar.\n\nDaneben wertet der Ölpreis (WTI) um 20:41 Uhr ab. Es geht -1,88 Prozent auf 96,03 US-Dollar nach unten, nachdem der Preis tags zuvor bei 97,87 US-Dollar stand.\n\nDerweil notiert der Baumwolle bei 0,73 US-Dollar. Im Vergleich zum Vortag (0,73 US-Dollar) ist das ein Abschlag von -0,05 Prozent.\n\nMit dem Haferpreis geht es indes nordwärts. Der Haferpreis gewinnt 0,38 Prozent auf 3,34 US-Dollar hinzu, nachdem gestern noch 3,33 US-Dollar an der Tafel standen.\n\nWährenddessen legt der Kaffeepreis um 2,18 Prozent auf 3,00 US-Dollar zu. Gestern war der Kaffeepreis noch 2,94 US-Dollar wert.\n\nMit dem Lebendrindpreis geht es indes nordwärts. Der Lebendrindpreis gewinnt 0,84 Prozent auf 2,52 US-Dollar hinzu, nachdem gestern noch 2,50 US-Dollar an der Tafel standen.\n\nZudem zeigt sich der Maispreis im Sinkflug. Um 20:20 Uhr gibt der Maispreis um -0,73 Prozent auf 4,41 US-Dollar ab, nachdem am Tag zuvor noch ein Preis von 4,44 US-Dollar gemeldet wurde.\n\nDaneben wertet der Mastrindpreis um 20:05 Uhr auf. Es geht 0,36 Prozent auf 3,74 US-Dollar nach oben, nachdem der Preis am Vortag bei 3,73 US-Dollar stand.\n\nWährenddessen zeigt sich der Orangensaftpreis im Plus. Im Vergleich zum Vortag (1,94 US-Dollar) geht es um 1,88 Prozent auf 1,97 US-Dollar nach oben.\n\nZeitgleich verstärkt sich der Sojabohnenpreis um 0,79 Prozent auf 11,75 US-Dollar. Einen Tag zuvor lag der Preis bei 11,65 US-Dollar.\n\nZudem zeigt sich der Sojabohnenmehlpreis im Aufwind. Um 20:20 Uhr zieht der Sojabohnenmehlpreis um 4,60 Prozent auf 332,20 US-Dollar an, nachdem am Tag zuvor noch ein Wert von 317,60 US-Dollar gemeldet wurde.\n\nWährenddessen verliert der Sojabohnenölpreis um -0,89 Prozent auf 0,67 US-Dollar. Gestern stand der Sojabohnenölpreis noch bei 0,68 US-Dollar.\n\nZeitgleich verringert sich der Zuckerpreis um -1,22 Prozent auf 0,14 US-Dollar. Einen Tag zuvor lag der Preis bei 0,14 US-Dollar.\n\nIndessen reduziert sich der Erdgaspreis - Natural Gas um -0,94 Prozent auf 2,65 US-Dollar. Am Vortag notierte der Erdgaspreis - Natural Gas bei 2,67 US-Dollar.\n\nIn der Zwischenzeit verbucht der Mageres Schwein Preis Abschläge in Höhe von -0,06 Prozent auf 0,91 US-Dollar. Am Tag zuvor lag der Mageres Schwein Preis bei 0,91 US-Dollar.\n\nWährenddessen wird der Milchpreis bei 17,03 US-Dollar gehandelt. Das bedeutet einen Abschlag von -0,06 Prozent im Vergleich zum Vortag (17,04 US-Dollar).\n\nZudem fällt der Heizölpreis. Um -4,82 Prozent reduziert sich der Heizölpreis um 20:40 Uhr auf 99,06 US-Dollar, nachdem der Heizölpreis am Vortag noch bei 104,08 US-Dollar lag.\n\nWährenddessen wird der Kohlepreis bei 104,85 US-Dollar gehandelt. Das bedeutet einen Abschlag von -0,80 Prozent im Vergleich zum Vortag (105,70 US-Dollar).\n\nWährenddessen zeigt sich der Reispreis im Minus. Im Vergleich zum Vortag (10,91 US-Dollar) geht es um -1,10 Prozent auf 10,79 US-Dollar nach unten.\n\nDerweil geht es für den Holzpreis südwärts. Der Holzpreis sinkt -0,26 Prozent auf 579,50 US-Dollar, nach 581,00 US-Dollar am Vortag.\n\nWährenddessen verliert der Erdgaspreis - TTF um -3,29 Prozent auf 44,19 Euro. Gestern stand der Erdgaspreis - TTF noch bei 45,70 Euro.\n\nRedaktion finanzen.net"} +{"url": "https://www.ilgiorno.it/varese/cronaca/arcisate-malore--guida-trattore-79enne-condizioni-disperate-764da021", "title": "Arcisate , ha un malore mentre guida il trattore nei campi : 79enne in condizioni disperate", "publish_date": "2026-04-10T19:49:15Z", "full_text": "Arcisate (Varese), 10 aprile 2026 – Un pomeriggio come tanti, tra i campi ai margini del paese. Il rumore lento del trattore, il lavoro quotidiano, la normalità. Poi, all’improvviso, qualcosa si spezza. Un malore, la perdita di controllo, l’impatto. E la quiete della campagna che si trasforma in tragedia.\n\nÈ accaduto oggi, 10 aprile, poco prima delle 15, in via Donizetti ad Arcisate, lungo la strada che conduce a Velmaio. Qui, in una zona fatta di terreni coltivati e case sparse, un uomo di 79 anni stava lavorando, quando è stato colpito da un improvviso malore mentre era alla guida del suo trattore. Le sue condizioni sono gravissime.\n\nLo schianto e i soccorsi\n\nIl mezzo, ormai fuori controllo, ha proseguito la sua corsa per pochi metri, finendo contro un muretto di confine. Un urto secco, violento. I primi a rendersi conto della gravità della situazione hanno lanciato l’allarme. In pochi minuti la zona si è riempita di sirene: soccorsi in codice rosso, quello della massima urgenza. Sul posto sono arrivati l’automedica, un’ambulanza della Croce Rossa Valceresio, i vigili del fuoco, la polizia locale e i carabinieri.\n\nI soccorritori si sono trovati davanti a una scena drammatica. L’anziano era in condizioni critiche. Le operazioni per stabilizzarlo sono state complesse, svolte direttamente sul posto, sotto gli occhi di chi assisteva con apprensione. Poi la corsa in ospedale. Il 79enne è stato trasportato d’urgenza al Circolo di Varese."} +{"url": "https://www.pressdemocrat.com/2026/04/09/keyboards-and-keyboard-covers-that-make-typing-with-long-nails-a-breeze/", "title": "Keyboards and keyboard covers that make typing with long nails a breeze", "publish_date": "2026-04-10T19:49:15Z", "full_text": "Because typing with long nails can be a nightmare\n\nI love having long nails. There’s something so elegant about lengthy claws, and they really elevate an ensemble. I don’t, however, love typing with long nails. If you’ve ever tried to type quickly and accurately with a fresh set of acrylics or press-ons, you know the struggle of having your fingers slip all over the place and hit the wrong keys.\n\nBut there’s good news for us manicure loyalists: Certain keyboards are designed to make typing with long nails easier than others. The key is in the keys, which are raised to give your nails more space and minimize the chances of them accidentally hitting the wrong letter. Oftentimes, these keyboards have circular keys instead of square ones, which allows for bigger gaps between the keys. If you’re partial to a keyboard you already own, you can also invest in a keyboard cover that fits over your keyboard and provides elevated keys.\n\nIn this article: Camiysn Typewriter-Style Mechanical Gaming Keyboard, UBOTIE Colorful Computer Wireless Keyboard Mouse Combos and HUO JI E-Yooso Z-88 Wired Typewriter-Style Mechanical Gaming Keyboard\n\nWhat people say about typing with special keyboards for long nails\n\nThere are a number of keyboards available on Amazon that are designed to make typing easier for people with long nails. One of the more popular products is the Camiysn Typewriter-Style Mechanical Gaming Keyboard, which has circular, elevated keys.\n\n“If you like that old-school typewriter sound, this is the keyboard for you,” one customer raved in a review. “I also have natural long nails and this keyboard makes typing with them a pure pleasure. So kudos for the ergonomic design and the price is a great value for the money spent.”\n\nAnother happy customer wrote: “I worked in customer service for about six years and I would say this is the best keyboard I’ve ever purchased. It’s great [for] women who wear long nails because the keys poke out to you. I love the typing sound that it makes because it allows my customers to hear the work that I’m doing for them, the LED lights are super cute and help [me] see my keys better when working late nights.”\n\nBest keyboards for typing with long nails\n\nCamiysn Typewriter-Style Mechanical Gaming Keyboard\n\nThis long nail-friendly keyboard is loaded with features such as backlit keys, a detachable magnetic wrist rest, adjustable rear feet and round raised keycaps. The keyboard, which comes in seven fun colors, is plugged in via a USB cable.\n\nUBOTIE Colorful Computer Wireless Keyboard Mouse Combos\n\nIf you prefer all your computer accessories to match, consider this wireless mouse and keyboard combo. The keyboard has retro-style round and raised keypads to make typing with long nails easier. It comes in 10 different colors with a matching colorful mouse.\n\nGEEZER Wireless Keyboard Mouse Combo\n\nFor even more color combinations, try this wireless keyboard and mouse set, which is available in 25 different hues. Both the keyboard and mouse are connected to your computer via a single wireless USB, which allows them to connect at a range of up to 33 feet. The keys on the keyboard are even detachable to make them easier to clean.\n\nTypewriter Style Mechanical Gaming Keyboard\n\nAnother great backlit option, this typewriter-style keyboard has rounded, elevated keys, which are easier on acrylic nails. When you type, it responds with audible clicks, which many users enjoy. The stepped layout offers an ergonomic angle and the concave keycap design allows for more comfortable typing.\n\nHUO JI E-Yooso Z-88 Wired Typewriter-Style Mechanical Gaming Keyboard\n\nAlthough this may look like a simple black or white keyboard when it’s off, powering up the backlights yields a fun surprise: The keys become illuminated with a rainbow backlight. The wired keyboard is equipped with mechanical keys that have medium resistance, an audible clicky sound and tactile feedback.\n\nAULA F99 Wireless Mechanical Keyboard\n\nIf you prefer raised keys with a standard square shape, consider this wireless model. Customers report a comfortable experience using this device with long nails. The gray-and-white keyboard can be connected to up to five devices at a time, including a computer, gaming console, tablet and more.\n\nYUNZII X71 Transparent Mechanical Keyboard with Clear Keycaps\n\nThis Bluetooth-equipped wireless keyboard is crafted from a high-transparency polycarbonate material, which allows you to see the inner workings of the device. Perfect for gaming, this keyboard is outfitted with colorful LED backlights that make it easier to type in the dark.\n\nTrueque Wireless Keyboard and Mouse Combo with Retro Round Keycaps and Phone Holder\n\nThis full-size keyboard has a slot across the top that you can use to hold your smartphone or tablet upright while you type. Both the wireless keyboard and the included mouse feature power switches and automatic sleep mode, which activates after 10 minutes of inactivity to help extend battery life.\n\nHiground Crystal Opal Basecamp 65% Mechanical USB Wired Gaming Keyboard\n\nPeople with long nails report that the raised keys on this wireless keyboard contribute to a more comfortable typing experience than flatter keyboards. The backlit keyboard has customizable RGB lighting, which gives a modern look but also adds convenience for gamers. The letters are printed on the sides of the keys rather than the top, which prevents fading.\n\nYUNZII X98 QMK/VIA Wireless Mechanical Gaming Keyboard with Knob\n\nThis super versatile gaming keyboard offers a multifunction knob to adjust volume and RGB effects, a tri-mode connection, nonslip stand and 2.4gHz wireless dongle. It’s RGB backlit for gorgeous rainbow colored lighting and features shortcuts to change RGB settings.\n\nPrices listed reflect time and date of publication and are subject to change.\n\nCheck out our Daily Deals for the best products at the best prices and sign up here to receive the BestReviews weekly newsletter full of shopping inspo and sales.\n\nBestReviews spends thousands of hours researching, analyzing and testing products to recommend the best picks for most consumers. BestReviews and its newspaper partners may earn a commission if you purchase a product through one of our links."} +{"url": "https://www.wallstreet-online.de/nachricht/20716512-schwellenlaender-rallye-voraus-trotz-krieg-indiens-aktienfonds-kapital-anziehen", "title": "Schwellenländer - Rallye voraus ?: Trotz Krieg : Warum Indiens Aktienfonds jetzt plötzlich Kapital anziehen | wallstreetONLINE", "publish_date": "2026-04-10T19:49:15Z", "full_text": "Wie Bloomberg unter Berufung auf Daten der Association of Mutual Funds in India berichtet, lagen die Nettozuflüsse in aktienorientierte Fonds bei 404,5 Milliarden Rupien. Im Februar waren es noch 259,8 Milliarden Rupien. Trotz eskalierender geopolitischer Spannungen und heftiger Schwankungen an den Märkten griffen Anleger also beherzt zu.\n\nMitten in Krieg, Börsenstress und globaler Nervosität setzen Indiens Privatanleger ein überraschendes Signal: Im März haben sich die Zuflüsse in indische Aktienfonds deutlich beschleunigt.\n\nDies ist umso bemerkenswerter, da der NSE Nifty 50, Indiens Leitindex, im März um mehr als elf Prozent einbrach. Es war der stärkste Monatsverlust seit sechs Jahren. Gleichzeitig zogen globale Investoren laut Bloomberg 14 Milliarden US-Dollar ab – ein Rekordwert.\n\nDoch genau hier liegt der brisante Punkt: Während ausländische Anleger sich zurückzogen, stemmten sich heimische Investoren und Institutionen gegen den Ausverkauf. Vor allem Aktienfonds halfen dabei, einen großen Teil des Abgabedrucks aufzufangen.\n\nFür den Markt ist das ein wichtiges Signal. Die Daten zeigen nämlich, dass die inländische Nachfrage nach Aktien in Indien selbst in einer Phase extremer Unsicherheit nicht zusammenbricht. Das reicht zwar noch nicht aus, um die anhaltenden Abflüsse aus dem Ausland komplett auszugleichen. Es zeigt jedoch, wo derzeit die eigentliche Stütze des Marktes sitzt: im Inland.\n\nDie entscheidende Frage lautet nun: Handelt es sich dabei um Trotz-Käufe in einem Crash oder ist dies der Beginn einer neuen Stärkephase am indischen Aktienmarkt?\n\nKeine Lust auf hohe Order- und Depotgebühren? Dann schnell zu SMARTBROKER+ wechseln: Alle nachfolgend vorgestellten Aktien handeln Sie über gettex ab 0 Euro*.\n\n*ab 500 Euro Ordervolumen, zzgl. marktüblicher Spreads und Zuwendungen Dann schnell zuAlle nachfolgend vorgestellten Aktien handeln Sie über gettex ab 0 Euro*.*ab 500 Euro Ordervolumen, zzgl. marktüblicher Spreads und Zuwendungen\n\n\n\nAutor: Ferdinand Hammer, wallstreetONLINE Redaktion\n\nDer NIFTY 50 HKD Index Indicative Net Asset Values wird zum Zeitpunkt der Veröffentlichung der Nachricht mit einem Plus von +1,27 % und einem Kurs von 1.934PKT auf Stuttgart (10. April 2026, 09:52 Uhr) gehandelt.\n\n\n\n"} +{"url": "https://www.wallstreet-online.de/nachricht/20718345-konter-anthropic-ki-wettrennen-eskaliert-openai-rivalen-druck", "title": "Konter gegen Anthropic : KI - Wettrennen eskaliert : OpenAI setzt Rivalen unter Druck | wallstreetONLINE", "publish_date": "2026-04-10T19:49:15Z", "full_text": "Laut einem von Bloomberg eingesehenen Schreiben habe OpenAI seine Kapazitäten \"schnell und kontinuierlich\" erhöht. Das verschaffe dem Unternehmen Vorteile in einer Phase stark wachsender Nachfrage nach KI-Anwendungen.\n\nIm Wettbewerb der KI-Giganten verschärft sich der Ton. OpenAI hat Investoren mitgeteilt, dass der Konzern seinem Rivalen Anthropic bei der entscheidenden Ressource Rechenleistung deutlich voraus sei. Grundlage sei ein früher und aggressiver Ausbau der Infrastruktur.\n\n\"Compute ist der Engpass\"\n\nOpenAI macht die strategische Bedeutung klar. \"Diese Lücke ist von Bedeutung, da die Rechenleistung mittlerweile eine Produktbeschränkung darstellt\", heißt es in dem Memo. Das Unternehmen sieht darin einen zentralen Faktor für die Skalierung seiner Software.\n\nHintergrund ist die wachsende Konkurrenz durch Anthropic, das mit neuen Modellen Marktanteile gewinnt und einen Börsengang prüft. Gleichzeitig kämpfte das Unternehmen zuletzt mit Ausfällen, ausgelöst durch hohe Nachfrage.\n\nZahlen zeigen wachsende Differenz\n\nOpenAI beziffert seine verfügbare Leistung für 2025 auf 1,9 Gigawatt. Das entspricht etwa der Stromversorgung von rund 750.000 Haushalten in den USA. Für 2026 erwartet der Konzern eine Kapazität im niedrigen zweistelligen Gigawatt-Bereich. Bis 2030 sollen es rund 30 Gigawatt werden.\n\nAnthropic liegt laut Schätzung von OpenAI zurück. Demnach erreichte der Rivale 2025 etwa 1,4 Gigawatt und könnte 2026 zwischen 7 und 8 Gigawatt liegen. \"Selbst am oberen Ende dieses Bereichs liegt unsere Steigerungsrate deutlich vorn und baut ihren Vorsprung weiter aus“, schreibt OpenAI.\n\nAnthropic kontert mit Milliardenoffensive\n\nAnthropic investiert ebenfalls massiv. Das Unternehmen plant Ausgaben von 50 Milliarden US-Dollar für Rechenzentren in den USA. Zudem sicherte sich die Firma zusätzliche Kapazitäten über Kooperationen mit Broadcom und Google. Ab 2027 sollen so etwa 3,5 Gigawatt verfügbar sein.\n\nFinanzchef Krishna Rao erklärte: \"Diese bahnbrechende Partnerschaft mit Google und Broadcom ist eine Fortsetzung unseres konsequenten Ansatzes beim Ausbau der Infrastruktur.\"\n\nStreit über Strategie verschärft sich\n\nWährend OpenAI auf Tempo setzt, galt Anthropic lange als vorsichtiger Investor. CEO Dario Amodei sagte dazu: \"Wir als Unternehmen versuchen, so verantwortungsbewusst wie möglich zu wirtschaften.\" Zugleich kritisierte er indirekt Wettbewerber: \"Und dann gibt es meiner Meinung nach einige Akteure, die nach dem Motto ['You only live once'] handeln.\"\n\nOpenAI weist diese Sicht zurück. Rückblickend wirke die Zurückhaltung des Rivalen \"weniger wie Disziplin, sondern eher wie eine Unterschätzung dessen, wie schnell die Nachfrage steigen würde\".\n\nAutorin: Saskia Reh, wallstreetONLINE Redaktion\n\nKeine Lust auf hohe Order- und Depotgebühren? Dann schnell zu SMARTBROKER+ wechseln: Alle nachfolgend vorgestellten Aktien handeln Sie über gettex ab 0 Euro*.\n\n*ab 500 Euro Ordervolumen, zzgl. marktüblicher Spreads und Zuwendungen Dann schnell zuAlle nachfolgend vorgestellten Aktien handeln Sie über gettex ab 0 Euro*.*ab 500 Euro Ordervolumen, zzgl. marktüblicher Spreads und Zuwendungen"} +{"url": "https://www.zazoom.it/2026-04-10/palermo-morti-due-operai-caduti-da-una-gru/18980070/", "title": "Palermo morti due operai caduti da una gru", "publish_date": "2026-04-10T19:49:15Z", "full_text": "Palermo morti due operai caduti da una gru\n\nA Palermo, due operai sono deceduti dopo essere caduti da una gru durante un intervento lavorativo. Un altro operaio è riuscito a salvarsi ed è rimasto illeso. La notizia è stata riportata da Pierluigi Vito. Le autorità stanno indagando sulle circostanze dell’incidente.\n\nDue operai sono morti dopo essere caduti da una gru; un terzo è rimasto illeso. Servizio di Pierluigi Vito TG2000. 🔗 Leggi su Tv2000.it © Tv2000.it - Palermo, morti due operai caduti da una gru Tragedia a Palermo, morti due operai caduti da una gru(Adnkronos) – Dramma a Palermo, dove due operai sono morti dopo essere precipitati da una gru. Leggi anche: Incidente sul lavoro a Palermo, due operai morti caduti da una gru Palermo, morti due operai caduti da una gru Temi più discussi: Incidente sul lavoro a Palermo, morti due operai caduti da una gru; Cadono da una gru, morti due operai a Palermo; Incidente sul lavoro a Palermo, morti due operai caduti da una gru; Incidenti sul lavoro: morti un vigile del fuoco in Veneto e due operai in Sicilia, feriti tra Lombardia, Emilia-Romagna e Piemonte. Incidente sul lavoro a Palermo, morti due operai caduti da una gruLa tragedia è avvenuta in via Ruggero Marturano. Un terzo operaio si sarebbe salvato finendo sui copertoni di un negozio di ricambio pneumatici ... tg24.sky.it VIDEO| Tragedia sul lavoro a Palermo, crolla il cestello di una gru: morti due operaiTragedia del lavoro a Palermo, dove due operai sono morti a seguito del crollo di un cestello per lavori edili in via Ruggero Marturano ... dire.it Segui con La Sicilia la diretta testuale di Frosinone-Palermo, calcio d'inizio alle 20.30! - facebook.com facebook Cede il 'braccio' di una gru: morti due operai a Palermo x.com"} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-10/Raw/raw_gdelt_asset_metals_derivatives.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-10/Raw/raw_gdelt_asset_metals_derivatives.jsonl new file mode 100644 index 0000000..58a01d5 --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-10/Raw/raw_gdelt_asset_metals_derivatives.jsonl @@ -0,0 +1,7 @@ +{"url": "https://wpdh.com/ixp/854/p/the-4-best-classic-diners-in-new-york-state/", "url_mobile": "", "title": "The Best Classic Diners In New York State", "seendate": "20260410T193000Z", "socialimage": "https://townsquare.media/site/854/files/2026/04/attachment-mixcollage-10-apr-2026-08-08-am-2689.jpg?&q=75&format=natural", "domain": "wpdh.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://www.vermilionstandard.com:443/life/food/new-air-canada-cafe-yvr", "url_mobile": "", "title": "New Air Canada Café at YVR taps into West Coast inspiration", "seendate": "20260410T190000Z", "socialimage": "", "domain": "vermilionstandard.com", "language": "English", "sourcecountry": "Canada"} +{"url": "https://www.oneidadispatch.com/2026/04/10/strawberry-pots/", "url_mobile": "", "title": "Strawberry pot window make for striking , efficient displays", "seendate": "20260410T190000Z", "socialimage": "https://www.oneidadispatch.com/wp-content/uploads/2026/04/Gardening_-_Strawberry_Pots_3_628-1.jpg", "domain": "oneidadispatch.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://www.newsday.com/business/healthgrades-long-island-hospitals-patient-safety-ez30ovxf", "url_mobile": "", "title": "Eight Long Island hospitals rank among the nation best for patient safety", "seendate": "20260410T190000Z", "socialimage": "https://cdn.newsday.com/ace/c:ZjlkYjA5NjktNWM0YS00:ZGI0ZTI4YTQtNjFkZi00/landscape/1280", "domain": "newsday.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://www.investorideas.com/news/2026/main/04101-cpi-inflation-energy-surge-market-impact.asp", "url_mobile": "", "title": "March CPI Surges to 3 . 3 % as Iran War Drives Energy Costs Higher ; What It Means for Investors", "seendate": "20260410T190000Z", "socialimage": "https://www.investorideas.com/images/investorideas-socialmedia.jpg", "domain": "investorideas.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://www.penarthtimes.co.uk/news/26009421.major-airlines-cut-flights-hike-fares-fuel-costs-rise/", "url_mobile": "", "title": "Major airlines cut flights and hike fares as fuel costs rise", "seendate": "20260410T190000Z", "socialimage": "https://www.penarthtimes.co.uk/resources/images/20768302.jpg?type=og-image&xType=0&yType=0", "domain": "penarthtimes.co.uk", "language": "English", "sourcecountry": "United Kingdom"} +{"url": "https://wrco.com/news/2026/04/10/utilities-seek-federal-pause-on-grid-bidding-amid-ai-driven-power-demand", "url_mobile": "", "title": "Utilities seek federal pause on grid bidding amid AI - driven power demand - WRCO", "seendate": "20260410T190000Z", "socialimage": "https://civicmedia.us/wp-content/uploads/2026/04/asseGrant-County-Data-Centers2.jpg", "domain": "wrco.com", "language": "English", "sourcecountry": "United States"} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-10/Raw/raw_gdelt_macro_central_banks.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-10/Raw/raw_gdelt_macro_central_banks.jsonl new file mode 100644 index 0000000..e62b63f --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-10/Raw/raw_gdelt_macro_central_banks.jsonl @@ -0,0 +1,10 @@ +{"url": "https://hitsfm.net/business/9a906e8ed2f1be1191aa6d7dc2574e4c", "url_mobile": "", "title": "Business - HITS FM", "seendate": "20260410T190000Z", "socialimage": "https://s3.amazonaws.com/syndication.abcaudio.com/files/2026-04-10/Getty_Strait-of-hormuz_041026.jpg", "domain": "hitsfm.net", "language": "English", "sourcecountry": "United States"} +{"url": "https://www.koratdaily.com/blog.php?id=18542", "url_mobile": "", "title": "3 องค์กรเอกชนโคราชตั้งวงหารือ ยื่นข้อเสนอพยุงธุรกิจ ลดภาระ ปชช . หลังเผชิญวิกฤตพลังงาน | KORATDAILY ONLINE | หนังสือพิมพ์โคราชคนอีสาน", "seendate": "20260410T190000Z", "socialimage": "https://www.koratdaily.com/images-upload/1775844159.jpg", "domain": "koratdaily.com", "language": "Thai", "sourcecountry": "Thailand"} +{"url": "https://globalpunjabtv.com/the-center-agreed-to-the-demand-of-chief-minister-bhagwant-singh-maan/", "url_mobile": "", "title": "ਕੇਂਦਰ ਨੇ ਮੁੱਖ ਮੰਤਰੀ ਭਗਵੰਤ ਸਿੰਘ ਮਾਨ ਦੀ ਮੰਗ ਤੇ ਸਹਿਮਤ ਪ੍ਰਗਟਾਈ - Global Punjab Tv punjabi news", "seendate": "20260410T190000Z", "socialimage": "https://globalpunjabtv.com/wp-content/uploads/2026/04/press-note-image-2-5.jpeg", "domain": "globalpunjabtv.com", "language": "Punjabi", "sourcecountry": "India"} +{"url": "https://www.kacu.org/2026-04-10/inflation-surges-to-highest-level-in-nearly-2-years-as-energy-costs-spike", "url_mobile": "https://www.kacu.org/2026-04-10/inflation-surges-to-highest-level-in-nearly-2-years-as-energy-costs-spike?_amp=true", "title": "Inflation surges to highest level in nearly 2 years as energy costs spike", "seendate": "20260410T190000Z", "socialimage": "http://npr-brightspot.s3.amazonaws.com/8a/88/04f517584d3c86cbe59e03de8829/gettyimages-2270119940.jpg", "domain": "kacu.org", "language": "English", "sourcecountry": "United States"} +{"url": "https://wgme.com/news/nation-world/trump-summons-banking-chiefs-for-a-closed-door-meeting-about-an-ai-model-report-jerome-powell-scott-bessent", "url_mobile": "", "title": "Trump summons banking chiefs for a closed - door meeting about an AI model : report", "seendate": "20260410T190000Z", "socialimage": "https://wgme.com/resources/media2/16x9/5891/1320/0x307/90/4ed63352-c617-44a9-b145-b1935fcd281e-GettyImages2270096602.jpg", "domain": "wgme.com", "language": "English", "sourcecountry": "United States"} +{"url": "http://www.em.com.br/economia/2026/04/7394973-por-que-governo-trump-voltou-a-atacar-o-pix-e-o-que-eua-podem-fazer-contra-ele.html", "url_mobile": "https://www.em.com.br/economia/2026/04/amp/7394973-por-que-governo-trump-voltou-a-atacar-o-pix-e-o-que-eua-podem-fazer-contra-ele.html", "title": "Por que governo Trump voltou a atacar o Pix ( e o que EUA podem fazer contra ele )? ", "seendate": "20260410T190000Z", "socialimage": "https://midias.em.com.br/_midias/jpg/2026/04/10/0dc74ec0-3436-11f1-9d5c-8ba507d7dbde-66013210.jpg", "domain": "em.com.br", "language": "Portuguese", "sourcecountry": "Brazil"} +{"url": "https://1037qcountry.com/news/030030-soaring-gas-prices-leads-to-biggest-monthly-inflation-spike-in-four-years-in-march/", "url_mobile": "", "title": "Soaring gas prices leads to biggest monthly inflation spike in four years in March", "seendate": "20260410T190000Z", "socialimage": "https://news.sagacom.com/wp-content/blogs.dir/3/files/2026/04/AP26098003992706-620x400.jpg", "domain": "1037qcountry.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://www.elsiglodetorreon.com.mx/noticia/2026/precio-del-dolar-hoy-viernes-10-de-abril-peso-mexicano-perfila-su-mejor-semana-en-un-ano.html", "url_mobile": "", "title": "Precio del dólar hoy viernes 10 de abril : peso mexicano perfila su mejor semana en un año", "seendate": "20260410T190000Z", "socialimage": "https://tecolotito.elsiglodetorreon.com.mx/i/2026/04/2000143.jpeg", "domain": "elsiglodetorreon.com.mx", "language": "Spanish", "sourcecountry": "Mexico"} +{"url": "https://www.risk.net/markets/7963346/the-swap-futures-comeback", "url_mobile": "", "title": "The swap futures comeback - Risk . net", "seendate": "20260410T190000Z", "socialimage": "https://www.risk.net/sites/default/files/styles/metatag_image_large_webp/public/2026-04/Eris-comeback-GettyImages-516173866.jpg.webp?itok=VlcNj_xH", "domain": "risk.net", "language": "English", "sourcecountry": "United Kingdom"} +{"url": "https://abc30.com/post/prices-surged-march-oil-shock-set-off-iran-war/18865879/", "url_mobile": "", "title": "Prices surged in March after oil shock set off by Iran war", "seendate": "20260410T190000Z", "socialimage": "https://cdn.abcotvs.com/dip/images/18856581_LA-Gas-Prices-img.png", "domain": "abc30.com", "language": "English", "sourcecountry": "United States"} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-10/Raw/raw_gdelt_macro_geopolitics_risk.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-10/Raw/raw_gdelt_macro_geopolitics_risk.jsonl new file mode 100644 index 0000000..e52d366 --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-10/Raw/raw_gdelt_macro_geopolitics_risk.jsonl @@ -0,0 +1,9 @@ +{"url": "https://www.zonebourse.com/actualite-bourse/le-dollar-s-affaiblit-avec-l-anticipation-de-pourparlers-sur-le-moyen-orient-ce7e50d9db8dfe23", "url_mobile": "", "title": "Le dollar saffaiblit avec lanticipation de pourparlers sur le Moyen - Orient", "seendate": "20260410T190000Z", "socialimage": "https://www.zonebourse.com/images/twitter_ZB_fdblanc.png", "domain": "zonebourse.com", "language": "French", "sourcecountry": "France"} +{"url": "https://mignews.com/news/technology/severnaya-koreya-sozdala-elektromagnitnuyu-bombu.html", "url_mobile": "", "title": "Северная Корея создала электромагнитную бомбу | MigNews - Новости Израиля и Мира на русском языке", "seendate": "20260410T190000Z", "socialimage": "https://mignews.com/media/cache/c3/c7/c3c77070ff24a6d343469d6f9f3a459a.jpg", "domain": "mignews.com", "language": "Russian", "sourcecountry": ""} +{"url": "https://www.sunstar.com.ph/davao/vp-sara-questions-pbbm-on-aid-amid-energy-crisis", "url_mobile": "https://www.sunstar.com.ph/amp/story/davao/vp-sara-questions-pbbm-on-aid-amid-energy-crisis", "title": "VP Sara Challenges Marcos on Aid Amid 2026 Energy Crisis", "seendate": "20260410T190000Z", "socialimage": "https://media.assettype.com/sunstar%2F2026-04-10%2Ftg1rk4ba%2FInspire-Inclusion-1.png?&ar=40%3A21&auto=format%2Ccompress&ogImage=true&mode=crop&enlarge=true&overlay=false&overlay_position=bottom&overlay_width=100", "domain": "sunstar.com.ph", "language": "English", "sourcecountry": "Philippines"} +{"url": "https://hitsfm.net/business/9a906e8ed2f1be1191aa6d7dc2574e4c", "url_mobile": "", "title": "Business - HITS FM", "seendate": "20260410T190000Z", "socialimage": "https://s3.amazonaws.com/syndication.abcaudio.com/files/2026-04-10/Getty_Strait-of-hormuz_041026.jpg", "domain": "hitsfm.net", "language": "English", "sourcecountry": "United States"} +{"url": "https://www.novosti.rs/planeta/svet/1596010/uskoro-cemo-saznati-tramp-otkrio-kad-biti-poznato-pregovori-sad-irana-biti-uspesni-punimo-brodove-najboljim-oruzjem", "url_mobile": "https://www.novosti.rs/amp/planeta/svet/1596010/uskoro-cemo-saznati-tramp-otkrio-kad-biti-poznato-pregovori-sad-irana-biti-uspesni-punimo-brodove-najboljim-oruzjem", "title": " USKORO ĆEMO SAZNATI Tramp otkrio kad će biti poznato da li će pregovori SAD i Irana biti uspešni : Mi punimo brodove najboljim oružjem", "seendate": "20260410T190000Z", "socialimage": "https://www.novosti.rs/data/images/2026-04-07/687584_tan2026-04-0622453721-5_f.jpg", "domain": "novosti.rs", "language": "Serbian", "sourcecountry": "Serbia"} +{"url": "http://www.shanghainews.net/news/278975895/china-sees-solid-rise-in-cross-border-travel-in-q1-with-foreign-national-trips-surging", "url_mobile": "", "title": "China sees solid rise in cross - border travel in Q1 , with foreign national trips surging", "seendate": "20260410T190000Z", "socialimage": "https://image.chitra.live/api/v1/wps/41e8625/84e7f982-1d32-48b3-a136-2c318225db5a/0/XxjwshE000114-20260410-CBMFN0A001-600x315.jpg", "domain": "shanghainews.net", "language": "English", "sourcecountry": "China"} +{"url": "https://udn.com/news/story/7270/9433920", "url_mobile": "https://udn.com/news/amp/story/7270/9433920", "title": "亞洲最新隱奢海島誕生 ! Club Med沙巴度假村開訂 4天3夜2萬起全包 | 流行消費 | 生活", "seendate": "20260410T190000Z", "socialimage": "https://uc.udn.com.tw/photo/t3/2026/04/10/34843622.jpg", "domain": "udn.com", "language": "Chinese", "sourcecountry": "Taiwan"} +{"url": "https://www.bankingnews.gr/diethni/articles/867952/synexizoun-na-eksoplizoun-tous-egklimaties-i-germania-paredose-5-tethorakismena-oximata-mediguard-stin-ethnofroura-tis-oukranias", "url_mobile": "", "title": "Συνεχίζουν να εξοπλίζουν τους εγκληματίες - Η Γερμανία παρέδωσε 5 τεθωρακισμένα οχήματα MEDIGUARD στην Εθνοφρουρά της Ουκρανίας", "seendate": "20260410T190000Z", "socialimage": "https://www.bankingnews.gr/media/k2/items/cache/68360f82a059c51093305359b4a5ece3_XL.jpg", "domain": "bankingnews.gr", "language": "Greek", "sourcecountry": "Greece"} +{"url": "https://www.cravenherald.co.uk/news/national/26012377.airports-warn-systemic-jet-fuel-shortage-strait-hormuz-stays-closed/", "url_mobile": "", "title": "Airports warn of systemic jet fuel shortage if Strait of Hormuz stays closed", "seendate": "20260410T190000Z", "socialimage": "https://www.cravenherald.co.uk/resources/images/20771955.jpg?type=og-image", "domain": "cravenherald.co.uk", "language": "English", "sourcecountry": "United Kingdom"} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-10/Raw/raw_gdelt_macro_yields_dollar.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-10/Raw/raw_gdelt_macro_yields_dollar.jsonl new file mode 100644 index 0000000..93b44d6 --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-10/Raw/raw_gdelt_macro_yields_dollar.jsonl @@ -0,0 +1,9 @@ +{"url": "https://www.saultstar.com:443/opinion/iran-ceasefire-brings-relief-not-resolution", "url_mobile": "", "title": "Iran ceasefire brings relief , not resolution", "seendate": "20260410T190000Z", "socialimage": "", "domain": "saultstar.com", "language": "English", "sourcecountry": "Canada"} +{"url": "https://baijiahao.baidu.com/s?id=1861955604405523399", "url_mobile": "", "title": "产教融合背景下AI赋能产业创新人才培养新路径探析", "seendate": "20260410T190000Z", "socialimage": "", "domain": "baijiahao.baidu.com", "language": "Chinese", "sourcecountry": "China"} +{"url": "https://www.elmorrocotudo.cl/noticia/deporte/nicolas-jarry-arrasa-en-madrid-no-cede-sets-y-ya-esta-en-semifinales-del-challenger", "url_mobile": "", "title": "Nicolás Jarry arrasa en Madrid : no cede sets y ya está en semifinales del Challenger", "seendate": "20260410T190000Z", "socialimage": "https://cdn.elmorrocotudo.cl/sites/elmorrocotudo.cl/files/imagecache/opengraph/imagen_noticia/jarry_challenger_edit_v2.png", "domain": "elmorrocotudo.cl", "language": "Spanish", "sourcecountry": "Chile"} +{"url": "https://www.finanzen.net/nachricht/rohstoffe/rohstoffpreise-am-freitagabend-15604785", "url_mobile": "", "title": "Rohstoffpreise am Freitagabend", "seendate": "20260410T190000Z", "socialimage": "https://images.finanzen.net/mediacenter/unsortiert/oelpreis-gopixa-0069.jpg", "domain": "finanzen.net", "language": "German", "sourcecountry": "Germany"} +{"url": "https://www.ilgiorno.it/varese/cronaca/arcisate-malore--guida-trattore-79enne-condizioni-disperate-764da021", "url_mobile": "", "title": "Arcisate , ha un malore mentre guida il trattore nei campi : 79enne in condizioni disperate", "seendate": "20260410T190000Z", "socialimage": "https://www.ilgiorno.it/image-service/view/acePublic/alias/contentid/ZGNhZTVhM2UtMDEyZC00/0/il-trattore-contro-il-mure-di-confine-l-uomo-e-gravissimo-in-ospedale.jpg?f=16:9", "domain": "ilgiorno.it", "language": "Italian", "sourcecountry": "Italy"} +{"url": "https://www.pressdemocrat.com/2026/04/09/keyboards-and-keyboard-covers-that-make-typing-with-long-nails-a-breeze/", "url_mobile": "", "title": "Keyboards and keyboard covers that make typing with long nails a breeze", "seendate": "20260410T190000Z", "socialimage": "https://www.pressdemocrat.com/wp-content/uploads/2026/04/keyboards-keyboard-covers-for-long-nails-new-ajkshdb-46a21b.jpg", "domain": "pressdemocrat.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://www.wallstreet-online.de/nachricht/20716512-schwellenlaender-rallye-voraus-trotz-krieg-indiens-aktienfonds-kapital-anziehen", "url_mobile": "", "title": "Schwellenländer - Rallye voraus ?: Trotz Krieg : Warum Indiens Aktienfonds jetzt plötzlich Kapital anziehen | wallstreetONLINE", "seendate": "20260410T190000Z", "socialimage": "https://assets.wallstreet-online.de/_media/22490/size_645/585472229.webp", "domain": "wallstreet-online.de", "language": "German", "sourcecountry": "Germany"} +{"url": "https://www.wallstreet-online.de/nachricht/20718345-konter-anthropic-ki-wettrennen-eskaliert-openai-rivalen-druck", "url_mobile": "", "title": "Konter gegen Anthropic : KI - Wettrennen eskaliert : OpenAI setzt Rivalen unter Druck | wallstreetONLINE", "seendate": "20260410T190000Z", "socialimage": "https://assets.wallstreet-online.de/_media/22490/symbolbilder/size_645/554045489.webp", "domain": "wallstreet-online.de", "language": "German", "sourcecountry": "Germany"} +{"url": "https://www.zazoom.it/2026-04-10/palermo-morti-due-operai-caduti-da-una-gru/18980070/", "url_mobile": "", "title": "Palermo morti due operai caduti da una gru", "seendate": "20260410T190000Z", "socialimage": "https://www.tv2000.it/tg2000/wp-content/uploads/sites/16/2026/04/0-145.jpg", "domain": "zazoom.it", "language": "Italian", "sourcecountry": "Italy"} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Full_text/full_text_asset_metals_derivatives.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Full_text/full_text_asset_metals_derivatives.jsonl new file mode 100644 index 0000000..0283e80 --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Full_text/full_text_asset_metals_derivatives.jsonl @@ -0,0 +1,6 @@ +{"url": "https://tech.ifeng.com/c/8sGYfvCKmod", "title": "DeepSeek , 该卸下扫地僧的枷锁了", "publish_date": "2026-04-12T14:43:52Z", "full_text": "我每次翻《天龙八部》,翻到少林寺藏经阁那一段,都要停下来。\n\n萧远山、萧峰父子对上慕容博、慕容复父子,鸠摩智再从旁搅局,三十年的血海深恨搅在一处,眼看就要分出生死。就在这当口,一个枯瘦的扫地僧走了出来。\n\n萧峰的降龙十八掌打在他身上,他虽受内伤吐血,却以浑厚内力生生受之;他举手投足间让慕容博陷入「假死」复又救活,这种生死由心的境界,令在场一众顶尖高手莫不震慑失语。\n\n这一刻,谁强谁弱,答案不言而喻。\n\nAI 圈最近几年,流行把 DeepSeek(深度求索)比作这位老僧。在所有人眼里,AI 赛道的格局早已注定,海外有御三家,国内有大厂和彼时风头正盛的 AI 六小虎,轮不到旁人来置喙。\n\n结果一家做量化交易出身的中国公司,悄没声儿地走出来,用一套从天而降的招法,在各项核心评测上与这帮人正面交手,打得有来有回。\n\n只是,扫地僧出场,是《天龙八部》行将收尾的时刻。他的使命是终结纷争、化解戾气,然后全书走向尾声。可大模型的故事,没有尾声,也没有终章,只有下一回,还有下下一回。\n\n把 DeepSeek 比作扫地僧,是对它过去的最高赞誉,但如果这三个字正在慢慢变成困住它的枷锁,我倒觉得,赞誉和催命符,有时候只在一念之间。\n\n扫地僧是怎么练成的\n\n金庸写扫地僧,从来不正面写他的功夫。他写的是别人的反应,萧峰愣了,慕容复愣了,旁观的人也愣了。高手的境界,要从旁人失语的瞬间才能传递出来。\n\nDeepSeek 的故事,也暗合这个逻辑。\n\n作为杭州的一家对冲基金,外人提到幻方量化,第一反应是期货、是算法交易、是数学天才们盯着屏幕上跳动的数字。这和 AI 大模型,八竿子打不着,却悄悄把一批工程师和研究员聚在一起做大模型。\n\n2023 年 11 月,他们发布首个开源代码大模型 DeepSeek Coder,后续拿出了一个 67B 的语言模型。在官方给出的多项评测中,67B 超过了 LLaMA2 70B,67B Chat 在部分中文和开放式评测中优于 GPT 3.5。只是,圈内少数几个消息灵通的人注意到了,大多数人没注意到。扫地僧还在扫地,少林寺的人都在忙着练少林长拳。\n\n让其开始崭露头角,是 2024 年 5 月 7 日发布的 V2。V2 用的是 MoE(混合专家)架构,总参数 2360 亿,但每次推理实际激活的只有 210 亿。与此同时,V2 首次采用了 MLA(多头潜在注意力)机制,大幅压缩了推理时的显存占用。\n\n两相叠加,让模型在同等效果下,跑得更快,花得更少。用金庸的话来说,这叫以柔克刚,以精妙的内功路数,弥补了真气总量上的不足。\n\n但砸出最大水花的,是定价。V2 的 API 定价,每百万 token 输入 1 元,输出 2 元。GPT-4 Turbo 当时是它的七十倍,Meta 的 Llama3 70B 是它的七倍。一块钱,一百万个 token,大约相当于一本《三国演义》的字数。\n\n这个价格摆出来,让整个国内大模型市场为之色变。当月,字节、阿里、百度、腾讯、讯飞、智谱,一家接一家跳出来宣布降价,最高降幅 97%,部分轻量级模型直接免费开放。\n\n一场持续了大半年的价格战,就这么被 DeepSeek 的一句定价点燃了。那时候,业内给 DeepSeek 送了个外号,价格屠夫。\n\n美国的半导体咨询公司 SemiAnalysis 在那段时间写了一篇分析,说这家公司有可能成为 OpenAI 的对手,也有可能碾压其他开源大模型。当时读到这句话的人,大概有一半觉得是危言耸听。一年多以后回头看,没有人再觉得是危言耸听了。\n\n2024 年末的 V3 和 2025 年初的 R1,则是连续出手的两招,把对手打得目瞪口呆。DeepSeek 用极低的投入,打出了旗鼓相当的效果。\n\n更让人震惊的是参与人数,139 名工程师和研究人员完成了这个项目,而 OpenAI 同期有 1200 名研究人员,Anthropic 有 500 名。Meta 超级智能实验室负责人亚历山大·王后来说了一句被广泛流传的话,当美国人休息时,他们在工作,而且以更便宜、更快、更强的产品追上我们。\n\n紧接着便是是 R1,主打深度推理,数学、代码、逻辑,在相当多的测试维度上与 OpenAI o1 不落下风,训练方法用的是 GRPO 强化学习,靠让模型自己想清楚来提升推理能力。\n\n最要紧的一步是开源。\n\nR1 的开源,被广泛解读为一种慷慨。模型权重、技术论文、训练细节全部公开,全球开发者共享成果。这套叙事里,DeepSeek 是那个敞开藏经阁大门的人,路不拾遗,人人可进。\n\n武功秘籍直接摆桌上,谁想学谁来拿的这一手,也打破了少数几家巨头对前沿模型的垄断,让全球数以万计的中小开发者有了和顶尖模型掰手腕的资格。\n\n金庸写扫地僧,主要抓住几样东西,出身边缘、多年隐匿、一鸣惊人、技法精绝、胸怀坦荡。DeepSeek V2 的价格屠刀、V3 的成本奇迹、R1 的开源普惠,也让人们在 DeepSeek 身上,真真切切地看见了那个老僧的影子。\n\n枷锁,以及枷锁之后\n\n但武侠小说是会结束的,AI 赛道不会。\n\n每次我写 DeepSeek 的文章,底下的评论区都像藏经阁又打了一场架。有人说它安安静静做产品,不收费、不立人设,能用就用,这才是正道。有人说它连国产其他巨头都未必打得过,已经无法搅局。\n\n有人替它抱不平,有人觉得它早就该被淘汰。更有人说,「我们一直以来都没把 DeepSeek 当作优等生,而是当作扫地僧,真心希望它能如我们所愿」,这句话说得又期待,又带着一丝说不清楚的悲凉。\n\n意见如此撕裂,本身就说明了一件事。DeepSeek 所受到的关注,早已超出了一家普通 AI 公司应有的体量。捧它的人把它捧上神坛,骂它的人把它踩进泥里,没有几家公司能在舆论场里同时承受这两种极端。\n\n这篇文章大概也逃不过同样的命运,有人会说这是黑稿,有人会说这是 PR 稿,落个两头不讨好。但这无所谓,舆论从来都是这样,藏经阁里打架,不管谁赢,总有人不服。\n\n说回正题,扫地僧出场那一幕,是《天龙八部》收尾的信号。他出手,纷争平息,故事逐渐走向终章。这个叙事结构,似乎天然就带着一种大结局的气息,英雄横空出世,一招定乾坤,从此江湖太平。\n\n根据《创智记》援引知情人士消息称,按照创始人梁文锋在内部透露的时间,DeepSeek V4 将于四月下旬正式发布。\n\n爽文里的主角,每一章都要有突破,读者翻到下一页,期待的永远是更大的惊喜。\n\nV3 和 R1 用四两拨千斤的逻辑征服了世界,大众于是开始把它当成 DeepSeek 的固定输出,每一次出手都必须让硅谷巨头血溅千里,都必须让英伟达的股价抖一抖。V4 也应当如此。\n\n可在这等待一年多的时间里,外界等得有些躁动,各路声音都出来了,说一拖再拖,是不是黔驴技穷了,扫地僧要不行了?说这话的人认为 DeepSeek 理应每次出手都是奇迹,一旦慢了半拍,便是江郎才尽。\n\n慢,自然有慢的原因。\n\n3 月 29 日,DeepSeek 的服务器崩了将近十三个小时,创下网页端和 App 平台上线以来最长中断纪录。连续的服务事故暴露了 DeepSeek 在运维监控、应急预案和灾备机制上的明显短板,也给整个 AI 行业敲响警钟。\n\n当然,综合各家报道来看,V4 一再推迟的原因,还藏在芯片层面。\n\nV3 和 R1 的成功,一定程度上建立在成熟的英伟达 CUDA 生态上,DeepSeek 的工程师们在工具完备、文档详尽、社区活跃的环境里,把算法效率一点一点榨到了极限,每一步都踩得踏实。\n\nV4 要做的事,是把这套功夫移植到国产 AI 芯片上。工具链还在快速迭代,底层接口和 CUDA 差异巨大,分布式训练框架几乎需要从头重构。\n\nDeepSeek 交出的答卷,如果是在受限条件下做出来的,这让它的每一分成绩,都带着额外的含金量。哪怕梁文锋愿意为这件事多拖几个月,也是一笔非常划算的决策。\n\n至于 V4 本身,《创智记》报道称,技术重心据悉落在了 LTM(长期记忆)能力的突破上,同时将原生多模态从底层融入架构,文字和视觉在预训练阶段就融合在一起。\n\n另一个值得关注的变化,是梁文锋本人的注意力在悄悄转移。尽管在过去的一年里,包括 R1 的核心作者郭达雅在内的部分 DeepSeek 核心骨干陆续离职,不过根据《晚点 LatePost》的观察,DeepSeek 的人才基本盘依然稳固,并未出现大规模的人才流失现象。\n\n进入 2025 年下半年,梁文锋也愈发看重技术的商业落地与产品化进程,积极招募负责 Agent 领域的策略产品经理。与此同时,他正在为公司启动估值,给员工的期权一个明确的锚点,让团队对未来有更清晰的预期。\n\n综合上述种种动向不难得出一个结论:曾经心无旁骛盯着 AGI 的 DeepSeek 也得开始面对一家成熟科技公司必须面对的那些现实:商业闭环、生态建设、可持续的收入来源。\n\n扫地僧可以几十年不问江湖俗事,守着藏经阁一扫到底,一家公司,没有这个选项。\n\n《笑傲江湖》里的令狐冲凭着独孤九剑可以破尽天下武功,但当他真正坐镇恒山派,每天迎来送往,护佑门人,一招鲜远远不够,他需要的是内政、是人心、是香火代代相传的根基。奇招,解决不了日常的柴米油盐。\n\n因此,我们应该主动帮 DeepSeek 卸下「扫地僧」这个名号。这三个字是对过去的最高褒奖,却是对未来的过重负担。即便 V4 发布时没有断崖式的领先,只是一款 LTM 扎实、多模态原生融合、各项指标均衡的水桶机。\n\n从产业的角度看,这依然是巨大的成功,成功在于它或许将证明 DeepSeek 有能力从一个创造奇迹的挑战者,变成一个稳定交付的基础设施提供者。\n\n有意思的是,这件事或许本来就是双向的。《晚点 LatePost》此前的报道里,DeepSeek 对外的沟通姿态明显比以往克制,既没有大张旗鼓地预热,也没有放出足以吊足胃口的技术信号。\n\n这种低调,很难说是无意为之。\n\n他们比任何人都清楚,扫地僧这三个字背后悬着什么。每一次出手若不能再掀翻整张牌桌,舆论的落差就会被无限放大。这是一种预期管理,也是一种自我解绑——他们同样不想再背着这个包袱走下去。\n\n▲AI 模型的世界,已经从少数几家机构的专属游戏,变成了全球开发者共同参与的基础设施建设,而且这个趋势还在加速。\n\n而话说回来,当舆论都在一窝蜂盯着 DeepSeek,却少有人往旁边多看一眼。\n\n这片江湖里,国内每一家 AI 都在苦修内功,押注多模态、Agent 生态、算力布局,也都在各自的赛道上走出了自己的路数。\n\nDeepSeek 固然是那个最让人心跳加速的名字,但把眼光只锁死在它一家身上,未免看窄了这个时代。真正让天龙八部成为天龙八部的,是那一整代人各有来路,各有绝学,彼此激荡,才撑起了那个波澜壮阔的时代。\n\n扫地僧的传说,止于藏经阁那一战,藏经阁外,才是真的江湖。"} +{"url": "https://www.swindonadvertiser.co.uk/news/26014087.major-airlines-cut-flights-hike-fares-fuel-costs-rise/", "title": "Major airlines cut flights and hike fares as fuel costs rise", "publish_date": "2026-04-12T14:43:52Z", "full_text": "The ongoing conflict in the Middle East between the US, Israel, and Iran has resulted in a recent spike in fuel prices.\n\nSeveral major airlines have already responded to this spike by increasing fares, adding or increasing fuel surcharges, and cutting flights.\n\nUK airline Skybus announced last week it had ceased all flights between Cornwall and London due to \"the huge rise in the global cost of fuel\" and \"a significant drop in new passenger bookings\".\n\nRyanair CEO Michael O'Leary also warned Brits to book their summer holidays “as quickly as you can” to avoid rising costs, due to the ongoing Middle East conflict.\n\nMore major airlines cut flights and increase prices amid rising fuel costs\n\nThree more major airlines have now cut flights and increased prices due to the rising cost of fuel caused by the ongoing conflict in the Middle East:\n\nAir India\n\nAir India this week announced it was increasing its fuel surcharge on domestic and international flights.\n\nThese revised fees came into effect for UK flights on Friday (April 10), although the airline assured passengers who have already booked tickets will be unaffected by the change.\n\nAir India said: \"For the avoidance of doubt, tickets that have already been issued prior to the above times will not attract the new surcharge unless customers seek date or itinerary changes that require a recalculation of the fare.\n\n\"Air India will review its surcharges periodically and make appropriate adjustments as the situation requires.\"\n\nAir India announced this week it was increasing its fuel surcharge. (Image: Getty Images)\n\nAir India usually operates more than 60 weekly flights between India and the UK, connecting cities like Delhi, Mumbai, Bengaluru, Ahmedabad, and Amritsar to London (Heathrow and Gatwick) and Birmingham.\n\nAir New Zealand\n\nAir New Zealand has been forced to cancel more flights due to the conflict in the Middle East, with routes in and out of Auckland, Wellington, and Christchurch impacted, according to the BBC .\n\nAirlines cut flights and hike fares as fuel prices surge https://t.co/p1uad5gOHk — BBC News (UK) (@BBCNews) April 7, 2026\n\nThese flight cancellations follow several others made by the airline last month.\n\nHowever, Air New Zealand said earlier this week that the \"vast majority\" of its customers affected by the cancellations were being offered alternative flights on the same day.\n\nAn airline spokesperson, via the BBC, said: \"Like airlines globally, we're experiencing jet fuel prices that are more than double what they would usually be.\"\n\nAir New Zealand serves the UK through a combination of codeshare partner flights and booking options from Heathrow and Manchester.\n\nIt works with partner airlines, including Singapore Airlines, British Airways, and United Airlines, to connect passengers via major hubs.\n\nDelta Airlines\n\nDelta Airlines also announced this week that it was cutting back the number of seats on its flights due to the rising fuel costs, The Independent reported.\n\nThe Airline, which operates numerous daily nonstop flights from London Heathrow (LHR), London Gatwick (LGW), and Edinburgh (EDI) to various US destinations, has already increased the price of its checked bag fee by US$10 (£7.45).\n\nNow, reduced seat numbers on Delta flights could result in airfare prices rising.\n\nThe 3 airlines that have entered liquidation or administration in 2026 (so far)\n\nSeveral airlines entered liquidation in 2025, according to the UK Civil Aviation Authority , including:\n\nBlue Islands Limited (UK) - November\n\nAir Kilroe Limited t/a Eastern Airways (UK) - November\n\nPlay Airlines (Iceland) - September\n\nThree airlines have entered administration or liquidation in 2026 (so far), resulting in the cancellation of more than 4,000 flights:\n\nMeanwhile, fellow chartered carrier Legend Airlines (Romania) has reportedly shut down.\n\nThe Street reported the airline has \"officially gone dormant\" after retiring two of its A340 planes.\n\nUK travel companies that have closed in 2026 (so far)\n\nFour UK travel companies have also ceased trading in 2026, resulting in the cancellation of flights and holiday packages to destinations around the world.\n\nThe four UK travel companies that have closed down in 2026 (so far) are:\n\nRegen Central Ltd\n\nGold Crest Holidays\n\nAsiara UK Ltd\n\nSimply Florida Travel Ltd\n\nAll four have ceased trading, according to Companies House, and have lost their Air Travel Organiser's Licence (ATOL).\n\nHave you been impacted by the recent flight cancellations or airfare price hikes caused by increased fuel prices? Let us know in the poll above or in the comments below."} +{"url": "http://www.prnewswire.com/news-releases/earth-day-sale-15-off-organic-mattresses-and-bedding-at-my-green-mattress-302736499.html", "title": "Earth Day Sale : 15 % Off Organic Mattresses and Bedding at My Green Mattress", "publish_date": "2026-04-12T14:43:52Z", "full_text": "CHICAGO, April 8, 2026 /PRNewswire/ -- In celebration of Earth Day, My Green Mattress is offering 15% off sitewide from April 10 through April 28. With no exclusions, customers can save on organic mattresses, bedding, mattress toppers, mattress protectors, and more—making it the perfect time to invest in healthier, more sustainable sleep.\n\nNo code is needed; the discount is automatically applied at checkout. Shop the sale.\n\n15% Discount on Organic Mattresses\n\nMy Green Mattress crafts each product using certified GOTS organic cotton and wool, along with GOLS certified organic latex, creating a sleep surface that is breathable, temperature-regulated, and free from harmful chemicals. Their signature 7-zone pocketed coil system provides targeted support, enhanced contouring, and reinforced edge support for a more restorative night's sleep.\n\nFrom adults looking to upgrade their sleep to parents seeking safer options for their children, My Green Mattress offers a full range of organic sleep solutions for the entire family—including crib mattresses, kids mattresses, and luxury options for master bedrooms. See their full range of organic mattress options.\n\nWhy Choose My Green Mattress?\n\nMade in the USA: Every mattress is handcrafted in the USA using high-quality materials and responsible manufacturing practices.\n\nEvery mattress is handcrafted in the USA using high-quality materials and responsible manufacturing practices. Certified organic & non-toxic: Products are GOTS and GOLS certified, MadeSafe® certified, and Greenguard Gold certified—free from harmful chemicals, flame retardants, and VOCs.\n\nProducts are GOTS and GOLS certified, MadeSafe® certified, and Greenguard Gold certified—free from harmful chemicals, flame retardants, and VOCs. Sustainable materials: My Green Mattresses are built with renewable, responsibly sourced materials that are better for both you and the environment.\n\nMy Green Mattresses are built with renewable, responsibly sourced materials that are better for both you and the environment. 365-night risk-free trial: Try it for a full year with confidence. If it's not the right fit, return it for a full refund.\n\nThis Earth Day, small choices can make a big impact. Switching to an organic mattress is one of the simplest ways to reduce your exposure to toxins while supporting more sustainable manufacturing practices. With 15% off sitewide, there's never been a better time to make the change.\n\nSOURCE My Green Mattress"} +{"url": "https://www.etftrends.com/tactical-allocation-content-hub/gold-volatility-amid-geopolitical-crises-history-tells/", "title": "Gold Volatility Amid Geopolitical Crises : What History Tells Us", "publish_date": "2026-04-12T14:43:52Z", "full_text": "Volatility in a Crisis Is Not Unusual\n\nGold’s March performance surprised many investors. Despite a sharp escalation in geopolitical tensions, gold prices pulled back after briefly retesting record highs. That kind of price action may seem counterintuitive, but it is not unusual in periods of crisis.\n\nGold reached an all-time high of $5,595 per ounce on January 29. Prices pulled back below $5,000 in February but were poised to retest those highs in March as the U.S. and Israel attacked Iran. The attack came on a Saturday and early the following Monday gold moved above $5,400. At that point, it looked like gold was on track to fulfill its role as a safe-haven asset.\n\nHowever, $5,418 marked the monthly high on March 2. What followed was a sharp selloff, gold plummeted $1,319 to a monthly low of $4,099 on March 23 before finishing March at $4,668.06, down $611, or 11.6% for the month. It appears the bottom may be forming, though volatility remains elevated.\n\nWhy Does Gold Fall During Global Uncertainty?\n\nWe understand why investors would be disappointed with gold’s performance during a month of global turmoil. Selling pressure overwhelmed safe-haven demand and central bank buying. That said, this type of price action is not unusual when viewed in a historical context.\n\nGold fell sharply at the onset of the financial crisis in 2008 and again during the early stages of the pandemic in 2020. In both cases, the initial reaction was driven by liquidity needs, rising rates and a stronger U.S. dollar. A similar dynamic was observed after Russia invaded Ukraine in 2022. Crude oil rose above $100 per barrel, contributing to higher interest rates and a stronger dollar, and after a short rally, gold declined by roughly 18%.\n\nWhile each of these periods was shaped by different underlying conditions, they illustrate that gold can experience volatility during the early stages of major global disruptions.\n\nOil, Rates and the Dollar Remain Key Drivers\n\nThe current crisis introduces another oil shock and a new level of geopolitical risk. Higher oil prices have raised inflation concerns and contributed to rising interest rates, a more hawkish Federal Reserve outlook and a stronger U.S. dollar. These forces tend to weigh on gold, particularly in the short term, and can be amplified by systematic and algorithm-driven trading.\n\nAt the same time, gold has delivered strong gains since 2024, so some degree of profit taking should not be surprising. Heavy outflows from bullion ETFs suggest that investors are locking in gains or raising liquidity, and gold can often serve as a source of liquidity during periods of broader market stress.\n\nCentral banks have been an important driver of gold demand, although activity likely slowed during the recent turmoil. Some countries may prioritize liquidity in times of stress. Turkey, for example, reportedly sold or swapped gold in March to support its currency. Several Gulf States have also been among the largest buyers in recent years, and their activity may fluctuate in the near term.\n\nOnce conditions stabilize, central bank demand is likely to normalize. In the meantime, the World Gold Council reports continued buying from countries such as Indonesia, Guatemala and Malaysia, including both new and returning participants. The broader trend of reserve diversification, particularly away from the U.S. dollar, remains intact.\n\nWe find it encouraging that the $4,000 level held despite rising rates, a stronger dollar, ETF outflows and uncertainty around central bank activity. Even after the March selloff, gold remains up $349, or 8.0% year to date.\n\nLooking ahead, once the current conflict runs its course, the global backdrop is likely to return to a familiar baseline of uncertainty. The U.S. continues to face elevated deficits and rising debt service costs, while efforts by many countries to reduce reliance on the dollar are ongoing. Higher oil prices also present risks to economic growth. In that context, the longer-term case for gold remains intact."} +{"url": "https://www.eastbaytimes.com/2026/04/12/horoscopes-april-12-2026-claire-danes-the-timing-is-right-to-branch-out/", "title": "Horoscopes April 12 , 2026 : Claire Danes , the timing is right to branch out", "publish_date": "2026-04-12T14:43:52Z", "full_text": "CELEBRITIES BORN ON THIS DAY: Saoirse Ronan, 32; Claire Danes, 47; David Letterman, 79; Ed O’Neill, 80.\n\nHappy Birthday: Pay attention. Emotional manipulation is apparent and may rob you of your money, reputation or goals if you are compliant. Stand up for yourself, your rights and your abilities. Keep an open mind, but don’t neglect to voice your opinion and to make choices that suit your needs. The timing is right to branch out and to take charge. Follow your heart, set your course and leave regret behind you. Your numbers are 1, 17, 23, 27, 35, 43, 48.\n\nARIES (March 21-April 19): You hold the power of choice. Reach out and take what’s yours, and head in a direction that will soothe your soul and make you feel good about the contributions you make and the outcomes you achieve. Don’t pay for others’ mistakes; choose to use intelligence, not cash, to win your battles, and you’ll far exceed your expectations. 4 stars\n\nTAURUS (April 20-May 20): Refrain from sharing personal or financial information. Someone will monopolize your time and take advantage of you if you let them. Look through every lens and listen intensely. Question what’s possible and get what you want in writing before you commit. Choose your battles wisely. Charm is your weapon; use it fairly and with intelligence. 2 stars\n\nGEMINI (May 21-June 20): Be first to stand up for what’s right. Truth is paramount if you want to maintain your position and reputation. Walk away from gossip and those who tempt you to indulge in excessive behavior. Look for solutions that benefit those in need, and you’ll pave your way to a higher position. Leave nothing to chance or unfinished. 5 stars\n\nCANCER (June 21-July 22): Stop before things get out of hand or run amok. Use your intelligence to navigate your way through conversations that can influence how others perceive you. Check out what’s possible, and put more energy into bringing about positive change. Recognition will be yours if you stand up for others. Speak from the heart. 3 stars\n\nLEO (July 23-Aug. 22): You can’t please everyone, but you can offer validity and tell the truth. Let your voice lead the way, and your passion shine through. An opportunity to share your story or to bring light to a situation will soothe your soul. Gather knowledge and experience, and support will be the byproduct of doing the right thing. 3 stars\n\nVIRGO (Aug. 23-Sept. 22): A change will be uplifting. Take time to clear your mind and assess what’s happening around you. Join forces with like-minded people, and someone you connect with will bring out the best in you. Trust your instincts, and your words and actions will help you bring about positive change. Romance is on the rise. 3 stars\n\nLIBRA (Sept. 23-Oct. 22): What’s familiar is in your best interest. Keep life simple and affordable, and surround yourself with those who support your interests. A partnership will encourage strength and the backup you require to get things done on time. Gauge what’s doable and what isn’t. Put your energy into learning, exploring and incorporating what aids you most into your daily routine. 5 stars\n\nSCORPIO (Oct. 23-Nov. 21): Emotions and impulse will clash if you aren’t careful. Choose your words carefully, and let your wisdom and experience lead the way. Opportunity is apparent, and time is on your side. Be gracious, humble and alert, and you’ll bypass any problems or interference that might cramp your style. Choose peace and progress over uncertainty and chaos. 2 stars\n\nSAGITTARIUS (Nov. 22-Dec. 21): A change of heart will point you in a different direction. Look inward, assess and confront your health, wealth and contractual ties. A change will help clear your head and reframe your future. Home is where the heart is, and comfort will help you find your way forward. Stick to what feels right and works best for you. 4 stars\n\nCAPRICORN (Dec. 22-Jan. 19): Keep your plans simple and affordable. Conversations will carry weight but also give rise to temptation, uncertainty and stress. Step back and consider how you can participate without jeopardizing your health, reputation or emotional well-being. A change of scenery or social networking will offer a unique perspective. Make comfort and peace of mind your goal. 3 stars\n\nAQUARIUS (Jan. 20-Feb. 18): Choose peace. Get your financials on track and a plan in place. Refuse to let your emotions and desires take precedence when it comes to spending and saving. Put your energy into positive change, decluttering your space and life, and discovering what it’s like to live a peaceful, mindful life in an emotionally and financially safe place. 3 stars\n\nPISCES (Feb. 19-March 20): Intelligence and smart moves will save the day. Don’t share too much information or give others a reason to question you. A chance meeting with someone at a social event will lift your spirits and offer insight into options you had yet to consider. Collect your thoughts, rearrange your plans and follow the protocol necessary to forge ahead. 3 stars\n\nBirthday Baby: You are dedicated, loyal and personable. You are passionate and visionary.\n\nStar Ratings Key:\n\n1 star: Avoid conflicts; work behind the scenes.\n\nAvoid conflicts; work behind the scenes. 2 stars: You can accomplish, but don’t rely on others.\n\nYou can accomplish, but don’t rely on others. 3 stars: Focus and you’ll reach your goals.\n\nFocus and you’ll reach your goals. 4 stars: Aim high; start new projects.\n\nAim high; start new projects. 5 stars: Nothing can stop you; go for gold.\n\nVisit Eugenialast.com, or join Eugenia on Instagram/Facebook/LinkedIn.\n\nWant a link to your daily horoscope delivered directly to your inbox each weekday morning? Sign up for our free Coffee Break newsletter at mercurynews.com/newsletters or eastbaytimes.com/newsletters."} +{"url": "https://www.iltempo.it/personaggi/2026/04/12/news/luigi-bisignani-rai-poteri-riforma-governance-lobby-logge-giampaolo-rossi-47241443/", "title": "Rai , in onda il risiko dei poteri tra Bruxelles e Palazzo", "publish_date": "2026-04-12T14:43:52Z", "full_text": "Foto: Il Tempo\n\nLuigi Bisignani 12 aprile 2026 a\n\na\n\na\n\nCaro direttore, finché c’è proroga c’è speranza. Questa volta a beneficiarne potrebbe essere il «piccolo mondo antico» della Rai, il nostro personale Stretto di Hormuz. L’incubo di Viale Mazzini ha un nome e un cognome: European Media Freedom Act. Il regolamento europeo — direttamente applicabile in quanto atto erga omnes — è entrato in vigore l’8 agosto 2025. Ciò significa che l’Italia si trova già in una condizione di ritardo, soprattutto sul fronte della riforma della governance Rai. Il Cda in carica nasce infatti dall’impianto della «legge Renzi», che ha rafforzato il peso del governo nelle nomine e nei conti. Per questo sono in corso trattative riservate tra il governo italiano e Bruxelles, con l’obiettivo di guadagnare ancora tempo ed evitare uno scontro, e si ragiona già su un possibile riassetto normativo — con il coinvolgimento dell’Agcom — per riallineare il sistema ai criteri fissati a livello europeo. Se l’adeguamento non arriverà rapidamente potrebbero aprirsi scenari nefasti anche per gli attuali vertici. In caso di inadempienza, la Commissione europea può avviare una procedura di infrazione, con sanzioni economiche, come già accaduto, ad esempio, per l’Ungheria di Viktor Orbán.\n\nNon è solo una questione di governance. C’è anche un altro nodo: il finanziamento, ai sensi dell’articolo 5. Il regolamento europeo impone che le risorse al servizio pubblico siano assegnate con criteri trasparenti e su base pluriennale, riaprendo così anche il dibattito sul canone. Ed è proprio in queste ore di incertezza che, nello Stretto di Hormuz della Rai — tra Saxa Rubra e via Teulada — si incrociano, come sempre, potere, visibilità, carriere, appalti e storie personali che alimentano, complicano e agitano la giungla del potere nei palazzi romani. E non solo: dalle logge più riservate del Vaticano fino alle grandi aziende pubbliche e a Piazza Dante, affollato condominio di DIS, AISE e AISI, dove le variazioni d’umore di Saxa Rubra sembrano talvolta pesare più di scenari ben più incandescenti. Intuendo la tempesta, ai piani alti c’è chi tenta di definire i palinsesti autunnali prima di un possibile scioglimento, così da «blindare» personaggi e programmi di riferimento almeno fino a gennaio 2027. L’amministratore delegato Giampaolo Rossi, in difficoltà anche per la mancata costruzione di una proposta informativa efficace sui referendum — soprattutto se confrontata con quella, martellante, di La7 — prova a muoversi prima che arrivi il ciclone, tanto da avviare anche una corte serrata per riportare in veste del «figliol prodigo» Nicola Porro in prime time su Rai Uno da Mediaset. Si sussurra che stia immaginando anche una sua possibile via di fuga: una Rai 2 «allargata», capace di accorpare cinema, fiction e documentari in un polo da oltre 500 milioni di euro, di fatto una seconda Rai costruita attorno alla sua figura. Un’ipotesi che però troverebbe forti resistenze sia in Cda — dove lo scontro più acceso è sempre quello tra i due leghisti, il deus ex machina Antonio Marano e Alessandro Morelli, sotto lo sguardo divertito di Simona Agnes — sia in Commissione di Vigilanza, presieduta da Barbara Floridia.\n\nNel frattempo, mentre Rossi valuta le sue opzioni, resta salda la direzione del Tg1 di Gian Marco Chiocci, al netto delle voci che lo vorrebbero a Palazzo Chigi alla guida dell’informazione del governo. Le autocandidature che continuano a circolare — da Francesco Verderami del Corriere della Sera, grande fan della premier, a Incoronata Boccia, considerata vicinissima all’Ad, fino a un grande professionista come Nicola Rao — restano, per ora, senza possibilità di approdo all’ammiraglia Rai, a meno che Chiocci, forte di un gradimento trasversale, non approdi in tempi brevi al vertice aziendale, come già avvenuto con Mario Orfeo. In questo clima, anche pesci più piccoli si agitano in cerca di una nuova collocazione. Al centro del risiko c’è Stefano Coletta: il coordinamento dei generi che guida assomiglia sempre più a una sorta di «DIS» interno, una cabina di regia che tutto vede e tutto controlla, capace di orientare scelte e palinsesti trasversalmente. Non a caso, attorno a lui si immagina un ulteriore rafforzamento del presidio sul prime time, anche a costo di uno spostamento di Williams Di Liberatore verso il daytime. Un prime time che, sotto la sua gestione, ha brillato solo a tratti: tra le eccezioni, Affari tuoi, Stasera tutto è possibile con Stefano De Martino e il franchise The Voice di Antonella Clerici, capace di tenere testa a Maria De Filippi.\n\nSmottamenti anche a Rai Cultura, dove si fa strada Angelo Mellone, finora responsabile del daytime e molto attivo anche sul versante del suo night time, impegnato in una frenetica attività di eventi di ogni tipo. Sul fronte dell’offerta, Rai Italia resta guidata da Maria Rita Grieco, ma cresce l’idea che serva un profilo più orientato al prodotto: tra i nomi circola quello di Gianfranco Zinzilli, oggi alla guida di Rai Radio Digital con risultati solidi. Tra gli outsider si muove Andrea Assenza, vice di Mellone e fedelissimo dell’Ad, che punta alla direzione dei contenuti digitali e transmediali, oggi affidata ad interim a Marcello Ciannamea, tra i dirigenti più solidi per risultati e affidabilità, recentemente investito anche della distribuzione. Solo a valle di questi movimenti si avverte l’agitazione più minuta nelle redazioni — e in particolare a RaiNews24 — dove i pesci piccoli inseguono occasioni e visibilità, in un clima reso più teso dal monitoraggio del Cdr. Emblematico è il caso del vicedirettore Luigi Monfredi: in passato molto aiutato da Paolo Petrecca — finito al centro delle polemiche per il disastro nella giornata inaugurale delle Olimpiadi — al quale, secondo i consueti spifferi interni, avrebbe poi voltato le spalle. Oggi tenta di ritagliarsi spazio riallacciando vecchie relazioni nel centrodestra e in ambienti vaticani ormai fuori gioco, nel tentativo di scalzare Antonio Preziosi, direttore del Tg2 penalizzato negli ascolti. Ed è lo stesso Preziosi a far filtrare l’ipotesi di un possibile approdo in Vaticano come prefetto del Dicastero per la Comunicazione, accreditando — secondo i consueti spifferi — una supposta benedizione del segretario di Stato Pietro Parolin, ma all’insaputa di Papa Leone, con l’obiettivo di scalzare la «coppia d’oro» formata da Paolo Ruffini e Andrea Tornielli.\n\nAnche a RaiSport non si placa il malumore: Giulio Delfino e Riccardo Pescante non si danno ancora pace per la nomina, arrivata con anni di ritardo, di Marco Lollobrigida dopo il tracollo della gestione precedente. Lollobrigida, volto storico e riconosciuto, verrà ratificato nel prossimo, infuocato Cda di giovedì. Ma quando si parla di Rai non si può prescindere dai grandi volti. Come Mara Venier, che a ogni fine stagione torna a evocare l’addio a Domenica In, alimentando le manovre attorno alla sua successione e le tensioni tra gli agenti più influenti, da Caschetto a Presta. Last but not least, Sigfrido Ranucci, da sempre spina nel fianco di tutti i governi da «tele-Renzi» a «tele-Meloni»: per lui si profila una norma che potrebbe costringerlo a smaltire subito le ferie arretrate, mettendo di fatto a rischio il suo ruolo in Report. Intanto si prepara anche la grande rentrée di Piero Marrazzo con «Le verità nascoste», dal titolo tutto un programma in arrivo su Rai3. La sensazione è quella di una Rai in continuo movimento, dove tutto cambia perché nulla cambi davvero. O forse sì."} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Full_text/full_text_asset_precious_metals_spot.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Full_text/full_text_asset_precious_metals_spot.jsonl new file mode 100644 index 0000000..0cf2842 --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Full_text/full_text_asset_precious_metals_spot.jsonl @@ -0,0 +1,7 @@ +{"url": "https://www.tgrthaber.com/ekonomi/islam-memisten-altin-ve-konut-icin-pazartesi-uyarisi-artik-zamani-geldi-3294009", "title": "İslam Memiş ten altın ve konut için pazartesi uyarısı ! Artık zamanı geldi", "publish_date": "2026-04-12T14:42:33Z", "full_text": "İSLAM MEMİŞ'TEN ORTA DOĞÜU EKSENİNDE ALTIN YORUMU\n\n\"İki ihtimal vardı. Ya savaşa devam ya tamam. Artık 15 günlük bir ateşkes süreci haberi geldi. Piyasalarda beklenen o tabii ve doğal fiyatlamalar da gerçekleşti.\n\nÖzel Özellikle petrol ve dolar endeksi gerilerken altın, gümüş, euro, Bitcoin, borsalar toparlandı.\n\nAncak haftanın son işlem gününe baktığımız zaman da bu gerilimin halen devam ettiğini, piyasalarda bir rahatlama döneminin olmadığını, biraz daha sakin bir seyirde, yatay bir seyirde kendini beklediğini gözlemliyoruz."} +{"url": "https://www.dostor.org/5503201", "title": "بكام جرام الذهب ؟.. أسعار الذهب اليوم الأحد 12 إبريل 2026", "publish_date": "2026-04-12T14:42:33Z", "full_text": "تستمر أسعار الذهب في مصر في التحرك داخل نطاقات سعرية محدودة، وسط ترقب من المتعاملين لأي تغيرات في الأسواق العالمية أو في سعر صرف الدولار محليًا، ويُعد الذهب من أهم السلع التي تعكس الحالة الاقتصادية بشكل مباشر، حيث يتأثر سعره بعدة عوامل أبرزها سعر الأونصة عالميًا وحركة العملات الأجنبية.\n\nوتشير البيانات الحالية إلى استقرار نسبي في الأعيرة المختلفة مثل 24 و21 و18، مع بقاء الجنيه الذهب عند مستويات مرتفعة. ويظل الذهب الخيار الأول للمواطنين الباحثين عن حفظ القيمة والادخار الآمن في ظل الظروف الاقتصادية المتغيرة.\n\nأسعار الذهب اليوم الأحد 12 إبريل 2026\n\nسعر الذهب عيار 24: شراء 8177 جنيه — بيع 8143 جنيه\n\nسعر الذهب عيار 22: شراء 7496 جنيه — بيع 7464 جنيه\n\nسعر الذهب عيار 21: شراء 7155 جنيه — بيع 7125 جنيه\n\nسعر الذهب عيار 18: شراء 6133 جنيه — بيع 6107 جنيه\n\nسعر الذهب عيار 12: شراء 4088 جنيه — بيع 4072 جنيه\n\nسعر الجنيه الذهب اليوم\n\nالجنيه الذهب: شراء 57240 جنيه — بيع 57000 جنيه\n\nسعر أونصة الذهب اليوم\n\nسعر أونصة الذهب اليوم الأحد: شراء 254333 جنيه — بيع 253276 جنيه\n\nسعر الدولار في البنوك والصاغة اليوم\n\nسعر الدولار اليوم في البنوك: 53.20 جنيه\n\nسعر دولار الصاغة اليوم: 53.54 جنيه\n\nالفرق بين البنك والصاغة: 0.34 جنيه\n\nسعر الفضة: 136.62 جنيه\n\nاقرأ أيضًا\n\nأسعار الذهب اليوم الخميس في السوق المحلي والعالمي (تحديث فوري)\n\nسعر الذهب الآن في السوق المصري؟ تعرف على آخر التفاصيل\n\nسعر الذهب الآن.. سعر الذهب في السوق المصري اليوم\n\nسعر الجنيه الذهب اليوم 11 أبريل 2026.. سعر جرام عيار 21"} +{"url": "https://www.latercera.com/pulso/noticia/quienes-son-los-toesca-los-protagonistas-del-momento-en-sanhattan/", "title": "Quiénes son los Toesca : Los protagonistas del momento en Sanhattan", "publish_date": "2026-04-12T14:42:33Z", "full_text": "Si algo llama la atención de quienes visitan Toesca es que buscan las oficinas de los dueños y no las encuentran. Porque no tienen. Su espacio de trabajo, en plantas libres, es el mismo que el de sus colaboradores.\n\n“La comunicación, la cercanía, el ambiente que se da...Los jóvenes lo aprecian mucho”, cuenta un socio.\n\nFue una de las “buenas prácticas” que se trajeron los fundadores de esta administradora general de fondos (AGF) especializada en activos alternativos, de cuando trabajaban en BTG Pactual, antes Celfin, su cuna financiera.\n\nPor estos días Toesca S.A. Administradora de Fondos de Inversión parece vivir sus minutos de fama. Una saga de adquisiciones, incluyendo el ingreso como socio de un histórico del mundo de la inversión institucional, la han fijado en la retina de muchos que sabían de su existencia, pero que no habían calibrado lo relevantes que se han hecho con menos de una década de existencia.\n\nEste año partió de hecho con su primera gran operación. El mismo 1 de enero anunció la compra de la AGF Frontal Trust y sólo 20 días después, los socios de Toesca se unieron al fondo norteamericano TC Latin America Partners para comprar el 90% del factoring Primus Capital.\n\nEntre ambas operaciones, el 20 de enero, sumaron a un histórico hombre de las AFP, Alejandro Bezanilla, ex gerente general de AFP Habitat, como socio.\n\nY en marzo volvieron a la carga para negociar una posible fusión con otra AGF similar en tamaño, Ameris Capital, la que en todo caso todavía no se cierra. “Podría avanzar o caerse”, dice una fuente conocedora de la negociación.\n\nAunque en su historia Toesca ha levantado un total de US$2.500 millones en inversiones, actualmente gestiona en torno a los US$1.500 millones en 25 fondos. Trabajan con 55 personas y Frontal aportará una treintena adicional. Sus ingresos son de unos US$12 millones al año.\n\nAlejandro Reyes ITALO ARRIAZA +56983956683 PHOTO.CL\n\nUn antiguo origen\n\nLa Toesca de hoy nació oficialmente el 4 de noviembre de 2016, con dos socios: Alejandro Reyes y Carlos Saieh.\n\nReyes, ingeniero civil industrial de la Universidad de Concepción, estuvo 15 años en Celfin. Allí creó el área de administración de activos, con énfasis en gestión de patrimonio. Llegó a ser socio hasta que BTG Pactual adquirió el banco de inversión local en 2012, pero se quedó en su puesto hasta abril de 2016, cuando renunció.\n\nSu dimisión, así como la de sus colegas que terminaron siendo sus socios, se produjo sólo meses después de la crisis que sufriera BTG con la detención de su presidente ejecutivo, André Esteve, en Brasil, por acusaciones de corrupción vinculadas al caso Lava Jato. Esto provocó una fuga de inversionistas y una consecuente salida de ejecutivos.\n\nSaieh, ingeniero civil industrial de la U. Católica (UC) con un MBA en Wharton School de la Universidad de Pensilvania, venía de estar a cargo del área de activos alternativos en Celfin Capital, primero, y luego en BTG, donde se quedó hasta agosto de 2016. Su carrera la había iniciado en 2003 como analista de inversiones y luego subgerente de inversiones en Consorcio.\n\nCarlos Saieh, Toesca ITALO ARRIAZA +56983956683 PHOTO.CL\n\nPero la marca Toesca existía desde antes. Es más, su origen se remonta a 1990, cuando fue creada por la aseguradora estadounidense Aetna como su administradora de fondos de inversión (AFI). En 2001, después que el gigante neerlandés ING adquiriera Aetna en el mundo, pasó a denominarse ING AFI.\n\nRecién en mayo de 2003, tomó su actual nombre. Fue el que le puso Moneda Asset Management -hoy Moneda Patria Investments- cuando la adquirió. Pero al cabo de 13 años, sus resultados como AGF de activos alternativos no fueron los mejores, así que la puso en venta.\n\nEn paralelo, Reyes y Saieh, recién dimitidos de BTG, decidieron en octubre de 2016 armar un AGF juntos: arrendaron una pequeña oficina en El Golf 50 y contrataron a un gerente de operaciones, un administrador y un encargado de software. Pero hacerlo desde cero tardaría de 6 meses a un año, por lo que aprovecharon la opción de Moneda y le compraron Toesca con la idea de cambiarle el nombre. Nunca lo hicieron. Lo que sí hicieron fue inyectarle dinero fresco.\n\nSegún documentación pública, pasó de contar con un capital de $524 millones en diciembre de 2016 a $13.700 millones en febrero de 2017. “Pusimos toda la plata que teníamos”, contó Saieh en el podcast Millions: El Arte de Invertir.\n\nRodrigo Rojas ITALO ARRIAZA +56983956683 PHOTO.CL\n\nAunque a fines de 2016 habían conseguido refuerzos. Se les habían unido Rodrigo Rojas y Arturo Irarrázaval, quienes lideraban el negocio de acciones en BTG, con todo su equipo. Irarrázaval, ingeniero comercial de la U. Católica y master en finanzas de la escuela de negocios ESE de la U. de Los Andes, había trabajado como analista de inversiones de dos AFP y como gestor de inversiones en renta variable en BTG. Rojas, a su vez, ingeniero civil y MBA en la UC, fue analista y director de inversiones en acciones de FIT Research entre 2001 y 2003, mismo cargo que asumió en Celfin Capital -luego BTG- para después ser gerente de portafolio de acciones hasta 2016.\n\nEste equipo fue el que creó el primer fondo de la firma, que no fue de activos alternativos, como era la idea: fue el Fondo Mutuo de Acciones Chile Equities, que partió el 30 de diciembre del 2016. Y como la plantilla se duplicó en seis meses, tuvieron que ubicar alguna oficina más adecuada: encontraron una planta libre en el actual edificio del BICE en Apoquindo. Eran sólo 10 personas más algunas mesas en 400 metros cuadrados.\n\nArturo Irarrázaval ITALO ARRIAZA +56983956683 PHOTO.CL\n\nEse mismo mes migró otro más desde BTG: Augusto Rodríguez, ingeniero comercial de la U. de Los Andes, quien manejaba la división inmobiliaria, también heredada de su desempeño en Celfin, aunque su carrera la había iniciado como analista de riesgo en ABN Amro en 2003.\n\nLuego de un verano incierto, en marzo de 2017 arribó Max Vial, quien presidía la corredora de bolsa de BTG y había sido director de gestión de patrimonio. Vial, ingeniero comercial con estudios de posgrado en finanzas y marketing, había llegado en 1997 a Celfin, cuando esta firma compró la corredora de bolsa Gardeweg, de la cual era socio.\n\nEse mismo marzo levantaron el primer fondo de activos alternativos en infraestructura: compraron el 49% de la Ruta del Algarrobo, la autopista que une La Serena y Vallenar y que controlaba con un 51% la española Sacyr. Los inversionistas que suscribieron el fondo eran fundamentalmente compañías de seguros.\n\nAugusto Rodríguez ITALO ARRIAZA +56983956683 PHOTO.CL\n\nY durante el primer semestre de ese año, lanzaron también su primer fondo de rentas inmobiliarias, con el que compraron un strip center en Machalí, y el primero en crédito privado, para invertir en el negocio del factoring de segundo piso, factorizando a otros factoring. Los fondos de la carretera y del strip center los vendieron el año pasado y el de factoring, lo liquidaron poco después.\n\nPero en menos de nueve meses ya habían lanzado fondos en sus cuatro estrategias principales: infraestructura, inmobiliario y crédito privado en activos alternativos, y acciones. En 2017 habían experimentado un crecimiento explosivo.\n\nMax Vial ITALO ARRIAZA +56983956683 PHOTO.CL\n\nEn ese contexto convencieron a Alejandro Montero, su exjefe en BTG, que vivía su tercer año sabático en París con su familia, a que se integrara. Montero, ingeniero comercial de la UC con un MBA en Wharton, había iniciado su carrera como analista en 1993 en Celfin y llegó a ser gerente general en Celfin y la primera etapa de BTG.\n\nLos años siguientes fueron de acelerada expansión. Ya a inicios de 2019 habían levantado el primer billion de activos administrados: US$1.000 millones.\n\nDespués de eso, vino una meseta, que coincidió con el estallido social, la salida de capitales del país y la pandemia.\n\nEse freno en la expansión se relaciona, según quienes conocen a Toesca, con varios factores que se confabularon. En sus primeros años recibieron un gran volumen de dinero fresco y que fue su principal motor de crecimiento, con una alta rentabilidad. Pero luego sobrevino la incertidumbre local, afectada por la salida de capitales de personas naturales, sumada a una reducción de la caja de las compañías de seguros, dado un descenso en su venta de rentas vitalicias, y un cambio regulatorio en la inversión de las AFP en 2020, que “secó” los fondos a activos alternativos nacionales, favoreciendo a los extranjeros. “Nunca más fluyó plata de las AFP a estos activos en Chile”, reclama un conocedor.\n\nAlejandro Montero ITALO ARRIAZA +56983956683 PHOTO.CL\n\nEn estos años más débiles, abrieron una nueva estrategia relacionada con campos agrícolas. Levantaron un fondo llamado Permanent Crops, con la idea de comprar campos para producir fruta. Y en plena pandemia entró el único de los socios que no venía del “universo BTG”: Manuel Ossa. Ingeniero comercial de la UC con un MBA en la escuela Booth de la U, de Chicago, había sido asesor del Ministerio de Vivienda en la primera administración Piñera, para luego trabajar como analista y gerente de portafolio en Inversiones Arizona, el family office de la familia Luksic.\n\nManuel Ossa ITALO ARRIAZA +56983956683 PHOTO.CL\n\nEl repunte y la visión\n\nEl negocio empezó a levantar cabeza en 2023, repuntó firmemente en 2024 y el 2025 fue incluso mejor que el anterior.\n\nEste mejor momento coincidió con una reducción en las tasas de interés, que se habían disparado para contener a la galopante inflación, pues cuando las tasas están altas, los inversores prefieren la seguridad de la renta fija en vez de apostar por activos de riesgo.\n\nCon el impulso de esta nueva primavera de la inversión, Toesca se decidió a crecer tanto orgánica como inorgánicamente. En su área de farmland, por ejemplo, se asociaron en 2024 con la gestora inglesa Astarte para ampliar su cartera de campos: hoy tienen uno de 300 hectáreas en Rapel para paltos y cítricos, otro del mismo tamaño en Molina para cerezas y carozos, y otro en Ñuble para avellanos.\n\nY en enero pasado se robaron la agenda del mercado con las adquisiciones de Frontal Trust y Primus. La primera, que gestiona del orden de los US$600 millones y dado que cuenta con estrategias similares de negocios, debiera integrarse fácilmente. La segunda, seguirá trabajando como un factoring normal, aparte del AGF.\n\nAlejandro Bezanilla ITALO_ARRIAZA WWW.PHOTO.CL\n\nEn el noticioso enero, Alejandro Bezanilla, ingeniero civil de la UC y exgerente de inversiones y gerente general de AFP Habitat, donde trabajó casi 20 años, se integró como socio y director ejecutivo. Su misión: darle un marco más institucional a la firma, que le permita trascender en el tiempo, y al mismo tiempo aprovechar su buen nombre en el mundo institucional para que apoye al equipo comercial en la captación de inversores.\n\nTodo con el objetivo de ir acercándose a una meta que comparten los socios y que ya no es sólo administrar dinero de chilenos en activos chilenos, sino ir a buscar plata al mundo para que invierta en activos regionales."} +{"url": "https://www.sun-sentinel.com/2026/04/12/ask-ira-time-for-nba-to-cook-the-books-in-heat-favor-after-hornets-rozier-fiasco/", "title": "Should the NBA do next do right by the Miami Heat ? ", "publish_date": "2026-04-12T14:42:33Z", "full_text": "Q: Ira, please tell me the Heat are not satisfied with a second-round pick for the Terry Rozier drama and that there is still some recourse. The NBA failed to provide the Heat with any information on the gambling investigation, and apparently their own internal NBA investigation was suspect, at best, and turned the other cheek, at worst, ignoring the facts. I’m hoping the Heat bring a formal lawsuit against the NBA which would be bolstered should Rozier be found guilty at trial or he pleads out. There is no excuse for what has transpired and the Heat deserve to have their first-round pick restored and the money paid to Rozier back, as well. This could be, for the Heat at least, two high first-round picks and could change the trajectory of the franchise without gutting the team for a whale, and set them up for years with a payroll that could add talent as needed. – Brian, Fort Lauderdale.\n\nA: Except NBA teams don’t sue the league (unless it is a certain owner in a very large market that has aired such grievances publicly, but that’s another story). In accepting the compromise of a second-round pick this June from the Hornets in the Terry Rozier matter, the Heat effectively signed off on the matter being closed. Now, if you are of the conspiracy ilk, perhaps Adam Silver can turn in some lottery chicanery (if the Heat are in the lottery) and get the Heat the type of lottery remuneration that the Mavericks wound up with in Cooper Flagg after trading Luka Doncic. At worst, how about sending Ray Acosta, Derrick Collins and Eric Dalen as the officiating crew for the Heat-Hornets play-in game? The Heat this season went a combined 14-3 with those three officiating their games this season.\n\nQ: Ira, why win on Sunday when it would only hurt the lottery odds, since the Hornets are winning in New York with the Knicks with nothing to play for? – Sammie.\n\nA: Which is why the NBA scheduled all of those East games for 6 p.m., so teams can’t play the scoreboard as freely. But, yes, the Hornets certainly have a better draw on Sunday than the Heat, with Atlanta with plenty to play for in their visit to Kaseya Center. The reality well could be that the Heat try to win, and like so many recent games, aren’t good enough. But remember, even with a loss and a 42-40 final record, making the playoffs would mean no lottery. So Sunday isn’t as important to those with lottery visions as what follows the rest of the week.\n\nQ: Will Erik Spoelstra pull another rabbit out of the hat? – Hal.\n\nA: Well, has there ever been a better play-in puppeteer?"} +{"url": "https://tech.ifeng.com/c/8sGYfvCKmod", "title": "DeepSeek , 该卸下扫地僧的枷锁了", "publish_date": "2026-04-12T14:42:33Z", "full_text": "我每次翻《天龙八部》,翻到少林寺藏经阁那一段,都要停下来。\n\n萧远山、萧峰父子对上慕容博、慕容复父子,鸠摩智再从旁搅局,三十年的血海深恨搅在一处,眼看就要分出生死。就在这当口,一个枯瘦的扫地僧走了出来。\n\n萧峰的降龙十八掌打在他身上,他虽受内伤吐血,却以浑厚内力生生受之;他举手投足间让慕容博陷入「假死」复又救活,这种生死由心的境界,令在场一众顶尖高手莫不震慑失语。\n\n这一刻,谁强谁弱,答案不言而喻。\n\nAI 圈最近几年,流行把 DeepSeek(深度求索)比作这位老僧。在所有人眼里,AI 赛道的格局早已注定,海外有御三家,国内有大厂和彼时风头正盛的 AI 六小虎,轮不到旁人来置喙。\n\n结果一家做量化交易出身的中国公司,悄没声儿地走出来,用一套从天而降的招法,在各项核心评测上与这帮人正面交手,打得有来有回。\n\n只是,扫地僧出场,是《天龙八部》行将收尾的时刻。他的使命是终结纷争、化解戾气,然后全书走向尾声。可大模型的故事,没有尾声,也没有终章,只有下一回,还有下下一回。\n\n把 DeepSeek 比作扫地僧,是对它过去的最高赞誉,但如果这三个字正在慢慢变成困住它的枷锁,我倒觉得,赞誉和催命符,有时候只在一念之间。\n\n扫地僧是怎么练成的\n\n金庸写扫地僧,从来不正面写他的功夫。他写的是别人的反应,萧峰愣了,慕容复愣了,旁观的人也愣了。高手的境界,要从旁人失语的瞬间才能传递出来。\n\nDeepSeek 的故事,也暗合这个逻辑。\n\n作为杭州的一家对冲基金,外人提到幻方量化,第一反应是期货、是算法交易、是数学天才们盯着屏幕上跳动的数字。这和 AI 大模型,八竿子打不着,却悄悄把一批工程师和研究员聚在一起做大模型。\n\n2023 年 11 月,他们发布首个开源代码大模型 DeepSeek Coder,后续拿出了一个 67B 的语言模型。在官方给出的多项评测中,67B 超过了 LLaMA2 70B,67B Chat 在部分中文和开放式评测中优于 GPT 3.5。只是,圈内少数几个消息灵通的人注意到了,大多数人没注意到。扫地僧还在扫地,少林寺的人都在忙着练少林长拳。\n\n让其开始崭露头角,是 2024 年 5 月 7 日发布的 V2。V2 用的是 MoE(混合专家)架构,总参数 2360 亿,但每次推理实际激活的只有 210 亿。与此同时,V2 首次采用了 MLA(多头潜在注意力)机制,大幅压缩了推理时的显存占用。\n\n两相叠加,让模型在同等效果下,跑得更快,花得更少。用金庸的话来说,这叫以柔克刚,以精妙的内功路数,弥补了真气总量上的不足。\n\n但砸出最大水花的,是定价。V2 的 API 定价,每百万 token 输入 1 元,输出 2 元。GPT-4 Turbo 当时是它的七十倍,Meta 的 Llama3 70B 是它的七倍。一块钱,一百万个 token,大约相当于一本《三国演义》的字数。\n\n这个价格摆出来,让整个国内大模型市场为之色变。当月,字节、阿里、百度、腾讯、讯飞、智谱,一家接一家跳出来宣布降价,最高降幅 97%,部分轻量级模型直接免费开放。\n\n一场持续了大半年的价格战,就这么被 DeepSeek 的一句定价点燃了。那时候,业内给 DeepSeek 送了个外号,价格屠夫。\n\n美国的半导体咨询公司 SemiAnalysis 在那段时间写了一篇分析,说这家公司有可能成为 OpenAI 的对手,也有可能碾压其他开源大模型。当时读到这句话的人,大概有一半觉得是危言耸听。一年多以后回头看,没有人再觉得是危言耸听了。\n\n2024 年末的 V3 和 2025 年初的 R1,则是连续出手的两招,把对手打得目瞪口呆。DeepSeek 用极低的投入,打出了旗鼓相当的效果。\n\n更让人震惊的是参与人数,139 名工程师和研究人员完成了这个项目,而 OpenAI 同期有 1200 名研究人员,Anthropic 有 500 名。Meta 超级智能实验室负责人亚历山大·王后来说了一句被广泛流传的话,当美国人休息时,他们在工作,而且以更便宜、更快、更强的产品追上我们。\n\n紧接着便是是 R1,主打深度推理,数学、代码、逻辑,在相当多的测试维度上与 OpenAI o1 不落下风,训练方法用的是 GRPO 强化学习,靠让模型自己想清楚来提升推理能力。\n\n最要紧的一步是开源。\n\nR1 的开源,被广泛解读为一种慷慨。模型权重、技术论文、训练细节全部公开,全球开发者共享成果。这套叙事里,DeepSeek 是那个敞开藏经阁大门的人,路不拾遗,人人可进。\n\n武功秘籍直接摆桌上,谁想学谁来拿的这一手,也打破了少数几家巨头对前沿模型的垄断,让全球数以万计的中小开发者有了和顶尖模型掰手腕的资格。\n\n金庸写扫地僧,主要抓住几样东西,出身边缘、多年隐匿、一鸣惊人、技法精绝、胸怀坦荡。DeepSeek V2 的价格屠刀、V3 的成本奇迹、R1 的开源普惠,也让人们在 DeepSeek 身上,真真切切地看见了那个老僧的影子。\n\n枷锁,以及枷锁之后\n\n但武侠小说是会结束的,AI 赛道不会。\n\n每次我写 DeepSeek 的文章,底下的评论区都像藏经阁又打了一场架。有人说它安安静静做产品,不收费、不立人设,能用就用,这才是正道。有人说它连国产其他巨头都未必打得过,已经无法搅局。\n\n有人替它抱不平,有人觉得它早就该被淘汰。更有人说,「我们一直以来都没把 DeepSeek 当作优等生,而是当作扫地僧,真心希望它能如我们所愿」,这句话说得又期待,又带着一丝说不清楚的悲凉。\n\n意见如此撕裂,本身就说明了一件事。DeepSeek 所受到的关注,早已超出了一家普通 AI 公司应有的体量。捧它的人把它捧上神坛,骂它的人把它踩进泥里,没有几家公司能在舆论场里同时承受这两种极端。\n\n这篇文章大概也逃不过同样的命运,有人会说这是黑稿,有人会说这是 PR 稿,落个两头不讨好。但这无所谓,舆论从来都是这样,藏经阁里打架,不管谁赢,总有人不服。\n\n说回正题,扫地僧出场那一幕,是《天龙八部》收尾的信号。他出手,纷争平息,故事逐渐走向终章。这个叙事结构,似乎天然就带着一种大结局的气息,英雄横空出世,一招定乾坤,从此江湖太平。\n\n根据《创智记》援引知情人士消息称,按照创始人梁文锋在内部透露的时间,DeepSeek V4 将于四月下旬正式发布。\n\n爽文里的主角,每一章都要有突破,读者翻到下一页,期待的永远是更大的惊喜。\n\nV3 和 R1 用四两拨千斤的逻辑征服了世界,大众于是开始把它当成 DeepSeek 的固定输出,每一次出手都必须让硅谷巨头血溅千里,都必须让英伟达的股价抖一抖。V4 也应当如此。\n\n可在这等待一年多的时间里,外界等得有些躁动,各路声音都出来了,说一拖再拖,是不是黔驴技穷了,扫地僧要不行了?说这话的人认为 DeepSeek 理应每次出手都是奇迹,一旦慢了半拍,便是江郎才尽。\n\n慢,自然有慢的原因。\n\n3 月 29 日,DeepSeek 的服务器崩了将近十三个小时,创下网页端和 App 平台上线以来最长中断纪录。连续的服务事故暴露了 DeepSeek 在运维监控、应急预案和灾备机制上的明显短板,也给整个 AI 行业敲响警钟。\n\n当然,综合各家报道来看,V4 一再推迟的原因,还藏在芯片层面。\n\nV3 和 R1 的成功,一定程度上建立在成熟的英伟达 CUDA 生态上,DeepSeek 的工程师们在工具完备、文档详尽、社区活跃的环境里,把算法效率一点一点榨到了极限,每一步都踩得踏实。\n\nV4 要做的事,是把这套功夫移植到国产 AI 芯片上。工具链还在快速迭代,底层接口和 CUDA 差异巨大,分布式训练框架几乎需要从头重构。\n\nDeepSeek 交出的答卷,如果是在受限条件下做出来的,这让它的每一分成绩,都带着额外的含金量。哪怕梁文锋愿意为这件事多拖几个月,也是一笔非常划算的决策。\n\n至于 V4 本身,《创智记》报道称,技术重心据悉落在了 LTM(长期记忆)能力的突破上,同时将原生多模态从底层融入架构,文字和视觉在预训练阶段就融合在一起。\n\n另一个值得关注的变化,是梁文锋本人的注意力在悄悄转移。尽管在过去的一年里,包括 R1 的核心作者郭达雅在内的部分 DeepSeek 核心骨干陆续离职,不过根据《晚点 LatePost》的观察,DeepSeek 的人才基本盘依然稳固,并未出现大规模的人才流失现象。\n\n进入 2025 年下半年,梁文锋也愈发看重技术的商业落地与产品化进程,积极招募负责 Agent 领域的策略产品经理。与此同时,他正在为公司启动估值,给员工的期权一个明确的锚点,让团队对未来有更清晰的预期。\n\n综合上述种种动向不难得出一个结论:曾经心无旁骛盯着 AGI 的 DeepSeek 也得开始面对一家成熟科技公司必须面对的那些现实:商业闭环、生态建设、可持续的收入来源。\n\n扫地僧可以几十年不问江湖俗事,守着藏经阁一扫到底,一家公司,没有这个选项。\n\n《笑傲江湖》里的令狐冲凭着独孤九剑可以破尽天下武功,但当他真正坐镇恒山派,每天迎来送往,护佑门人,一招鲜远远不够,他需要的是内政、是人心、是香火代代相传的根基。奇招,解决不了日常的柴米油盐。\n\n因此,我们应该主动帮 DeepSeek 卸下「扫地僧」这个名号。这三个字是对过去的最高褒奖,却是对未来的过重负担。即便 V4 发布时没有断崖式的领先,只是一款 LTM 扎实、多模态原生融合、各项指标均衡的水桶机。\n\n从产业的角度看,这依然是巨大的成功,成功在于它或许将证明 DeepSeek 有能力从一个创造奇迹的挑战者,变成一个稳定交付的基础设施提供者。\n\n有意思的是,这件事或许本来就是双向的。《晚点 LatePost》此前的报道里,DeepSeek 对外的沟通姿态明显比以往克制,既没有大张旗鼓地预热,也没有放出足以吊足胃口的技术信号。\n\n这种低调,很难说是无意为之。\n\n他们比任何人都清楚,扫地僧这三个字背后悬着什么。每一次出手若不能再掀翻整张牌桌,舆论的落差就会被无限放大。这是一种预期管理,也是一种自我解绑——他们同样不想再背着这个包袱走下去。\n\n▲AI 模型的世界,已经从少数几家机构的专属游戏,变成了全球开发者共同参与的基础设施建设,而且这个趋势还在加速。\n\n而话说回来,当舆论都在一窝蜂盯着 DeepSeek,却少有人往旁边多看一眼。\n\n这片江湖里,国内每一家 AI 都在苦修内功,押注多模态、Agent 生态、算力布局,也都在各自的赛道上走出了自己的路数。\n\nDeepSeek 固然是那个最让人心跳加速的名字,但把眼光只锁死在它一家身上,未免看窄了这个时代。真正让天龙八部成为天龙八部的,是那一整代人各有来路,各有绝学,彼此激荡,才撑起了那个波澜壮阔的时代。\n\n扫地僧的传说,止于藏经阁那一战,藏经阁外,才是真的江湖。"} +{"url": "https://www.express.co.uk/celebrity-news/2192212/liverpool-boy-band-who-made-history", "title": "Liverpool band made history - but theyre not the Beatles | Celebrity News | Showbiz & TV", "publish_date": "2026-04-12T14:42:33Z", "full_text": "Two members of the Liverpool band who made history in 1976\n\nFifty years ago this month a song was recorded which would become the soundtrack to the UK’s long, hot summer of 1976. The track in question felt like it had been beamed into Britain from another world. Or, at the very least, from Philadelphia, the unofficial global capital of soul music during the 1970s.\n\nIt was joyous, it was uplifting, it was romantic, and it sold in lorry-loads, climbing to the top of the singles charts in the days when a record had to sell hundreds of thousands of copies to reach number one. Even now, You To Me Are Everything by The Real Thing remains a guaranteed dance floor filler splicing good time vibes with that unmistakable “Philly Sound”. Article continues below ADVERTISEMENT\n\nExcept You To Me Are Everything didn’t actually come from Philadelphia, or Los Angeles, or Detroit, or any of the other hotbeds of the US music industry. That’s because The Real Thing, like The Beatles before then, hailed from an English city built largely on its trade links with America, namely Liverpool.\n\nWhen You To Me Are Everything went to number one, The Real Thing became the first British all-black group to top the UK singles chart. That’s not a bad claim to fame for four lads who sounded every bit as Scouse as John, Paul, George and Ringo, if not more so\n\nDave Smith and Chris Amoo of The Real Thing perform on stage during the Cambridge Club Festival in 2023\n\n“We’ve got a song called Hometown that goes, ‘Liverpool is who I am, where I grew into a man’,” says Chris Amoo, now in his sixth decade as lead singer of The Real Thing. “Nowadays, when we’re playing to a packed audience, I make it my business to say ‘There’s no Americans in this band!’ And everyone will laugh because right the way through our career people have automatically thought we’re American. In actual fact we’re from that part of Liverpool called Toxteth. And I’m proud of that.” Article continues below ADVERTISEMENT\n\nOriginally formed by Chris and his childhood friend Dave Smith, The Real Thing – or Vocal Perfection as they were initially known – came together at a time when the UK music industry, according to Chris, “didn’t really know what to do with or how to market black British artists”. Article continues below ADVERTISEMENT\n\nDespite appearing on the TV show Opportunity Knocks, the 1970s equivalent of The X Factor, the group – which also featured Chris’ older brother Eddie and Ray Lake on backing vocals – struggled to break through until Tony Hall, the renowned compere, DJ, record promoter and producer, took them in hand as their manager.\n\nInspired by an advertisement he’d seen in London’s Piccadilly Circus branding Coca-Cola as “the real thing”, Hall changed their name, got them work supporting Seventies heartthrob David Essex, and introduced the group to up-and-coming songwriters Ken Gold and Micky Denne.\n\nOne of the earliest songs Gold and Denne had written was You To Me Are Everything, which Gold thought would be perfect for The Real Thing. The song needed a home and the band needed a breakthrough hit. The rest, as they say, is history.\n\n“When I first heard it, I thought it was great,” says Chris. “It actually reminded me of the Johnny Bristol song Hang On In There Baby which I’ve always loved.\n\n“But here’s the thing – when we recorded it, I didn’t like it. I thought that the demo was better. Ken said to Tony, ‘I’ve heard Chris singing better than this – let’s go in and do it again.’ I was all ‘Cor, who do they think they are?’ but I went along with it.\n\n“The next day we started again with a clear tape, doing it exactly the way Ken and Micky saw it because they were the ones who wrote the song. They didn’t want me changing lines just because I thought it felt good. They wanted it sung the way they’d written it. And when I heard it back I thought ‘Umm, I see what they mean’. I still prefer my first version, but they showed us how to put a record down properly.”\n\nThe original line-up of The Real Thing pictured in 1976\n\nA few days later Chris took an acetate copy of the disc (often referred to in music industry circles as the white label) to The Timepiece nightclub in Liverpool, a local Mecca for lovers of black music. It was midweek and the dancefloor was empty – until, that is, the resident DJ Les Spaine put You To Me Are Everything on the turntable. Nobody had heard it before, yet within seconds the dancefloor was packed.\n\nIn May 1976 the single was released, going into the UK top 40. The following week it was at number 22. The week after that it had climbed to number five. Seven days later it reached number one, staying there for three weeks. At one point You To Me Are Everything was selling 25,000 copies a day at a time when the UK was experiencing a period of unusually hot weather. Even now, the summer of 1976 remains a benchmark for heatwaves in the UK.\n\n“When it comes to a hit record, everything surrounding that record becomes important,” says Chris. “People go and buy records when they want to feel good about something, and people were feeling bloody good about things that summer. That song suited the whole atmosphere of the Seventies, and 1976 in particular. People had their windows and front doors open for weeks on end, it was that hot, and the sound you heard coming through those windows and doors was You To Me Are Everything.”\n\nThe Real Thing supported Seventies heartthrob David Essex on tour as one of their first major gigs\n\nIn the months and years that followed The Real Thing continued to release hit singles, including Can’t Get By Without You and Can You Feel The Force, while their 1977 album 4 From 8 remains arguably the grittiest soul album ever released by a British group, inspired as it was by their formative years spent in the Liverpool 8 post code. And yet You To Me Are Everything remains the band’s calling card, overshadowing to an extent the rest of the band’s catalogue.\n\nNot that Chris Amoo has any regrets about that. As far as he’s concerned the song was more of a blessing than a curse, helping inadvertently to shape the band’s subsequent career.\n\n“We never felt that it was an albatross around our necks, but we knew it was something we would have to be very careful with, otherwise that was going to be the only song we’d record,” he says. “It helped us go in other directions, for better or for worse, but that’s something you have to do otherwise you’ll never find that creative fulfilment.\n\n“Believe you me though, I never dreamt I’d be sat here 50 years later talking about You To Me Are Everything. Even when it was number one, I thought ‘OK, it’s number one. This is great, just great’. Then it goes out of the charts, and other number ones come along, and future generations arrive with their own number ones which take precedence.\n\n“A standard though is a number one that goes through every generation. Off the top of my head, I can’t think of another number one from that time like You To Me Are Everything. As soon as you hear it, you just know. Not many people, no matter what genre of music you’re in, get the chance to record something like that.”\n\nAlthough Ray Lake and Eddie Amoo died in 2000 and 2018 respectively, The Real Thing continue to record and tour with Chris Amoo and Dave Smith at the helm. And if you should go to see them at some point in 2026, rest assured, they most definitely will perform You To Me Are Everything.\n\nCelebrity news and gossip plus selected offers and competitions Subscribe Invalid email We use your sign-up to provide content in ways you've consented to and to improve our understanding of you. This may include adverts from us and 3rd parties based on our understanding. You can unsubscribe at any time. Read our Privacy Policy\n\n“When we go on now, and we sing it, the reaction is out of this world,” says Chris. “Wherever we go – on tour, or recording, or in TV studios – people look at you with respect. And they smile. That song makes them smile. What more can you possibly ask for than that?”"} +{"url": "https://www.boerse-express.com/news/articles/wisdomtree-silver-3x-etc-bestaende-brechen-ein-891172", "title": "WisdomTree Silver 3x ETC : Bestände brechen ein ! ", "publish_date": "2026-04-12T14:42:33Z", "full_text": "Der Silbermarkt steuert auf ein sechstes Angebotsdefizit zu, während physische Lagerbestände schrumpfen. Dieses fundamentale Ungleichgewicht stützt den Preis und befeuert gehebelte Anlageinstrumente.\n\nDer Silbermarkt steuert im Jahr 2026 auf das sechste Angebotsdefizit in Folge zu. Während die industrielle Nachfrage aus der Solar- und Elektronikbranche ungebremst wächst, leeren sich die physischen Lagerbestände zusehends. Diese fundamentale Knappheit trifft nun auf einen schwächelnden US-Dollar und befeuert gehebelte Anlageprodukte.\n\nIn der vergangenen Handelswoche verzeichnete das Edelmetall einen spürbaren Aufwind. Haupttreiber für das wöchentliche Plus von rund 4,6 Prozent beim Spot-Preis war ein deutlicher Rücksetzer der US-Währung. Der Dollar erlitt den stärksten wöchentlichen Einbruch seit Januar. Diese Währungsschwäche glich den Druck der hartnäckigen US-Inflation von 3,3 Prozent mühelos aus. Gleichzeitig stützen die anhaltenden diplomatischen Verhandlungen in Islamabad und ein fragiler regionaler Waffenstillstand den Status von Silber als sicheren Hafen.\n\nLeere Lager und hohe Nachfrage\n\nDie fundamentalen Daten des Silver Institute untermauern die aktuelle Aufwärtsbewegung. Für das laufende Jahr wird ein physisches Marktdefizit von 67 Millionen Unzen prognostiziert. Das Angebot wächst voraussichtlich nur marginal um 1,5 Prozent, während die physische Investmentnachfrage um beachtliche 20 Prozent anziehen soll.\n\nBesonders brisant ist die Lage an der Rohstoffbörse COMEX. Die registrierten Silberbestände sind auf 76 Millionen Unzen gefallen. Damit decken sie nur noch 13,4 Prozent der offenen Kontrakte ab. Diese Verknappung der physischen Reserven zieht einen soliden Boden unter den Preis, auch wenn das historische Rekordhoch vom Januar bei über 121 US-Dollar noch ein Stück entfernt liegt.\n\nHebelwirkung und wichtige Marken\n\nDer WisdomTree Silver 3x ETC profitiert als dreifach gehebeltes Produkt überproportional von diesem positiven Momentum und schloss am Freitag bei 168,39 Euro. Anleger müssen bei dem 286 Millionen Euro schweren Instrument jedoch die tägliche Anpassung der Swaps im Blick behalten. In Seitwärtsphasen führt dieser Mechanismus unweigerlich zu spürbaren Abweichungen vom regulären Silberpreis.\n\nFür die am Montag beginnende Handelswoche rücken klare charttechnische Marken in den Fokus. Auf der Oberseite muss der ETC das Freitags-Tageshoch von 171,20 Euro überwinden, um den aktuellen Trend zu bestätigen. Fällt der zugrundeliegende Silberpreis hingegen unter die wichtige Unterstützung bei 74,63 US-Dollar, droht ein kurzfristiger Rücksetzer in Richtung der 72-Dollar-Marke."} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Full_text/full_text_macro_central_banks.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Full_text/full_text_macro_central_banks.jsonl new file mode 100644 index 0000000..57068d7 --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Full_text/full_text_macro_central_banks.jsonl @@ -0,0 +1,9 @@ +{"url": "https://www.govtech.com/blogs/lohrmann-on-cybersecurity/why-anthropics-mythos-is-a-systemic-shift-for-global-cybersecurity", "title": "Why Anthropic Mythos Is a Systemic Shift for Global Cybersecurity", "publish_date": "2026-04-12T14:39:07Z", "full_text": "Dan Lohrmann BIO\n\nCONTACT\n\nRSS\n\nCreating robust government solutions demands fresh perspectives, inventive approaches and diligent effort. From fortifying cybersecurity defenses and leveraging AI to optimizing cloud infrastructure and securing mobile platforms, Dan offers practical ways to \"get to yes\" securely."} +{"url": "https://finance.yahoo.com/markets/options/articles/45k-debt-invest-ira-pay-125503481.html", "title": "I Have $45K in Debt . Should I Invest in an IRA or Pay the Bills First ? ", "publish_date": "2026-04-12T14:39:07Z", "full_text": "Quick Read\n\nIt’s a common question: Should I be investing if I’m carrying debt?\n\nMany advisers think you should pay off your debt (not counting a mortgage) before investing.\n\nPaying off non-mortgage debt frees up monthly cash flow that can fund a Roth IRA or other investment.\n\nA recent study identified one single habit that doubled Americans’ retirement savings and moved retirement from dream, to reality. Read more here.\n\nA 32-year-old with $45,000 in non-mortgage debt recently called into The Ramsey Show to ask: \"Would it be smart for me to open up a Roth IRA now even though I'm still in debt , or should I wait till I get all my debt off of me first?\" Host Dave Ramsey quickly advised the caller to focus on the debt first.\n\n\"The fastest way to become a millionaire, the fastest way to build substantial investments, is to first get out of debt because your most powerful wealth-building tool is your income,\" he said. The caller's annual income fluctuates between $100,000 and $150,000. Ramsey suggested she work overtime to earn $150,000, and live on $100,000. That $45,000 could be gone in a year.\n\nRead: I Review Investing Platforms for a Living, And SoFi Crypto Finally Changed My Mind\n\nI’ve spent years reviewing investing platforms across stocks, options, ETFs, and now crypto. Most crypto platforms fall into one of two categories: fast-moving exchanges with regulatory uncertainty, or traditional financial firms that treat crypto like an afterthought. SoFi Crypto is one of the very few platforms that breaks that mold.\n\nSeparating the Mortgage From Other Types of Debt\n\nThe caller also has a mortgage of $255,000, presumably at a reasonable interest rate. The $45,000 includes higher-rate student loans, a car loan and personal borrowing. Ramsey's advice: \"Pay the $45K off and then open the Roth IRA.\"\n\nRamsey was blunt with the caller: \"You've been a little sloppy. That's how we got here. That doesn't make you bad. It just makes you normal, but normal sucks. We don't want to be normal.\"\n\nEvery dollar going toward debt payments is a dollar that cannot be invested. Once the $45,000 is gone, the monthly cash that was servicing those loans becomes available to fund a Roth IRA and taxable accounts simultaneously. At her income level, she can contribute up to $7,500 annually to a Roth IRA, but she could also stack additional savings into a brokerage account. She has roughly 30 years of compounding before a traditional retirement age, which should set her up nicely.\n\n$45,000 in Debt Isn't As Bad As It Sounds\n\nRamsey's framework works well for someone in exactly this caller's position: high income, manageable non-mortgage debt, and a timeline short enough that delaying Roth contributions by one year costs very little in compounding. A 32-year-old losing one year of Roth contributions is a small sacrifice compared to the freedom of eliminating $45,000 in debt payments."} +{"url": "https://tribunaonline.com.br/economia/trabalhador-podera-sacar-ate-20-do-fgts-para-pagar-dividas-diz-ministro-298957", "title": "Trabalhador poderá sacar até 20 % do FGTS para pagar dívidas , diz ministro | Tribuna Online", "publish_date": "2026-04-12T14:39:07Z", "full_text": "Dario Durigan afirma que o atual governo deixa uma situação equilibrada na economia e nas finanças públicas | Foto: José Cruz/Agência Brasil\n\nNo comando do Ministério da Fazenda há menos de um mês, Dario Durigan disse em entrevista à Folha que trabalhadores com renda de até cinco salários mínimos (R$ 8.105) poderão sacar até 20% de seu saldo no FGTS (Fundo de Garantia por Tempo de Serviço) para quitar dívidas.\n\nContinue Lendo\n\nA medida deve liberar mais R$ 7 bilhões e será um dos elementos de um programa de renegociação que prevê também um desconto mínimo concedido pelos bancos e uma garantia do governo para refinanciar o saldo restante, com taxa de juros pactuada ou limitada.\n\nO pacote, uma demanda do presidente Lula (PT), deve contar também com linhas para caminhoneiros, motoristas de aplicativos e taxistas, e apoio a setores como construção civil e fertilizantes. Ele nega que as medidas sejam eleitoreiras. \"A gente está lidando com os problemas concretos.\"\n\nDurigan afirma que o atual governo deixa uma situação equilibrada na economia e nas finanças públicas, quadro distinto do \"descalabro\" ocorrido em 2022, quando Jair Bolsonaro (PL) tentou a reeleição. \"Não estamos deixando nenhuma bomba amarrada.\"\n\nFolha - A pauta do governo no momento são as medidas para reduzir o endividamento. O cenário é preocupante?\n\nDario Durigan - Depois do primeiro Desenrola, teve o começo de corte da Selic, em agosto de 2023, e uma queda do endividamento. No fim de 2024 e durante 2025, a relação é diretamente proporcional entre o aumento da taxa de juros e o endividamento das famílias, dos informais, das pequenas empresas e das grandes.\n\nO importante para as pessoas é que elas tomem crédito sustentável. A expectativa é que a gente dê um estímulo agora nessa virada de chave e deixe medidas estruturantes. Vai ter uma limitação na possibilidade de essa pessoa continuar jogando nas bets, uma espécie de quarentena para quem aderir.\n\nFolha - Por quanto tempo?\n\nDario Durigan - O presidente vai arbitrar. A gente tem trabalhado com um prazo de seis meses.\n\nFolha - Quais serão as ferramentas de estímulo?\n\nDario Durigan - Não há gasto público direto. A ideia é que as próprias instituições financeiras façam uma redução da dívida e haja um refinanciamento com uma taxa de juros menor. E aí entra o governo garantindo a inadimplência eventual nessa segunda operação.\n\nO governo não vai pagar a dívida das pessoas, mas vai garantir [o crédito] de modo que os bancos façam uma taxa de juros menor. E a gente vai usar o FGO [Fundo de Garantia de Operações] para isso.\n\nFolha - As pessoas também vão poder fazer um saque extraordinário no FGTS para pagar dívidas mais caras. Como vai funcionar?\n\nDario Durigan - Tem duas discussões. O ministro [do Trabalho, Luiz] Marinho identificou uma interpretação inconsistente da Caixa em relação à devolução que já foi feita para as pessoas demitidas e que fizeram a opção do saque-aniversário com consignado. Para corrigir essa interpretação, seria uma devolução de R$ 7 bilhões.\n\nA segunda medida envolve um saque limitado do FGTS. O que estamos discutindo? Quanto a gente pode limitar esse saque sem comprometer a sustentabilidade do fundo.\n\nFolha - Esse 'quanto' está em que faixa?\n\nDario Durigan - A gente tem trabalhado com um limite de 20% de saque da conta individual. É o número que está sendo discutido e que tem um impacto contido no fundo.\n\nFolha - Todos os trabalhadores terão acesso?\n\nDario Durigan - Os trabalhadores que ganhem até cinco salários mínimos e que fizerem jus às demais regras. Quem ganha até cinco salários mínimos representa 92% dos brasileiros. Acima disso, tem muito menos gente e dívidas maiores. Não deveríamos mobilizar fundos ou opções de saque para esses casos, o que não impede as instituições de oferecerem refinanciamento.\n\nFolha - O desconto vai ser de quanto?\n\nDario Durigan - Espero que de até 90%. Um exemplo: tem uma dívida de R$ 10 mil a juros de 8% ao mês. É impagável. Dá-se um desconto de 90%, fica com uma dívida de R$ 1.000. E, com a garantia da FGO, essa dívida pode ser rolada a 2% ou 2,5% ao mês. Muito menor e pagável.\n\nVamos ter que exigir um desconto mínimo. Estamos calibrando, mas espero que chegue a 90%.\n\nFolha - Vai ter limite de juros?\n\nDario Durigan - Como vai ter garantia pública, acho importante ter um juro pactuado ou limitado.\n\nFolha - Seriam esses 2,5%?\n\nDario Durigan - É um exemplo do que a gente tem perseguido, mas em diálogo com o sistema financeiro.\n\nFolha - Quantas pessoas serão atendidas?\n\nDario Durigan - Temos uma expectativa de atender a mais de 30 milhões de pessoas.\n\nFolha - Quanto vai tirar do fundo? Setores de habitação e de infraestrutura veem os saques com preocupação.\n\nDario Durigan - A gente não vai comprometer a sustentabilidade nem as políticas financiadas pelo fundo. Vamos fazer de maneira bem limitada e opcional.\n\nFolha - Falam em saque entre R$ 7 bilhões e R$ 10 bilhões.\n\nDario Durigan - Nossa estimativa é por aí. Mais para R$ 7 [bilhões].\n\nFolha - Após o Desenrola, houve aumento de 9 milhões de pessoas inadimplentes. O programa fracassou?\n\nDario Durigan - Não, ao contrário. O Desenrola cumpriu seu papel. Havia uma expectativa no começo de 2024 de que houvesse cortes na taxa de juros, a gente não viu isso. O que a gente viu foi um novo endividamento a partir de 2025.\n\nComo de novo estamos na expectativa de um corte da taxa de juros, é preciso que as famílias também possam viver com uma taxa de juros mais razoável nas dívidas pessoais.\n\nFolha - E para as empresas?\n\nDario Durigan - O programa tem três grandes frentes. Estamos falando das famílias. Os trabalhadores informais devem ter uma linha garantida também, porque tomam dívida mais cara. E as empresas vão poder tomar créditos, mas é uma coisa menor, focalizada para pequenas e MEIs [microempreendedores individuais].\n\nFolha - Como será a linha para informais?\n\nDario Durigan - Vamos refinanciar dívidas dos informais, que não têm garantia de salário, muitas vezes não têm patrimônio, um faturamento sólido e recorrente. O FGO também vai entrar para diminuir a taxa de juros.\n\nFolha - O FGI [Fundo Garantidor para Investimentos] pode ter aumento para as linhas do Peac [programa de crédito para micro, pequenas e médias empresas]?\n\nDario Durigan - Estamos discutindo outras medidas na economia, que não são de estímulo ao consumo. Visam a endereçar questões pontuais de alguns setores. Depende de um aporte do governo para capitalizar o FGI.\n\nAs linhas que já são previstas dentro do Fundo Clima, do Fundo Social, podem também ser mobilizadas. Pode ter uma linha de estímulo à construção civil. Podemos ter uma linha como foi a de financiamento de caminhões no fim do ano, estendida para motoristas de aplicativos e taxistas.\n\nFolha - Qual é a bússola nessas discussões? É o temor de desaceleração da economia, ou um cenário eleitoral mais desafiador para o presidente Lula?\n\nDario Durigan - É uma avaliação econômica do que pode estar disfuncional no país. O endividamento das famílias é preocupante, e estamos endereçando isso. No caso dos setores específicos, existem alguns que sofrem mais com os juros ou com a questão geopolítica. O tema dos fertilizantes, por exemplo, pode ser objeto de uma dessas linhas.\n\nFolha - Há receio no mercado de que seja o início de um saco de bondades do presidente em ano eleitoral.\n\nDario Durigan - Não se trata de uma questão eleitoral. A gente está lidando com problemas concretos. Não vamos deixar de atender à questão da guerra nos combustíveis e o endividamento das pessoas, questões fundamentais para a economia do país.\n\nFolha - Nos combustíveis, preveem alguma nova medida?\n\nDario Durigan - Não. Vamos aguardar até o fim de maio para uma reavaliação.\n\nFolha - O imposto de exportação foi suspenso. Era a fonte de compensação de todas as medidas. Como vão fazer?\n\nDario Durigan - O juiz que deferiu a liminar cita supostos dispositivos da medida provisória que não existem. É uma medida absurda. A gente recorreu ao Tribunal de Justiça do Rio, que negou o efeito que a União pediu, mas sem entrar na discussão. É inadmissível.\n\nFolha - Vão ao Supremo Tribunal Federal?\n\nDario Durigan - Até onde for preciso. Se isso não for corrigido, tem que buscar outras receitas.\n\nFolha - O Congresso avançou na discussão de projetos considerados pautas-bomba. A questão dos agentes comunitários, o novo mínimo da assistência social. Vê ímpeto eleitoral?\n\nDario Durigan - Tenho dito a todos os líderes, ao presidente Hugo [Motta, da Câmara], ao presidente Davi [Alcolumbre, do Senado], que estamos enfrentando uma situação de guerra. Estamos fazendo um esforço fiscal para proteger o país. Esse esforço não pode ser desvirtuado ou desviado em outras questões que não nos interessam agora.\n\nTenho pedido a sensibilidade do Congresso. Reforço aqui o pedido para que a gente não avance nessas pautas problemáticas.\n\nFolha - A guerra é um fator de incerteza, e o Banco Central diminuiu o ritmo de corte dos juros. Como vê a decisão?\n\nDario Durigan - A parte da Fazenda, a gente vem fazendo. Adotar medidas que garantam a neutralidade fiscal e que minimizem o aumento de preço no país ajuda a tomada de direção do BC.\n\nFolha - O BC fala em cautela.\n\nDario Durigan - Eu falo também. Não vamos deixar pauta-bomba do Executivo para as próximas gestões, como aconteceu em 2022. Não vamos repetir esse cenário para 2027.\n\nNão estamos empurrando para frente o tema dos precatórios, um [aumento no] Fundeb [fundo da educação básica]. Eu não estou tirando IPI ou IOF do próximo governo. Nós recompusemos a estrutura fiscal do país. Tudo isso colabora com a política monetária.\n\nFolha - Mas como avalia a política do presidente do BC, Gabriel Galípolo?\n\nDario Durigan - Eu não vou comentar o papel do BC porque tem a sua competência. O que estou dizendo é, do lado da Fazenda, com todas as dificuldades políticas, são várias decisões que a gente está colocando na mesa. Reforma tributária, rever o Perse [programa de benefícios para o setor de eventos], corte linear de 10% nos benefícios tributários. Isso tudo fortalece o fiscal.\n\nFolha - O fiscal não seria um motivo para o BC colocar o pé no freio?\n\nDario Durigan - O fiscal não é motivo.\n\nFolha - Há duas indicações abertas na diretoria do BC. Já levou algum nome para o presidente?\n\nDario Durigan - Não tive a oportunidade de tratar com o presidente Lula sobre isso.\n\nFolha - O governo pode fazer algum ajuste para o BRB não quebrar?\n\nDario Durigan - A orientação é que não deve haver ajuda federal. Os bancos federais, atuando como bancos, podem avaliar o interesse em comprar carteira, operação, imóvel. Os bancos privados estão avaliando. O que a gente não pode perder de vista é que a responsabilidade é do governo do Distrito Federal, acionista do BRB.\n\nFolha - O governo encaminhará o PLDO [Projeto de Lei de Diretrizes Orçamentárias] de 2027, primeiro ano do próximo presidente. Qual será a sinalização?\n\nDario Durigan - De estabilidade. Isso vale para além da questão orçamentária e econômica, vale para a questão política. O ano de 2022 é um exemplo negativo para o país.\n\nDigo para quem me procura do mercado: é estranho o mercado apoiar tanto as forças políticas que estavam governando em 2022, porque foi um ano de descalabro nas contas públicas. Estou falando seja do ponto de vista econômico, seja da mensagem de falta de respeito institucional, de se namorar com o golpe de Estado.\n\nO ano de 2026 vai ser diferente. Vamos deixar as contas públicas em ordem, para que em 2027 não haja sustos como a gente tomou em 2023.\n\nFolha - Vai ter um escrutínio de comparação. A oposição está catalogando números, o próprio ex-ministro Paulo Guedes vai lançar um livro.\n\nDario Durigan - É bem-vinda a comparação. Não estamos deixando nenhuma bomba amarrada dentro do governo para o próximo. Vamos respeitar as instituições. É um trabalho muito diferente. Não teve populismo em conta pública. A gente tem um limite de gasto que controlou as despesas e tivemos uma recomposição da receita.\n\nFolha - Há ceticismo em relação ao arcabouço, e a Fazenda já reconheceu que precisará reforçá-lo.\n\nDario Durigan - Se o próximo governo fizer um ajuste de 2% do PIB, como a gente fez, vai chegar no fim do próximo ciclo com uma situação muito melhor.\n\nÉ preciso limitar as despesas obrigatórias. Isso vai precisar avançar, sem ficar empurrando o problema para frente, com discurso que divide o país, mas trazendo todo mundo para a mesa, chegando a acordos.\n\nFolha - É limitar o BPC [Benefício de Prestação Continuada], ou mexer nos pisos de saúde e educação?\n\nDario Durigan - Vários debates têm que ser enfrentados, como a gente fez no fim de 2024. As alterações feitas pelo governo Bolsonaro em 2021 [flexibilização das regras] tiraram o BPC de uma boa política eficiente. É preciso rever isso. Estamos agora discutindo o seguro-defeso [benefício para pescadores artesanais] no Congresso.\n\nFolha - Na hipótese de reeleição do presidente Lula, há chance de discutir a unificação dos programas sociais?\n\nDario Durigan - Existe essa possibilidade, sim, de racionalizar, trazer eficiência, diminuir a burocracia. Quando a gente discute biometria, acompanhamento dos cadastros, mais filtros, isso só não basta. Mas isso precisa ser feito. Não dá para acontecer como no governo passado, de repente desliga a máquina pública, desliga os controles e olha só para a questão eleitoral. Isso não será feito.\n\nRAIO-X\n\nDario Durigan, 41\n\nFormado em direito pela USP (Universidade de São Paulo). Atuou como assessor na subchefia de Assuntos Jurídicos da Casa Civil no governo Dilma Rousseff (PT). Foi diretor de políticas públicas do WhatsApp entre 2020 e 2023, quando assumiu a secretaria-executiva do Ministério da Fazenda. Desde 20 de março, é ministro da Fazenda, sucedendo Fernando Haddad."} +{"url": "https://www.tinnhanhchungkhoan.vn/co-phieu-can-quan-tam-ngay-134-post388652.html", "title": "Cổ phiếu cần quan tâm ngày 13 / 4", "publish_date": "2026-04-12T14:39:07Z", "full_text": "(ĐTCK) Báo Đầu tư Chứng khoán trích báo cáo phân tích một số cổ phiếu cần quan tâm trước phiên 13/4 của các công ty chứng khoán.\n\nKhuyến nghị mua dành cho cổ phiếu GEX\n\nCTCK BIDV (BSC)\n\nTriển vọng kinh doanh 2026-2027 đối với Công ty cổ phần Tập đoàn Gelex (GEX – sàn HOSE): mảng thiết bị điện (GEE) dư địa tăng thị phần lớn, hưởng lợi mạnh từ chính sách nội địa hóa; mảng vật liệu xây dựng (VGC) biên lợi nhuận gộp hồi phục và tái cấu trúc hướng đến tối ưu; mảng BĐS KCN (VGC, PXL, Titan Hải Phòng) hạ tầng và chính sách tạo cơ hội thu hút FDI.\n\nNăm 2026, doanh thu và lợi nhuận sau thuế - cổ đông thiểu số dự phóng lần lượt đạt 43.081 tỷ đồng (tăng trưởng 9%) và 1.201 tỷ đồng, giảm 19% và giảm 7% nếu loại bỏ khoản bất thường trong năm 2025.\n\nNăm 2027, doanh thu và lợi nhuận sau thuế - cổ đông thiểu số dự phóng đạt 45,844 tỷ đồng (tăng trưởng 6%), 1.296 tỷ đồng (tăng trưởng 8%). Chúng tôi điều chỉnh giảm 19% dự phóng lợi nhuận sau thuế - cổ đông thiểu số năm 2026 so với báo cáo trước do: Dự án khách sạn Fairmont hoạt động sớm hơn dự kiến 1 năm, làm tăng chi phí lãi vay và khấu hao. Công ty đã vay thêm 200 triệu USD trong quý I/2026, trực tiếp tăng chi phí lãi vay và lỗ tỷ giá.\n\nChúng tôi giảm 8% giá mục tiêu năm 2026 từ mức 53.200 đồng/CP xuống mức 48.800 đồng/CP với các giả định sau: Điều chỉnh tăng WACC từ 10.7% lên mức 11,6% và các BĐS đầu tư có mức cap rate từ 6% lên 9% do môi trường lãi suất đã tăng cao hơn so với năm 2025;\n\nĐịnh giá mảng vật liệu xây dựng tăng 50% định giá từ 8.300 tỷ đồng lên 12.482 tỷ đồng, với giả định thuế chống bán phá giá kính xây dựng giúp tăng biên gộp mảng này 2 điểm % và tái cơ cấu doanh nghiệp giúp giảm 0,7 điểm% tỷ lệ SGA/doanh thu;\n\nBổ sung 2.800 tỷ đồng giá trị sổ sách của 2 công ty con là Titan Hải Phòng (BĐS KCN) và FIH (dự án nhà ở thương mại 226 Lê Lai, Hải Phòng). Trong quý I/2026, GEL hoàn thành huy động 2.800 tỷ đồng từ IPO để góp vốn 2 công ty kể trên.\n\nTuy nhiên, trong đợt tăng IPO tăng vốn của GEL diễn ra quý IV/2025, GEX không đăng ký mua dẫn đến tỷ lệ sở hữu tại GEL giảm từ 80% xuống mức 70%.\n\nMặc dù điều chỉnh giảm 8% định giá, tuy nhiên, giá cổ phiếu cũng đã giảm 38% từ đỉnh gần nhất mở ra cơ hội mua cổ phiếu GEX với giá mục tiêu năm 2026 đạt 48.800 đồng/CP, upside 23% (so với giá tham chiếu ngày 10/04/2026) dựa trên phương pháp định giá từng phần. Dự phóng lợi nhuận sau thuế - cổ đông thiểu số 2026 đạt 1.201 tỷ đồng (giảm 19%), cổ phiếu đang giao dịch ở mức P/E FW 2026 là 30.2x, tương đương với trung bình 2021 – 2025.\n\nKhuyến nghị tăng tỷ trọng dành cho cổ phiếu MSR\n\nCTCK Agriseco (AGR)\n\nCTCP Masan High-Tech Materials (UPCOM: MSR) mới đây đã công bố tài liệu ĐHCĐ thường niên 2026 với nhiều thông tin đáng chú ý. Theo đó, MSR đặt kế hoạch kinh doanh với 2 kịch bản. Trong kịch bản thấp, doanh thu thuần dự kiến đạt 16.000 tỷ đồng, lợi nhuận sau thuế đạt 1.700 tỷ đồng. Trong kịch bản cao, doanh thu thuần dự kiến đạt 20.300 tỷ đồng và lợi nhuận sau thuế đạt 2.500 tỷ đồng. Các kịch bản đề ra đều tăng trưởng mạnh so với kết quả thực hiện 2025. Công ty giữ nguyên lợi nhuận sau thuế cổ đông công ty mẹ không chia cổ tức và dự kiến phát hành gần 11 triệu cổ phiếu ESOP với mức giá 15.000 đồng/cp.\n\nTriển vọng các mảng kinh doanh của MSR: Mảng vonfram: Đây hiện là mảng kinh doanh chủ lực của MSR, đóng góp khoảng 60% tổng doanh thu. Triển vọng thị trường duy trì tích cực khi nhu cầu toàn cầu gia tăng, đặc biệt từ các ngành công nghệ cao, trong khi nguồn cung bị thắt chặt do Trung Quốc – quốc gia chi phối phần lớn sản lượng – siết chặt kiểm soát xuất khẩu. Giá vonfram hiện tại đã tăng hơn gấp đôi so với đầu năm, dao động quanh ngưỡng 2.000 USD/MTU và dự kiến duy trì ở mức cao trong thời gian tới. Với vị thế là một trong những nhà cung cấp lớn ngoài Trung Quốc, MSR được kỳ vọng hưởng lợi từ xu hướng giá và sự thiếu hụt nguồn cung.\n\nMảng đồng: Giá bán đồng hiện tại tăng khoảng 20%. Đà tăng này đến từ nguồn cung gián đoạn kéo dài và hoạt động đầu cơ tại thị trường Mỹ. Theo dự báo của Goldman Sachs, giá đồng vẫn duy trì cao trong nửa đầu năm 2026, trước khi có thể hạ nhiệt khi Mỹ làm rõ chính sách nhập khẩu đồng. Chúng tôi kỳ vọng lãi gộp mảng đồng năm 2026 tăng khoảng 25% so với năm trước nhờ giá cao và sản lượng phục hồi.\n\nMảng florit: Giá florit bình quân năm 2025 duy trì xu hướng đi ngang, trong khi mặt bằng giá hiện tại đã tăng khoảng 4% so với cuối năm. Trong ngắn hạn, giá được kỳ vọng vận động theo xu hướng tăng nhẹ nhờ nguồn cung tiếp tục bị kiểm soát chặt từ Trung Quốc, trong khi nhu cầu duy trì ổn định, đặc biệt từ các ngành hóa chất và sản xuất vật liệu phục vụ chuỗi giá trị xe điện.\n\nKế hoạch chuyển sàn từ UPCoM lên HOSE: Năm 2026, MSR cũng lên kế hoạch hủy đăng ký giao dịch cổ phiếu trên sàn UPCoM để niêm yết trên sàn HOSE. Tập đoàn Masan cũng đã công bố nghị quyết về việc thoái tối đa 5% vốn tại MSR nhằm tăng tỷ lệ cổ phiếu tự do chuyển nhượng, giúp MSR đủ điều kiện trở thành công ty đại chúng và chuẩn bị cho quá trình chuyển sàn. Điều này sẽ giúp MSR cải thiện tính minh bạch, gia tăng thanh khoản và mở rộng tệp nhà đầu tư, đặc biệt là dòng vốn tổ chức và nhà đầu tư nước ngoài.\n\nKết quả kinh doanh của MSR ghi nhận sự cải thiện rõ rệt trong năm 2025. Bước sang năm 2026, doanh nghiệp đặt kế hoạch tăng trưởng tích cực cùng kỳ vọng niêm yết cổ phiếu trên sàn HOSE. Agriseco Research khuyến nghị tăng tỷ trọng cổ phiếu với giá mục tiêu là 56.000 đồng/cp (upside 16% so với giá hiện tại).\n\nPVS và PVT là 2 cổ phiếu thích hợp để đầu tư giai đoạn này\n\nCTCK MB (MBS)\n\nGiá dầu được kỳ vọng sẽ chuyển sang trạng thái biến động cao theo thông tin đàm phán, với mặt bằng giá duy trì ở mức cao tương đối trong ngắn hạn, thay vì quay trở lại vùng thấp trước xung đột. Với giá dầu neo cao, chúng tôi dự phóng hầu hết các doanh nghiệp dầu khí nội địa đều sẽ hưởng lợi trong quý I/2026 với lượng backlog dự án và giá bán sản phẩm tăng cao.\n\nChúng tôi ưu tiên lựa chọn các doanh nghiệp dầu khí có (1) định giá thấp và tiềm năng tăng giá còn nhiều, (2) hưởng lợi từ giá dầu tăng cao và (3) không bị ảnh hưởng quá lớn từ gián đoạn nguồn cung dầu. Dựa trên 3 yếu tố trên, chúng tôi đánh giá PVS và PVT là 2 cổ phiếu thích hợp để đầu tư giai đoạn này.\n\n>> Tải báo cáo\n\nKhuyến nghị mua dành cho cổ phiếu MCH\n\nCTCK Phú Hưng (PHS)\n\nSau khi chứng kiến mức sụt giảm về kết quả kinh doanh do gián đoạn chung của kênh GT trong năm 2025, kết quả kinh doanh 2 tháng đầu năm 2026 của CTCP Hàng tiêu dùng Masan (MCH – sàn HOSE) đã ghi nhận mức phục hồi rõ rệt, cho thấy hiệu quả ban đầu của mô hình Retail Supreme.\n\nCụ thể, doanh thu tăng 15,2% đạt 5.160 tỷ đồng, mức tăng trưởng được đóng góp bởi ngành hóa mỹ phẩm (tăng trưởng 27,7%), gia vị (tăng trưởng 22,8%) và thực phẩm tiện lợi (tăng trưởng 10,3%).\n\nMCH là doanh nghiệp dẫn đầu ngành hàng tiêu dùng tại Việt Nam, sở hữu hệ sinh thái thương hiệu mạnh, thị phần dẫn đầu, danh mục sản phẩm đa dạng đáp ứng mọi nhu cầu thiết yếu. Chúng tôi kỳ vọng MCH sẽ tiếp tục duy trì đà tăng trưởng bền vững và vượt trội so với ngành, nhờ hệ thống phân phối độc nhất, năng lực R&D, quảng bá thương hiệu mạnh mẽ cùng với chiến lược cao cấp hóa sản phẩm và mở rộng ra thị trường quốc tế.\n\nViệc niêm yết lên HOSE vào tháng 12/2025 sẽ mở ra cơ hội bổ sung vào các rổ chỉ số, thu hút dòng vốn mới; cùng với chính sách chi trả cổ tức cao cũng là yếu tố hấp dẫn cho các nhà đầu tư.\n\nCho năm 2026F/2027F, chúng tôi dự phóng MCH sẽ ghi nhận doanh thu thuần lần lượt tăng 11,2%/8,7% đạt 33.977/36.934 tỷ đồng. Sử dụng phương pháp DCF và P/E, chúng tôi ước tính giá hợp lý đối với MCH là 177.200 đồng/cổ phiếu. Do đó, chúng tôi đưa ra khuyến nghị mua với mức tăng giá tiềm năng là 25%"} +{"url": "https://baomoi.com/truy-to-nhom-dieu-hanh-bankland-lua-gan-500-ty-dong-cua-hon-5-300-bi-hai-c54920488.epi", "title": "Truy tố nhóm điều hành Bankland lừa gần 500 tỷ đồng của hơn 5 . 300 bị hại", "publish_date": "2026-04-12T14:39:07Z", "full_text": "Lập công ty huy động vốn để chiếm đoạt tiền\n\nNgày 12/4, Viện KSND TP Hà Nội vừa hoàn thành cáo trạng truy tố bị can Vũ Đức Tĩnh (SN 1981, ở phường Cát Lái, TP HCM) về tội \"Lừa đảo chiếm đoạt tài sản\".\n\nBị truy tố cùng tội danh với Tĩnh còn 9 người khác, trong đó có Nguyễn Thị Thanh Vân (34 tuổi, ở xã Phú Hội, tỉnh Lâm Đồng).\n\nTheo cáo buộc, để có tiền sử dụng vào mục đích cá nhân, từ tháng 10/2021 - 11/2022, Vũ Đức Tĩnh đã chỉ đạo thành lập 3 pháp nhân gồm: Công ty Bankland, Công ty Cawiho, Công ty GBF. Thực tế, 3 công ty này không hoạt động sản xuất kinh doanh, chỉ hoạt động theo hình thức đa cấp, huy động tiền của các nhà đầu tư sau để trả lãi cho nhà đầu tư trước.\n\nBị can Vũ Đức Tĩnh không đứng tên trong danh sách cổ đông các công ty, nhưng ông ta tự nhận là cố vấn cấp cao, chỉ đạo, điều hành hoạt động của cả 3 công ty này.\n\nĐối với Công ty Bankland, Vũ Đức Tĩnh phân công Quản Văn Dương giữ chức chủ tịch HĐQT, Nguyễn Thị Như giữ chức tổng giám đốc; Công ty Cawiho, Tĩnh phân công Tạ Văn Cương giữ chức chủ tịch HĐQT, Ninh Đại Dương quản lý, cập nhật thông tin và số tiền đầu tư của khách hàng trên trang web của công ty; còn Công ty GBF, Tĩnh phân công Vũ Hồng Quân giữ chức chủ tịch HĐQT và Kiều Văn Hoạch làm giám đốc.\n\nRiêng bị can Nguyễn Thị Thanh Vân được Tĩnh phân công là kế toán trưởng của 3 công ty trên.\n\nSau khi thành lập, Tĩnh chỉ đạo chủ tịch HĐQT và giám đốc của 3 công ty tổ chức hội nghị, hội thảo, cung cấp thông tin sai sự thật về các hình thức đầu tư nhằm kêu gọi góp vốn, mua cổ phiếu chưa niêm yết.\n\nTheo đó, tại Công ty Bankland, từ tháng 12/2021 - 9/2022, cơ quan truy tố xác định bị can Vũ Đức Tĩnh và đồng phạm đã chiếm đoạt được tổng số hơn 479 tỷ đồng của 5.291 bị hại, thông qua hình thức huy động vốn với lãi suất cao, bán cổ phiếu chưa được niêm yết và bán các dự án không có thật. Số tiền trên, nhóm Tĩnh cho nhà đầu tư hơn 28 tỷ đồng, còn chiếm đoạt hơn 451 tỷ đồng.\n\nCông ty Cawiho, từ tháng 11/2021 - 8/2022, các bị can đã chiếm đoạt hơn 88 tỷ đồng của 59 bị hại, thông qua hình thức huy động vốn với lãi suất cao và bán cổ phiếu chưa được niêm yết. Nhóm đã trả cho bị hại tổng số hơn 45 tỷ đồng, còn chiếm đoạt hơn 42 tỷ đồng.\n\nCòn tại Công ty GBF, từ tháng 8/2022 - 12/2022, nhóm của Tĩnh đã chiếm đoạt hơn 4,3 tỷ đồng của 18 bị hại cũng với chiêu thức tương tự. Đã trả lại cho bị hại gần 1 tỷ đồng, chiếm đoạt hơn 3,3 tỷ đồng.\n\nCơ quan truy tố quy kết, bị can Vũ Đức Tĩnh là người chỉ đạo, còn Nguyễn Thị Thanh Vân là kế toán trưởng. Hai bị can và đồng phạm được phân công làm lãnh đạo 3 công ty, đã chiếm đoạt của 5.368 bị hại số tiền hơn 572 tỷ đồng; đã trả hơn 75 tỷ đồng, còn chiếm đoạt hơn 497 tỷ đồng.\n\nHai bị can Quản Văn Dương, Nguyễn Thị Như trong vụ án.\n\nKhông thực hiện yêu cầu của cơ quan điều tra\n\nVề số tiền huy động được, các bị can chia nhau hưởng lợi theo mức khác nhau. Riêng Vũ Đức Tĩnh khai sử dụng để mua bất động sản ở nhiều địa phương, như Quảng Ninh và đặc khu kinh tế Phú Quốc.\n\nKết quả xác minh đối với bất động sản tại phường Hạ Long, tỉnh Quảng Ninh, cho thấy, các bị can mua 4 căn hộ từ Công ty TNHH Mặt trời Phú Quốc: Căn hộ S41210 do Nguyễn Thị Thanh Vân đứng tên giá trị vốn tự có là hơn 821 triệu đồng, vay ngân hàng hơn 5,7 tỷ đồng, tổng giá trị hơn 6,5 tỷ đồng; căn M639 do Nguyễn Thị Thanh Vân đứng tên giá trị vốn tự có hơn 2,8 tỷ đồng, không vay vốn ngân hàng; căn hộ S380 do Nguyễn Đức Minh đứng tên với vốn tự có là hơn 11,7 tỷ đồng, không vay vốn ngân hàng; căn hộ M637 do Nguyễn Văn Minh đứng tên với vốn tự có hơn 3 tỷ đồng, cũng không vay ngân hàng.\n\nCơ quan Cảnh sát điều tra Công an TP Hà Nội đã đề nghị Công ty TNHH Mặt trời Phú Quốc phối hợp làm thủ tục thanh lý hợp đồng mua bán và chuyển tiền sau khi thanh lý đến tài khoản của Công an TP Hà Nội để xử lý theo quy định của pháp luật. Tuy nhiên, cáo trạng thể hiện đến nay, Công ty TNHH Mặt trời Phú Quốc chưa trả lời yêu cầu trên của Công an TP Hà Nội.\n\nNgoài các bất động sản trên, bị can Vũ Đức Tĩnh còn nhờ lái xe của mình đứng tên các căn hộ số V502 và C132 tại một dự án ở Hạ Long. Cụ thể, tại căn C132 của dự án, tổng số tiền đã được thanh toán là gần 2,6 tỷ đồng, sau khi hai bên thỏa thuận thống nhất thanh lý hợp đồng, Công ty CP Bất động sản Mặt trời 2 phải trả cho lái xe của Tĩnh số tiền 3 tỷ đồng và doanh nghiệp này đã chuyển tiền vào tài khoản của Công an TP Hà Nội. Đối với căn V502, tổng số tiền đã thanh toán là gần 7,5 tỷ đồng, sau khi hai bên thỏa thuận thống nhất thanh lý hợp đồng, Công ty CP Bất động sản Mặt trời 2 phải trả cho lái xe của Tĩnh hơn 8,6 tỷ đồng.\n\nTrong các ngày 24/4/2024 và 28/11/2024, Cơ quan điều tra yêu cầu Công ty CP Bất động sản Mặt trời 2 chuyển toàn bộ số tiền trên đến tài khoản của Công an TP Hà Nội nhưng đến nay, doanh nghiệp này chưa thực hiện."} +{"url": "https://www.reflector.com/news/national/lessons-learned-in-70s-have-made-the-us-and-world-economies-less-vulnerable-to-oil/article_889e87a7-70fd-5892-8f19-f669048a2cd2.html", "title": "Lessons learned in 70s have made the US and world economies less vulnerable to oil shocks", "publish_date": "2026-04-12T14:39:07Z", "full_text": "State Alabama Alaska Arizona Arkansas California Colorado Connecticut Delaware Florida Georgia Hawaii Idaho Illinois Indiana Iowa Kansas Kentucky Louisiana Maine Maryland Massachusetts Michigan Minnesota Mississippi Missouri Montana Nebraska Nevada New Hampshire New Jersey New Mexico New York North Carolina North Dakota Ohio Oklahoma Oregon Pennsylvania Rhode Island South Carolina South Dakota Tennessee Texas Utah Vermont Virginia Washington Washington D.C. West Virginia Wisconsin Wyoming Puerto Rico US Virgin Islands Armed Forces Americas Armed Forces Pacific Armed Forces Europe Northern Mariana Islands Marshall Islands American Samoa Federated States of Micronesia Guam Palau Alberta, Canada British Columbia, Canada Manitoba, Canada New Brunswick, Canada Newfoundland, Canada Nova Scotia, Canada Northwest Territories, Canada Nunavut, Canada Ontario, Canada Prince Edward Island, Canada Quebec, Canada Saskatchewan, Canada Yukon Territory, Canada\n\nZip Code"} +{"url": "https://www.prnewswire.com/news-releases/the-conference-board-employment-trends-index-eti-declined-in-march-302734697.html", "title": "The Conference Board Employment Trends Index™ ( ETI ) Declined in March", "publish_date": "2026-04-12T14:39:07Z", "full_text": "NEW YORK, April 6, 2026 /PRNewswire/ -- The Conference Board Employment Trends Index™ (ETI) declined to 105.72 in March, from an upwardly revised 105.84 in February. The Employment Trends Index is a leading composite index for payroll employment. When the Index increases, employment is likely to grow as well, and vice versa. Turning points in the Index indicate that a change in the trend of job gains or losses is about to occur in the coming months.\n\n\"Job seekers continue to face a challenging market,\" said Mitchell Barnes, Economist at The Conference Board. \"This is evident in the ETI as several components moderated in March. Overall, the US economy has remained surprisingly resilient, but rising geopolitical uncertainty may contribute to ongoing employer hesitancy to add more workers.\"\n\nThe share of consumers who report \"jobs are hard to get\"—an ETI component from the Consumer Confidence Survey®—climbed to 21.5% in March and reflects a 5-percentage point rise since March 2025. The share of small firms reporting that jobs are 'not able to be filled right now' declined by 1 percentage point in March to reach 32%. The share of involuntary part-time workers rose in March to 16.5%, but that measure declined from 19.4% in December.\n\nInitial claims for unemployment insurance declined to 207,800 in March, reflecting a steady decline in jobless claims from the 2025 average of 226,450. Employment in the temporary help services industry rose marginally in March and in three of the last five months. Industrial production and real manufacturing and trade sales were also steady in their most recent data releases.\n\nMarch's decrease in the Employment Trends Index was a result of negative contributions from five of its eight components: the Ratio of Involuntarily Part-time to All Part-time Workers, the Percentage of Firms with Positions Not Able to Fill Right Now, the Percentage of Respondents Who Say They Find 'Jobs Hard to Get, Industrial Production, and Real Manufacturing and Trade Sales. Three components contributed positively: Initial Claims for Unemployment Insurance, Job Openings, and the Number of Employees Hired by the Temporary-Help Industry.\n\nThe eight leading indicators of employment aggregated into the Employment Trends Index include:\n\nPercentage of Respondents Who Say They Find \"Jobs Hard to Get\" (The Conference Board Consumer Confidence Survey ® )\n\n) Initial Claims for Unemployment Insurance (U.S. Department of Labor)\n\nPercentage of Firms with Positions Not Able to Fill Right Now (© National Federation of Independent Business Research Foundation)\n\nNumber of Employees Hired by the Temporary-Help Industry (U.S. Bureau of Labor Statistics)\n\nRatio of Involuntarily Part-time to All Part-time Workers (BLS) ⴕ\n\nJob Openings (BLS)**\n\nIndustrial Production (Federal Reserve Board)*\n\nReal Manufacturing and Trade Sales (U.S. Bureau of Economic Analysis)***\n\n*Statistical imputation for the recent month\n\n**Statistical imputation for two most recent months (due to data release delays)\n\n***Statistical imputation for three most recent months (due to data release delays)\n\nⴕ Note missing October 2025 value for Ratio of Involuntarily Part-time Workers estimated using linear interpolation\n\nThe Conference Board publishes the Employment Trends Index monthly, at 10 a.m. ET, on the Monday that follows each Friday release of the Bureau of Labor Statistics Employment Situation report. The technical notes to this series are available on The Conference Board website: http://www.conference-board.org/data/eti.cfm.\n\nAbout The Conference Board\n\nThe Conference Board is the member-driven think tank that delivers trusted insights for what's ahead. Founded in 1916, we are a non-partisan, not-for-profit entity holding 501 (c) (3) tax-exempt status in the United States. www.conference-board.org.\n\nEmployment Trends Index (ETI)™ 2026 Publication Schedule Index Release Date (10 AM ET) Data for the Month Monday, February 9th 2026 January 2025 Monday, March 9th February Monday, April 6th March Monday, May 11th April Monday, June 8th May Monday, July 6th June Monday, August 10th July Tuesday, September 8th August Monday, October 5th September Monday, November 9th October Monday, December 7th November Monday, January 11th 2027 December\n\n\n\n\n\nSOURCE The Conference Board"} +{"url": "https://www.sozcu.com.tr/30-yildir-ilk-kez-yasaniyor-merkez-bankalari-dolardan-kacip-altina-sigindi-p309549", "title": "30 yıldır ilk kez yaşanıyor : Merkez bankaları dolardan kaçıp altına sığındı", "publish_date": "2026-04-12T14:39:07Z", "full_text": "Merkez bankalarının altına yönelmesi ile küresel rezerv dengelerinde tarihi bir eşik aşıldı. Bloomberg verilerine göre merkez bankalarının altın stokları, son 30 yılda ilk kez ABD Hazine tahvillerinin önüne geçti.\n\nMerkez bankalarının toplam altın rezervi 30 yıldır ilk kez, ABD hazine tahvillerini geride bıraktı. Analistlere göre bu, ülkelerin dolar cinsi varlıklardan bilinçli ve hızlı uzaklaşmasını yansıtan kritik dönüm noktası oldu.\n\nABD TAHVİLLERİNİ SOLLADI\n\nBloomberg verilerine göre, altın artık küresel merkez bankası rezervlerinin yüzde 24'ünü oluştururken, ABD hazine tahvillerinin rezervlerdeki payı ise yüzde 21 seviyesine geriledi. Toplam altın rezervleri yaklaşık 4 trilyon dolara yükselirken ABD tahvillerinin payını 3,9 trilyon dolar civarında olduğu değerlendiriliyor.\n\n2015'in son çeyreğinde merkez bankalarının rezervlerinde ABD hazine tahvilleri yüzde 33, altın ise yüzde 9 seviyesindeydi.\n\nMERKEZ BANKALARI İÇİN STRATEJİK ALTERNATİF\n\nAnalistlere göre rezervlerdeki denge değişimi Rusya'nın Ukrayna'yı işgalinden sonra döviz varlıklarının dondurulması ile başladı. 2022'de ABD ve müttefikleri Rus Merkez Bankası varlıklarından yaklaşık 300 milyar doları dondurmuş, bu hamle dolar cinsinden varlıklara el konulabileceği gerçeğini gözler önüne sermişti.\n\nYaptırımlardan muaf olan ve risk taşımayan altın ise bu süre zarfında merkez bankaları için stratejik alternatif haline geldi.\n\nDÜNYA ALTIN KONSEYİ AÇIKLADI\n\nDünya Altın Konseyi verilerine göre, merkez bankaları 2025'te toplam altın fiyatlarındaki yükselişe rağmen 863 ton altın alımı gerçekleştirdi. Bu miktar, kayıtlardaki en yüksek dördüncü yıllık artış olarak öne çıkarken son on yıl ortalamasının neredeyse iki katına ulaştı.\n\nBu süreçte en fazla alımı ise Polonya Merkez Bankası gerçekleştirdi. Banka, rezervlerine 102 ton daha altın ekleyerek toplam rezervlerini 550 tona çıkardı.\n\nÇin Halk Bankası da bu süreçte resmi olarak 27 tonluk alım açıklasa da Dünya Altın Konseyi, geçen yılki toplam alımların yaklaşık yüzde 57'sinin bildirilmediğini ve gerçek birikimin önemli ölçüde daha yüksek olduğunu belirtiyor.\n\nALIMLAR SÜRECEK\n\nDiğer yandan Dünya Altın Konseyi'nin 2025 Merkez Bankası Altın Rezervleri Anketine göre merkez bankaları önümüzdeki yıllarda da altın alımına devam edeceğinin sinyalini veriyor. Katılımcılar altın rezervlerini azaltma niyetinde olmadığını belirtirken, doların da küresel rezervlerdeki payının 5 yıl sonra daha düşük olmasını bekliyor.\n\nABD doları küresel ticarette, emtia fiyatlamasında ve finansal sözleşmelerdeki baskın konumunu korusa da küresel rezervlerdeki payı yüzde 72 seviyesinden yüzde 58'e düştü. Bu düşüş ise ABD'de mali açıkların düşük faizle finanse edilmesini giderek zorlaştırıyor.\n\nAynı zamanda altın, 2025 yılını yaklaşık yüzde 70’lik yükselişle tamamlayarak 1979'den beri en güçlü yıllık performansını gösterdi. Bu yükselişi destekleyen kurumsal alımların da hız kesmeden sürdüğü görülüyor.\n\n*BU HABERDE YER ALAN İFADELER YATIRIM TAVSİYESİ DEĞİLDİR."} +{"url": "https://www.tinnhanhchungkhoan.vn/tien-re-co-quay-lai-chung-khoan-sang-cua-but-pha-post388709.html", "title": "Tiền rẻ có quay lại , chứng khoán sáng cửa bứt phá ? ", "publish_date": "2026-04-12T14:39:07Z", "full_text": "(ĐTCK) Mặt bằng lãi suất hạ nhiệt cùng kỳ vọng nâng hạng thị trường đang kích hoạt dòng tiền quay lại chứng khoán. Trong bối cảnh đó, các nhóm xây dựng, vật liệu, bán lẻ và ngân hàng nổi lên như những điểm đến tiềm năng của dòng vốn trong giai đoạn tới.\n\nTrong bối cảnh thị trường đang dao động trong vùng sideway và chịu tác động đan xen từ thông tin nâng hạng cũng như yếu tố địa chính trị, liệu VN-Index trong tuần tới sẽ tiếp tục mở rộng nhịp hồi hướng tới vùng 1.800 điểm hay quay lại kiểm định vùng hỗ trợ quanh 1.700–1.720 điểm để tích lũy lại trước khi xác lập xu hướng rõ ràng hơn, theo ông/bà?\n\nÔng Lâm Gia Khang, Trưởng bộ phận phân tích thị trường, CTCK Vietinbank (CTS)\n\nVới việc FTSE đã chính thức công nhận thị trường đạt tiêu chuẩn của thị trường mới nổi, Chính phủ tiếp tục giữ nguyên mục tiêu tăng trưởng GDP năm 2026 ở mức 10%, dòng tiền bắt đầu chảy mạnh trở lại vào thị trường với thanh khoản trung bình mỗi phiên đạt trên 24.000 tỷ đồng, dự kiến chỉ số VN-Index sẽ tiếp tục duy trì xu hướng tăng điểm và áp sát kháng cự 1.800 điểm trong tuần tới, dù vẫn chịu tác động từ yếu tố bất định từ kết quả đàm phán tại Islamabad giữa Mỹ và Iran liên quan đến các vấn đề eo biển Hormuz, chương trình hạt nhân Iran, sự hiện diện của các căn cứ quân sự của Mỹ ở khu vực Trung Đông.\n\nÔng Nguyễn Thế Minh, Giám đốc Khối Nghiên cứu và phát triển - Công ty Chứng khoán Yuanta Việt Nam\n\nTôi cho rằng chỉ số VN-Index có thể sẽ hướng tới thử thách mức 1.800 điểm trong tuần giao dịch tới, nhưng thị trường có thể xuất hiện nhịp điều chỉnh khi chạm mức kháng cự này. Nhìn chung, rủi ro địa chính trị đã giảm đáng kể và xu hướng ngắn hạn vẫn đang trong xu hướng tăng cho nên tôi kỳ vọng thị trường sẽ duy trì đà tăng trong tuần giao dịch tới, nhưng đà tăng này sẽ di chuyển theo hướng zig zag với các phiên tăng giảm đan xen.\n\nBà Châu Thiên Trúc Quỳnh - Giám đốc Điều hành khối Tư vấn đầu tư Vietcap\n\nQuan điểm kỹ thuật: Diễn biến hiện tại cho thấy lực mua tại vùng giá cao vẫn duy trì trên thị trường, tập trung rõ hơn ở nhóm có tính dẫn dắt cao là Ngân hàng. Do đó, chúng tôi cho rằng trở ngại tại đường MA50 (1.750 điểm) mang tính ngắn hạn, tuy nhiên, với những diễn biến của tình hình chính trị thế giới, nếu nhịp điều chỉnh xuất hiện trong phiên 13/04, nhiều khả năng sẽ được giới hạn bởi vùng hỗ trợ gần tại 1.725 điểm trước khi xác lập xu hướng rõ ràng hơn.\n\nÔng Trần Thái Bình - CFA, Giám đốc Cấp cao Khối Phân tích OCBS\n\nTrong bối cảnh thị trường đang tích lũy trong biên độ hẹp với các yếu tố địa chính trị còn khó lường, tôi nghiêng về kịch bản VN-Index sẽ cần những nhịp kiểm định quanh vùng hiện tại trước khi có đủ động lực chinh phục các ngưỡng cao hơn. Thị trường sẽ phân hóa mạnh hơn khi bước vào mùa báo cáo quý I sắp đến. Việc hướng tới mốc trên 1.800 điểm là hoàn toàn khả thi trong trung hạn nhờ kỳ vọng nâng hạng.\n\nTuy nhiên, trong ngắn hạn, sẽ xuất hiện nhiều nhịp rung lắc để thay máu dòng tiền sẽ giúp xu hướng tăng trưởng bền vững hơn. Sự thận trọng ở đây là cần thiết để hấp thụ hết các áp lực chốt lời và những phản ứng tâm lý từ tin tức quốc tế. Nói cách khác, giai đoạn này thiên về tích lũy sức mạnh hơn là bứt phá ngay lập tức.\n\nVới kỳ vọng nâng hạng thị trường và dòng vốn ETF có thể lên tới hàng tỷ USD trong giai đoạn tới, đâu sẽ là nhóm ngành thực sự hưởng lợi bền vững, thay vì chỉ tăng theo hiệu ứng tâm lý ngắn hạn?\n\nÔng Lâm Gia Khang, Trưởng bộ phận phân tích thị trường, CTCK Vietinbank (CTS)\n\nĐể đạt được mục tiêu tăng trưởng GDP ở mức 10% trong khi hoạt động xuất khẩu - vốn là một trong ba lực đẩy chính của nền kinh tế tiếp tục bị ảnh hưởng tiêu cực bởi xu hướng bảo hộ thị trường nội địa của các quốc gia cùng tình hình địa chính trị phức tạp, hoạt động đầu tư công dự kiến sẽ tích cực được đẩy mạnh trong phần còn lại của năm 2026. Điều này sẽ mở ra nhiều cơ hội thuận lợi cho các doanh nghiệp ngành xây dựng hạ tầng và vật liệu xây dựng như đá, xi măng, nhựa đường, thép.\n\nNgoài ra, nhóm cổ phiếu bán lẻ cũng là nhóm có nhiều kỳ vọng khi Chính phủ nhiều khả năng sẽ thực hiện nhiều chính sách kích cầu nội địa nhằm bù đắp dư địa tăng trưởng bị co hẹp lại của hoạt động xuất khẩu. Theo dữ liệu từ Tổng Cục Thống kê, tổng mức bán lẻ hàng hóa và doanh thu dịch vụ tiêu dùng trong quý I/2026 tăng 10,9% so với cùng kỳ năm trước.\n\nBên cạnh đó, nhà đầu tư cũng có thể cân nhắc giải ngân vào nhóm cổ phiếu ngân hàng khi đây là kênh dẫn vốn quan trọng góp phần đẩy nhanh tiến độ các dự án đầu tư công. Bên cạnh đó, riêng các ngân hàng quốc doanh cũng dự kiến sẽ tiến hành bơm 1 triệu tỷ đồng ra nền kinh tế trong năm 2026 để thúc đẩy tăng trưởng.\n\nÔng Nguyễn Thế Minh, Giám đốc Khối Nghiên cứu và phát triển - Công ty Chứng khoán Yuanta Việt Nam\n\nKhi TTCK Việt Nam được nâng hạng thì các cổ phiếu có quy mô vốn hóa càng lớn và có tỷ lệ room ngoại còn lại càng cao thì càng hưởng lợi. Do đó, các nhà đầu tư có thể nên chú ý vào các nhóm cổ phiếu vốn hóa lớn, đặc biệt trong VN30 để đầu tư theo chu kỳ nâng hạng. Tuy nhiên, tôi lưu ý hiệu ứng nâng hạng thị trường thường chỉ tác động tích cực trong thời gian ngắn hạn và sau đó thị trường sẽ thường chịu tác động bởi các nền tảng vĩ mô và cơ bản.\n\nBà Châu Thiên Trúc Quỳnh - Giám đốc Điều hành khối Tư vấn đầu tư Vietcap\n\nViệc nâng hạng của thị trường sẽ có hiệu lực từ thứ Hai, ngày 21/09/2026. Các quỹ chỉ số sẽ thực hiện mua cổ phiếu Việt Nam theo lộ trình 4 đợt như sau: 21/09/2026 (tỷ trọng 10%), 22/03/2027 (20%), 21/06/2027 (35%) và 20/09/2027 (35%). Các cổ phiếu Việt Nam đáp ứng các tiêu chí để có thể được đưa vào chỉ số FTSE Global All Cap bao gồm: HPG, VCB, BID, VHM, VIC, MSN, SAB, FPT, VNM, SSI, DPM, KBC, HUT, SHB, DIG, EIB, DXG, KDH, VIX, VND, PDR, DGC, NVL, VJC, VCI, VRE, GEX, FRT, GEE, BSR, KDC, STB. FTSE Russell sàng lọc các cổ phiếu dựa trên nhiều tiêu chí như tỷ lệ sở hữu nhà đầu tư nước ngoài còn lại, quy mô vốn hóa, thanh khoản và tỷ lệ cổ phiếu tự do chuyển nhượng (free float).\n\nDựa trên những yếu tố đó cho thấy danh mục chủ yếu nhóm cổ phiếu trong VN30, nhóm mid- cap mạnh. Nếu xét về phân loại ngành thì là ngân hàng, tiêu dùng bán lẻ, bất động sản, chứng khoán, sản xuất… và thời gian giải ngân còn khá xa. Do vậy, chúng ta nên hướng tới những cổ phiếu còn nền tảng vững chắc , thay vì hiệu ứng tâm lý ngắn hạn.\n\nÔng Trần Thái Bình - CFA, Giám đốc Cấp cao Khối Phân tích OCBS\n\nKhi dòng vốn ETF và các quỹ ngoại quy mô lớn đổ vào, họ sẽ ưu tiên các tiêu chí về vốn hóa, thanh khoản và quản trị doanh nghiệp. Thay vì các nhóm tăng nóng theo tin đồn, hai nhóm ngành tiêu biểu sẽ hưởng lợi thực chất bao gồm nhóm Ngân hàng với tỷ trọng vốn hóa lớn nhất, đây vẫn là nhóm chiếm tỷ trọng lớn trong chỉ số và có tính đại diện cao cho nền kinh tế. Những ngân hàng có hệ số CAR cao và tỷ lệ nợ xấu được kiểm soát tốt sẽ là lựa chọn hàng đầu. Nhóm chứng khoán được hưởng lợi trực tiếp từ thanh khoản thị trường gia tăng và sự mở rộng của nhà đầu tư nước ngoài.\n\nNgoài ra, các doanh nghiệp đầu ngành có free-float lớn trong các lĩnh vực như bất động sản, bán lẻ, tiêu dùng, hạ tầng hoặc công nghệ sẽ được ưu tiên lựa chọn. Những nhóm này không chỉ tăng theo tâm lý mà sẽ được khối ngoại mua ròng thực chất vì đáp ứng tiêu chí FTSE về vốn hóa, thanh khoản và tỷ lệ tự do chuyển nhượng. Ngược lại, các cổ phiếu nhỏ, thanh khoản kém chỉ hưởng lợi ngắn hạn và dễ đảo chiều mạnh.\n\nTrong góc nhìn của ông/bà, việc mặt bằng lãi suất huy động giảm và định hướng nới lỏng chính sách tiền tệ có đủ để kích hoạt dòng tiền quay lại thị trường chứng khoán trong ngắn hạn, đặc biệt với các nhóm nhạy cảm như bất động sản và chứng khoán?\n\nÔng Lâm Gia Khang, Trưởng bộ phận phân tích thị trường, CTCK Vietinbank (CTS)\n\nViệc mặt bằng lãi suất huy động hạ nhiệt sẽ khiến hoạt động gửi tiền tại các ngân hàng trở nên kém hấp dẫn hơn, qua đó kích hoạt dòng tiền chảy mạnh hơn vào các kênh đầu tư có mức độ rủi ro cao hơn như bất động sản và chứng khoán. Bên cạnh đó, định hướng nới lỏng chính sách tiền tệ cũng sẽ tạo điều kiện thuận lợi cho các doanh nghiệp niêm yết cải thiện hoạt động kinh doanh, giúp định giá thị trường trở nên hấp dẫn hơn và thu hút sự tham gia mạnh của dòng vốn đầu tư trong nước và quốc tế.\n\nÔng Nguyễn Thế Minh, Giám đốc Khối Nghiên cứu và phát triển - Công ty Chứng khoán Yuanta Việt Nam\n\nThanh khoản hệ thống đã hồi phục trở lại, cùng với đó là rủi ro lạm phát có thể sớm hạ nhiệt dần khi giá dầu cũng đã bắt đầu bước vào xu hướng giảm ngắn hạn cho nên tôi kỳ vọng lãi suất có thể sớm hạ nhiệt trong thời gian tới, điều này có thể tác động tích cực lên các nhóm Ngân hàng, chứng khoán và bất động sản trong bối cảnh các nhóm cổ phiếu này đang có mức định giá thấp.\n\nBà Châu Thiên Trúc Quỳnh - Giám đốc Điều hành khối Tư vấn đầu tư Vietcap\n\nViệc mặt bằng lãi suất huy động giảm và định hướng nới lỏng chính sách sẽ giúp tâm lý thị trường bình tĩnh trở lại, ổn định được xu hướng, không bán tháo các cổ phiếu nhóm bất động sản, chứng khoán cũng như ổn định chính sách margin (lãi suất đầu ra) của các công ty chứng khoán.\n\nTuy nhiên, để kích hoạt dòng tiền quay trở lại với các nhóm ngành trên hoặc với thị trường chứng khoán ngay trong ngắn hạn cần thêm thời gian thẩm thấu chính sách cũng như nhà đầu tư gửi tiết kiệm với lãi suất cao trước đó không thể rút ra nhanh được để chuyển đổi.\n\nÔng Trần Thái Bình - CFA, Giám đốc Cấp cao Khối Phân tích OCBS\n\nViệc mặt bằng lãi suất huy động duy trì ở mức thấp và định hướng chính sách tiền tệ theo hướng hỗ trợ tăng trưởng rõ ràng là yếu tố tích cực đối với thị trường chứng khoán. Khi chi phí vốn giảm, dòng tiền có xu hướng tìm kiếm kênh sinh lời cao hơn, và chứng khoán thường là một trong những lựa chọn tự nhiên. Khi lãi suất tiết kiệm giảm, khoảng cách giữa lãi suất huy động và lợi suất cổ phiếu sẽ thu hẹp, khiến dòng tiền từ gửi tiết kiệm và trái phiếu chuyển sang các kênh khác trong đó có kênh chứng khoán.\n\nNhóm bất động sản và chứng khoán sẽ là những nhóm phản ứng nhanh nhất. Tuy nhiên, tôi thận trọng lưu ý: hiệu ứng này cần thời gian hàng tháng để lan tỏa, và chỉ thực sự mạnh khi kinh tế tăng trưởng bền vững và lạm phát được kiểm soát tốt. Nếu địa chính trị bất ổn, dòng tiền có thể vẫn chọn phòng thủ thay vì đổ mạnh vào rủi ro cao. Nhà đầu tư còn cân nhắc nhiều yếu tố khác như triển vọng lợi nhuận doanh nghiệp, rủi ro toàn cầu và tâm lý thị trường.\n\nTrong ngắn hạn, các nhóm ngành này có thể phản ứng khá nhạy với thông tin lãi suất, nhưng để hình thành một xu hướng tăng bền vững vẫn cần nhiều yếu tố kết hợp và hỗ trợ.\n\nTrong bối cảnh thị trường chưa hình thành xu hướng rõ ràng và vẫn vận động sideway, nhà đầu tư nên ưu tiên chiến lược trading ngắn hạn theo nhịp điều chỉnh hay tích lũy trung hạn ở các cổ phiếu có nền tảng tốt và định giá hấp dẫn, theo ông/bà?\n\nÔng Lâm Gia Khang, Trưởng bộ phận phân tích thị trường, CTCK Vietinbank (CTS)\n\nNhà đầu tư ngắn hạn được khuyến nghị tận dụng diễn biến điều chỉnh và rung lắc của thị trường để tiến hành giải ngân vào các cổ phiếu thuộc các nhóm ngành được kỳ vọng tiếp tục duy trì đà tăng trưởng đã được đề cập ở trên. Việc giải ngân nên được tiến hành từng phần và đòi hỏi tuân thủ chặt chẽ kỷ luật giao dịch, tiến hành cắt lỗ khi thị giá giảm hơn 7% kể từ vùng giá tiến hành mua vào.\n\nÔng Nguyễn Thế Minh, Giám đốc Khối Nghiên cứu và phát triển - Công ty Chứng khoán Yuanta Việt Nam\n\nTôi cho rằng nhà đầu tư có thể tận dụng nhịp điều chỉnh ngắn hạn để mua vào cho các chiến lược trading ngắn hạn vì tôi đánh giá cơ hội ngắn hạn đang gia tăng. Đồng thời, xu hướng trong dài hạn vẫn đang tăng cho nên các nhà đầu tư có thể tích lũy trong nhịp điều chỉnh để gia tăng tỷ trọng cổ phiếu.\n\nÔng Trần Thái Bình - CFA, Giám đốc Cấp cao Khối Phân tích OCBS\n\nTrong bối cảnh thị trường chưa xác lập xu hướng rõ ràng, tôi cho rằng chiến lược linh hoạt là phù hợp nhất. Nhà đầu tư ngắn hạn có thể tận dụng các nhịp điều chỉnh về vùng hỗ trợ để trading, đặc biệt ở những cổ phiếu có chất lượng tốt đang hình thành nền giá tích lũy. Song song đó, với tầm nhìn trung hạn, đây cũng là giai đoạn phù hợp để tích lũy từng phần các cổ phiếu có nền tảng cơ bản tốt, định giá hợp lý và triển vọng tăng trưởng rõ ràng.\n\nKhi thị trường bước sang chu kỳ tăng mới - đặc biệt nếu câu chuyện nâng hạng trở thành hiện thực - những cổ phiếu này thường là nhóm dẫn dắt xu hướng thay vì chỉ tăng theo hiệu ứng tâm lý ngắn hạn. Thị trường hiện nay giống như một chiếc lò xo đang được nén lại: có thể chưa bật mạnh ngay, nhưng càng tích lũy đủ lâu thì khi xu hướng hình thành, biên độ tăng trưởng thường sẽ đáng kể."} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Full_text/full_text_macro_geopolitics_risk.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Full_text/full_text_macro_geopolitics_risk.jsonl new file mode 100644 index 0000000..4d04831 --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Full_text/full_text_macro_geopolitics_risk.jsonl @@ -0,0 +1,5 @@ +{"url": "https://www.readingchronicle.co.uk/news/national/26014084.russia-ukraine-trade-blame-violating-orthodox-easter-ceasefire/", "title": "Russia and Ukraine trade blame for violating Orthodox Easter ceasefire", "publish_date": "2026-04-12T14:41:52Z", "full_text": "Russian President Vladimir Putin on Thursday called a 32-hour ceasefire over the Orthodox Easter weekend, ordering Russian forces to halt hostilities from 4pm on Saturday until the end of Sunday.\n\nUkrainian President Volodymyr Zelensky promised to abide by the ceasefire, but warned there would be a swift military response to any violations.\n\nThe General Staff of Ukraine’s Armed Forces said in a statement on Sunday it had recorded 2,299 ceasefire violations by 7am local time, including assaults, shelling and small drone launches.\n\nAn Easter bread with a candle in it was found covered by dust by Ukrainian emergency services following a Russian drone strike on Sumy on Saturday (Ukrainian Emergency Service/AP)\n\nIt said the use of long-range drones, missiles, or guided bombs had not been reported.\n\nA Ukrainian military officer had said on Saturday that Russian forces had continued to attack their positions.\n\nRussia’s Defence Ministry, meanwhile, said on Sunday it had recorded 1,971 ceasefire violations by Ukrainian forces, including drone strikes on Russia’s Kursk and Belgorod regions that injured civilians.\n\nPrevious attempts to secure ceasefires have had little or no impact, with the two sides blaming each other for violations.\n\nMr Putin unilaterally declared a 30-hour ceasefire last Easter, but each side accused the other of breaking it."} +{"url": "https://www.bordertelegraph.com/news/national/26014105.starmer-urges-us-iran-to-find-way-through-peace-talks-fail/", "title": "Starmer urges US and Iran to find a way through after peace talks fail", "publish_date": "2026-04-12T14:41:52Z", "full_text": "The Prime Minister also called for the fragile ceasefire to continue and warned against any further escalation.\n\nBut the US president cast fresh uncertainty over any hope of a fast resolution to the conflict as he lambasted Iran for failing to release its grip on the vital oil and gas shipping lane and commit to giving up its nuclear ambitions.\n\nIn a lengthy post on his Truth Social platform after the peace talks ended without a deal, Mr Trump said the US would “immediately” start “BLOCKADING any and all Ships trying to enter, or leave, the Strait of Hormuz”.\n\nHe added that the US navy would also “seek and interdict every vessel in International Waters that has paid a toll to Iran. No one who pays an illegal toll will have safe passage on the high seas”.\n\nHe added, without elaborating: “Other Countries will be involved with this Blockade.”\n\nHe said talks in Pakistan involving US Vice-President JD Vance “went well, most points were agreed to, but the only point that really mattered, NUCLEAR, was not”.\n\nSir Keir discussed Washington and Tehran’s negotiations with the Sultan of Oman after the two sides’ 21-hour session ended without an agreement in the early hours of Sunday.\n\nIn a readout of Sir Keir’s call with His Majesty Sultan Haitham bin Tarik al Said, a Downing Street spokeswoman said: “They discussed the peace talks held in Pakistan over the weekend and urged both sides to find a way through.\n\n(PA Graphics)\n\n“It was vital there was a continuation of the ceasefire, and that all parties avoided any further escalation, the leaders agreed.”\n\nThey also discussed efforts to reopen the Strait of Hormuz, which has been throttled by Iran, sending energy prices soaring.\n\nBritain will host further talks on reopening the maritime pinch-point with a coalition of countries next week.\n\nAccording to the call readout: “His majesty updated on the situation in the Strait of Hormuz, and the Prime Minister thanked him for Oman’s efforts to rescue sailors from vessels in distress in the region.\n\n“Reflecting on international efforts to co-ordinate safe passage for shipping in the region, the Prime Minister said that following meetings convened by the Foreign Secretary and British military planners, partners continued to work towards restoring freedom of navigation for the long term.”\n\nThe meeting next week is expected to look for ways to support a sustainable end to the conflict and focus on increasing international diplomatic pressure on Iran to reopen the strait, according to an official with knowledge of the planning.\n\nThis includes exploring co-ordinated economic and political measures, such as sanctions, and working with the International Maritime Organisation to secure the release of thousands of ships and sailors trapped in the strait.\n\nWes Streeting said ministers have learned to draw a distinction between what Donald Trump ‘says and what he does’ (Jeff Overs/BBC)\n\nIt would be the third meeting hosted by Britain regarding the issue this month, following a virtual meeting of more than 40 nations convened by the Foreign Secretary and a gathering of allied military officers.\n\nThe Prime Minister visited allies in the Gulf this week for talks on how to support what he described as a “fragile” ceasefire.\n\nGulf nations have borne the brunt of Tehran’s retaliation for the US-Israeli campaign against it, with thousands of Iranian missiles and drones targeting US military sites and energy infrastructure there.\n\nMr Trump agreed a two-week ceasefire earlier this week, with the reopening of the Strait of Hormuz a key condition, shortly after warning Iran that “a whole civilisation will die” if it did not meet his demands.\n\nHealth Secretary Wes Streeting criticised Mr Trump’s “incendiary, provocative, outrageous” language, and said ministers had learned to draw a distinction between what the American leader “says and what he does”.\n\nDisagreements over the Iran war, Greenland and the Chagos Islands, as well as the US president’s repeated jibes against the UK, had “undoubtedly strained” UK-US relations, the senior minister added."} +{"url": "https://article.wn.com/view/2026/04/12/China_to_reinstate_some_Taiwan_ties_after_opposition_leaders/", "title": "China to reinstate some Taiwan ties after opposition leader visit", "publish_date": "2026-04-12T14:41:52Z", "full_text": "China said Sunday it would resume some suspended ties with Taiwan, including direct flights and imports of aquaculture products, following a visit by a Beijing-friendly opposition ...... read full story"} +{"url": "https://www.muensterschezeitung.de/nachrichten/schlagzeilen/ukraine-krieg-tausende-verstoesse-bei-osterwaffenruhe-beklagt-3530354", "title": "Ukraine - Krieg : Tausende Verste bei Osterwaffenruhe beklagt", "publish_date": "2026-04-12T14:41:52Z", "full_text": "Die von Kremlchef Putin angeordnete Waffenruhe zum orthodoxen Osterfest ist erwartungsgemäß brüchig. Aber zumindest sind Hunderte Kriegsgefangene wieder in Freiheit. Wie geht es im Krieg weiter?\n\nKremlchef Wladimir Putin hat zum orthodoxen Osterfest eine Waffenruhe in seinem Angriffskrieg gegen die Ukraine angeordnet.\n\nDie Ukraine und Russland haben sich bei ihrer vereinbarten Waffenruhe zum orthodoxen Osterfest gegenseitig Tausende Verstöße vorgeworfen. Allerdings gab es anders als sonst nach Angaben des Generalstabs in Kiew keine Angriffe mit russischen Raketen und Gleitbomben und damit insgesamt auch weniger Opfer und Zerstörung als an üblichen Tagen des Moskauer Angriffskrieges. Russland wiederum verzeichnete ebenfalls keine ukrainischen Angriffe auf die für die Kriegswirtschaft wichtige Ölindustrie.\n\nKremlchef Wladimir Putin hatte verfügt, dass für 32 Stunden die Waffen bis Mitternacht (23.00 Uhr MESZ) am Sonntag schweigen sollen, damit die Menschen in Russland und in der Ukraine in Ruhe Ostern feiern können. Die orthodoxen Christen feiern in diesem Jahr eine Woche nach den westlichen Kirchen Ostern.\n\nEinen echten Osterfrieden gab es zwar nicht. Allerdings tauschten die Kriegsparteien kurz vor Beginn der Feierlichkeiten Hunderte Gefangene aus - jeweils 175 Militärangehörige und 7 Zivilisten. Beide Seiten kündigten an, dass die immer wieder vollzogenen Austausche fortgesetzt werden sollen.\n\nGespannte Lage an der Front\n\nDie Lage an der Front blieb indes gespannt. Die Kriegsparteien hatten bereits im vorher ihr Misstrauen gegenüber der geplanten Waffenruhe bekundet, weil es schon bei vorübergehenden Feuerpausen in der Vergangenheit immer wieder Verstöße gab. Deshalb drohten beide Seiten wiederholt, auf Angriffe des Gegners zu reagieren.\n\nDer ukrainische Generalstab registrierte 2.299 Verletzungen der seit Samstag geltenden Waffenruhe. Konkret gab es demnach unter anderem 479 Fälle von Beschuss und rund 1.800 Angriffe mit kleineren Drohnen. «Schläge mit Raketen, Gleitbomben und Drohnen vom Typ Shahed gab es nicht», teilte der Generalstab weiter mit.\n\nVerletzte im Gebiet Charkiw\n\nAuch die ukrainischen Luftstreitkräfte bestätigten, dass es für sie eine Pause von 18 Stunden gegeben habe. Am Morgen habe es allerdings im Gebiet Sumy einen für die Flugabwehr relevanten russischen Drohnenangriff gegeben. Im Gebiet Charkiw im Osten der Ukraine meldeten die Behörden nach einem russischen Drohnenangriff während der Waffenruhe zwei Verletzte in einem Lebensmittelgeschäft.\n\nKurz vor Beginn des orthodoxen Osterfests tauschen die Ukraine und Russland erneut Gefangene aus. Foto: Efrem Lukatsky/AP/dpa\n\nDas russische Verteidigungsministerium warf der Ukraine gezielte Angriffe vor. «Insgesamt wurden im Zeitraum vom 11. April, 16.00 Uhr, bis zum 12. April, 8.00 Uhr, 1.971 Verstöße gegen den Waffenstillstand durch Einheiten der ukrainischen Streitkräfte registriert», teilte das Ministerium in Moskau mit. Die ukrainische Armee habe trotz des Osterfriedens russische Stellungen unter anderem im Raum Pokrowsk im Gebiet Donezk sowie im Gebiet Dnipropetrowsk angegriffen. «Alle Attacken wurden abgewehrt», hieß es.\n\nSelenskyj scheitert mit Vorschlag zur Verlängerung der Waffenruhe\n\nSelenskyj erneuerte auch seinen Vorschlag, aus der Waffenruhe einen dauerhaften Waffenstillstand zu machen. Kremlsprecher Dmitri Peskow bekräftige im russischen Staatsfernsehen, dass die Kampfhandlungen nach Ablauf wieder aufgenommen würden, wenn Selenskyj keine Entscheidung treffe, sich auf die russischen Bedingungen für einen Frieden einzulassen.\n\nPeskow erklärte, dass Russland einen «nachhaltigen Frieden» und keine einfache Waffenruhe wolle. Er meint damit, dass Kiew seine Truppen aus dem Gebiet Donezk zurückziehen solle, wo nach seiner Darstellung noch etwa 18 Prozent unter ukrainischer Kontrolle sind. Die Ukraine kontrolliert dort ihre strategisch wichtigen Städte Kramatorsk und Slowjansk. Selenskyj lehnt es kategorisch ab, solche Gebietsabtretungen als Geschenk an die russischen Besatzer zu machen.\n\nSelenskyj würdigt Standhaftigkeit der Ukrainer\n\nIn seiner Osterbotschaft würdigte Selenskyj den Mut und die Standhaftigkeit seiner Landsleute. Das Land habe gerade den schwersten Winter seiner Geschichte überstanden, sagte er mit Blick. «Wir vertrauen nicht nur auf die himmlischen Mächte, sondern auch auf unsere Sicherheits- und Verteidigungskräfte», sagte Selenskyj.\n\nDer ukrainsche Präsident Wolodymyr Selenskyj und seine Frau Olena würdigten zum orthodoxen Osterfest die Standhaftigkeit ihrer Landsleute im Kampf gegen den russischen Angriffskrieg. (Archivbild) Foto: Präsidialamt der Ukraine/ZUMA Wire/dpa\n\nDie Ukraine verteidige sich unerschütterlich. «Damit auf das fünfte Osterfest in Kriegszeiten das erste friedliche Osterfest folgt. In unserem ganzen Land, für alle unsere Menschen», sagte Selenskyj, der mit seiner Frau Olena in der Sophienkathedrale in Kiew die Videobotschaft aufnahm.\n\nKämpfe gehen weiter - Treffen im «Ramstein»-Format geplant\n\nRussland hat bereits angekündigt, die Kampfhandlungen nach Ablauf der Waffenruhe wieder aufzunehmen - nach Darstellung von Kremlsprecher Peskow bis Moskaus Kriegsziele erreicht sind. Die Verhandlungen unter US-Vermittlung über eine Beendigung des Krieges pausieren nach seinen Angaben, weil die Unterhändler Washingtons im Iran-Krieg beschäftigt seien.\n\nDer ukrainische Verteidigungsminister Mychajlo Fedorow kündigte nach einem Telefonat mit seinem deutschen Amtskollegen Boris Pistorius (SPD) für kommenden Mittwoch ein neues Treffen im sogenannten Ramstein-Format an. Bei den Gesprächen der Ukraine-Kontaktgruppe solle es darum gehen, wie Russland zu einem Frieden gezwungen werden könne, teilte das Ministerium in Kiew mit."} +{"url": "https://www.diariocritico.com/internacional/trump-anuncia-bloqueo-estrecho-ormuz-paguen-a-iran", "title": "Trump anuncia un bloqueo del Estrecho de Ormuz para todos aquellos que paguen a Irán", "publish_date": "2026-04-12T14:41:52Z", "full_text": "Trump anuncia un bloqueo del Estrecho de Ormuz para todos aquellos que paguen a Irán\n\ndomingo 12 de abril de 2026 , 15:42h\n\nEl presidente de Estados Unidos, Donald Trump, ha informado este domingo que ha ordenado a la Armada estadounidense el inicio de un cierre perimetral del estrecho de Ormuz, en estos momentos bajo control de Irán, y ha dejado claro que va a interceptar \"en aguas internacionales\" a cualquier buque que decida pagar a Irán para cruzar este estratégico paso.\n\n\"Con efecto inmediato la Armada de Estados Unidos (...) comenzará el proceso para bloquear todos y cada uno de los buques que intenten entrar o salir del estrecho de Ormuz\", ha indicado Trump en un mensaje publicado en redes sociales en la que ha sido su primera reacción al fracaso de las conversaciones de este sábado entre Estados Unidos e Irán en Islamabad (Pakistán).\n\nTrump ha cargado contra lo que considera la \"extorsión mundial\" impuesta por las autoridades iraníes con el cierre de Ormuz y ha alertado al resto del mundo de que los buques de guerra estadounidenses \"buscarán e interceptarán cualquier barco en aguas internacionales que haya pagado un peaje a Irán\".\n\nPutin respalda a Irán tras el fracaso de las negociaciones\n\nPor otra parte, el presidente de Rusia, Vladimir Putin, ha mantenido este domingo una charla telefónica con su homólogo iraní, Masud Pezeshkian, en la que le ha mandado todo el respaldo de Moscú ante el fracaso de las conversaciones de paz mantenidas en la víspera entre las delegaciones de alto nivel entre Estados Unidos e Irán.\n\nIrán y Rusia habían firmado el año pasado un nuevo acuerdo estratégico de defensa que se había traducido, por ejemplo, en las nuevas partidas de drones iraníes al Ejército ruso en medio de la guerra de Ucrania.\n\nDurante su conversación con Pezeshkian, Putin ha \"subrayado además la disposición de Moscú para seguir facilitando la búsqueda de una solución política y diplomática al conflicto\". \"Con este fin, Rusia mantendrá contactos activos con todos sus socios en la región\", ha asegurado el presidente ruso antes de volver a afirmar \"el compromiso mutuo de seguir fortaleciendo las relaciones de buena vecindad\"."} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Full_text/full_text_macro_inflation_employment.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Full_text/full_text_macro_inflation_employment.jsonl new file mode 100644 index 0000000..8270a08 --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Full_text/full_text_macro_inflation_employment.jsonl @@ -0,0 +1,8 @@ +{"url": "https://www.ringblad.no/enighet-med-fellesforbundet-i-frontfagsoppgjoret-parat-fortsatt-i-mekling/s/5-45-2209025", "title": "Lønnsforhandlinger , Arbeidsliv | Enighet med Fellesforbundet i frontfagsoppgjøret – Parat fortsatt i mekling", "publish_date": "2026-04-12T14:40:26Z", "full_text": "– Dette lønnsoppgjøret sikrer en solid forbedring for både økonomien, forutsigbarheten og tryggheten til norske arbeidsfolk, sier leder i Fellesforbundet Christian Justnes i en pressemelding.\n\nEtter å ha sittet 13 timer på overtid ble altså de enige. Det bekrefter også Riksmekleren på sin nettside.\n\nMen Parat sitter fortsatt i mekling.\n\n– Til tross for meldinger om avklaring for Fellesforbundet sitter Parat fortsatt ved meklerens bord. Utfallet for de 1242 medlemmene som er omfattet av oppgjøret, er foreløpig usikkert, skriver Parat i en pressemelding.\n\nEnighet\n\nFellesforbundet og Norsk Industri er enige om et generelt tillegg på 6,50 kroner, som gir alle en lønnsøkning på godt over 1000 kroner i måneden, står det i Fellesforbundets pressemelding.\n\nI tillegg har de lavest lønte på industrioverenskomsten fått ytterligere 4 kroner i tillegg. Partene er enige om en lønnsramme på 4,4 prosent.\n\nFellesforbundet hadde varslet streik for 33.237 medlemmer, men for disse er altså streiken avverget.\n\nMeklet på overtid\n\nTirsdag ble det brudd i den frivillige meklingen mellom Fellesforbundet, Parat og Norsk Industri. Siden onsdag har partene møttes til tvungen mekling på Riksmeklerens kontor.\n\nHovedkravene i årets forhandlinger besto av reallønnsvekst, forskuttering av sykepenger og en oppfølging av Industriens Kompetansefond for å sikre ansatte muligheter til faglig påfyll.\n\n– Etter flere år med kraftig prisstigning og høye renter er kravet om reallønnsvekst ufravikelig, uttalte Parats forhandlingsleder, Kjell Morten Aune, da det ble kjent at forhandlingene gikk til tvungen mekling.\n\n35.000 medlemmer\n\nFør enigheten ble det varslet at Fellesforbundet og Parat var villige til å ta ut til sammen nesten 35.000 medlemmer i streik, fordelt på over 1000 bedrifter.\n\nFellesforbundets leder Christian Justnes uttalte tidligere at forbundet ville ta ut nesten samtlige av sine medlemmer allerede i første uttak om det skulle bli streik.\n\nKun deler av forsvarsindustrien og bedrifter som produserer nødvendig sykehusutstyr var unntatt streikevarselet.\n\n(©NTB)"} +{"url": "https://www.moonofalabama.org/2026/04/war-on-iran-loser-tries-setting-terms-the-strange-idea-of-blockading-blockaders.html/comment-page-2", "title": "War On Iran : – Loser Tries Setting Terms – The Strange Idea Of Blockading Blockaders – Moon of Alabama", "publish_date": "2026-04-12T14:40:26Z", "full_text": "April 12, 2026\n\nWar On Iran: – Loser Tries Setting “Terms” – The Strange Idea Of Blockading Blockaders\n\nThe first round of talks between the U.S. and Iran has failed to achieve any progress.\n\nThe U.S. negotiators thoroughly misjudged their positions and tried to set terms (archived):\n\nMr. Vance said little about what took place during more than 21 hours of negotiations, suggesting he had handed the Iranians a take-it-or-leave-it proposal to forever terminate their nuclear program, and they left it.\n\n“We’ve made very clear what our red lines are,” Mr. Vance told reporters, “what things we’re willing to accommodate them on.” He added, “They have chosen not to accept our terms.”\n\nThe U.S. has so far lost the war. None of its war aims has been achieved. Its attempts to steal Iran’s enriched Uranium ended with the biggest air force losses since the Vietnam War era. It is not in a position to set any terms:\n\nIn that respect, this negotiation appears to have differed little from the one that ended in deadlock in Geneva in late February, … Mr. Trump’s chief leverage now comes in his ability to threaten to resume major combat operations. After all, the fragile two-week cease-fire ends on April 21. But while the threat of resuming combat operations may be invoked in coming days, it not a particularly viable political choice for Mr. Trump — and the Iranians know it. Mr. Trump declared the cease-fire last week in large part to stem the pain from the loss of 20 percent of the world’s oil supplies, which was sending the price of gasoline soaring, creating shortages of fertilizer and, among other critical supplies, helium for the production of semiconductors. Markets rose on the prospect of an agreement, even an incomplete or unsatisfactory one. Should the war resume, the markets would likely decline, the shortages would worsen and inflation — already up to 3.3 percent — would almost inevitably rise. And that leaves the most urgent issue: the reopening of the Strait of Hormuz.\n\nAfter the end of the negotiations a tweet by Donald Trump pointed to a piece which asserts that his best next move to reopen the Strait of Hormuz is to blockade Iran:\n\nThe Trump card the president holds if Iran won’t bend: a naval blockade: https://justthenews.com/government/sec…\n\n(TS: 12 Apr 00:16 ET)​​​‍​​‌‍​​‌‍​​​​​​​‌‍​​​​‌‍​​​​​​​​​‌‍​​​​​​​​​​‌‍​​​​​​​​‌‍​​​​​​​​​​‌‍​​​​​​​​​‌‍​​​​​‌‍​‌‍​​​​​​‌‍​​​​‌‍​​​​​‌‍​​​​​​​​​​‌‍​​​​​​​‌‍​​​‌‍\n\nThe piece in question – The Trump card the president holds if Iran won’t bend: a naval blockade – is by John Solomon, a lawyer, and remarkable for its ignorance:\n\nIf Iran refuses to accept the final deal the United States offered Saturday, Trump could bomb Tehran back to the “Stone Ages” as he vowed. Or he might just reprise his successful blockade strategy to choke an already teetering Iranian economy and ratchet up diplomatic pressure on China and India by cutting them off one of their key sources of oil. Ironically, the massive USS Gerald Ford carrier that led the Venezuelan blockade is now in the Persian Gulf after a brief hiatus for repairs and crew rest after a deadly fire. And now it joins the USS Abraham Lincoln and other major naval assets.\n\nThe USS Gerald Ford, with broken toilets and a burned out laundry, is in the Mediterranean. It would have to pass the Suez Canal, the Bab al Mandeb Strait and the Strait of Hormuz to reach the Persian Gulf. Bab al Mandeb is controlled by the Houthi, Hormuz by Iran. Good luck passing either …\n\nThe idea of lifting Iran’s blockade of the Strait of Hormuz by blockading Iran is not from John Solomon but from the crazed neoconservative Jack Keene:\n\nThe idea of a naval blockade was first suggested last week by retired Gen. Jack Keane, one of the nation’s top military strategists. “If the war resumes and after we degrade Iran’s remaining military assets sufficiently, the US military could choose to occupy Kharg — or to destroy it,” Keane wrote it a New York Post column. “Alternatively, the US Navy could set up a blockade, shutting down Tehran’s export lifeline.” If we preserve Kharg’s infrastructure but take physical control, we’d have a chokehold over Iran’s oil and its economy,” he added. “That’s the ultimate leverage we’d need to seize its ‘nuclear dust,’ or stores of enriched uranium, and to eliminate its enrichment facilities.”\n\nKharg does not matter as much for Iranian exports as the DC nutters assume. During the eight years of the Iran-Iraq war Kharg was kept closed while oil exports from Iran continued to flow.\n\nAny attempt to blocked Iran would necessitate the use of force to prevent Indian, Chinese and Russian ships from entering Iranian harbors.\n\nIt would also mean less oil supplies for the global markets. Historically sea blockades take many months and even years to show effects. That is more time than Trump has to politically survive.\n\n—\n\nIt is costing a lot of time, and money, to run Moon of Alabama. Please consider to contribute."} +{"url": "https://www.thestandard.co.zw/business/article/200053827/zimbabwes-lenders-hedge-against-global-shocks", "title": "Zimbabwe lenders hedge against global shocks", "publish_date": "2026-04-12T14:40:26Z", "full_text": "CBZ Holdings Limited chairman Luxon Zembe said the domestic economy was expected to grow on the back of strong agricultural output, stable exchange rates and firm mineral prices.\n\nZIMBABWE’S banks are cautiously positioning for growth in 2026, buoyed by improving economic fundamentals and relative policy stability, while tightening risk management frameworks to shield themselves from currency pressures and global shocks.\n\nInsights from chairpersons and executives of major lenders, contained in financial statements for the year ended December 31, 2025, show a sector cautiously optimistic about the outlook.\n\nThe confidence is anchored on projected economic expansion of around 5% and improving stability in key macroeconomic indicators.\n\nCBZ Holdings Limited chairman Luxon Zembe said the domestic economy was expected to grow on the back of strong agricultural output, stable exchange rates and firm mineral prices.\n\n“These fundamentals are expected to provide a supportive platform for economic activity across key sectors,” Zembe said.\n\nHowever, he warned of risks emanating from global instability, particularly in the Gulf region and parts of Europe, adding that the group would rely on “prudent risk governance” and operational efficiencies to navigate the environment.\n\nBanks are aligning growth strategies with stronger capital positions, digital transformation and partnerships aimed at unlocking new revenue streams.\n\nAt TN CyberTech Bank, chief executive officer Tawanda Nyambirai said the institution would drive growth through a “hyperintegration strategy” focused on partnerships.\n\nAt TN CyberTech Bank, chief executive officer Tawanda Nyambirai\n\n“Looking ahead, the bank will continue to pursue its hyperintegration strategy, which seeks to grow its customer base, unlock new revenue streams and enhance shareholder value,” Nyambirai said.\n\nZB Financial Holdings Limited chairperson Agnes Makamure echoed the positive outlook.\n\n“Zimbabwe’s economy is projected to register positive growth of 5,0% in 2026,” she said.\n\nBut Makamure flagged significant downside risks, including foreign currency shortages, energy constraints and infrastructure gaps, alongside global headwinds such as geopolitical tensions and trade uncertainty.\n\nShe added that monetary authorities were likely to maintain tight policies to preserve stability, even as policymakers face the delicate task of balancing growth and inflation control.\n\nStability in inflation, interest rates and exchange rates is seen as critical to sustaining momentum after years of volatility that eroded confidence and disrupted financial intermediation.\n\nFBC Holdings Limited chairman Herbert Nkala said the group was encouraged by a stable operating environment and would leverage its diversified model to grow shareholder value.\n\nSimilarly, NMB Bank chairman Pearson Gowero said growth would be anchored on stable macroeconomic indicators and enhanced access to credit lines.\n\nHe added that the bank would prioritise operational efficiency and digital innovation to deliver more accessible and cost-effective financial services.\n\nAt First Capital Bank Zimbabwe, chairman Patrick Devenish said the institution had strengthened its capital base, liquidity and governance frameworks to support long-term growth.\n\n“The board is confident that First Capital Bank is strategically primed to navigate 2026 and the years beyond,” Devenish said, highlighting plans to invest in customer-centric innovation and enhance operational resilience.\n\nThe cautious optimism expressed by Zimbabwe’s financial leaders comes after a decade defined by extreme macroeconomic volatility.\n\nFor years, the sector struggled with hyperinflation and rapid currency depreciation that eroded capital bases and disrupted traditional financial intermediation.\n\nThe current focus on stability in inflation, interest rates, and exchange rates is seen as the critical foundation for sustaining the current momentum.\n\nThe projected 5% growth rate for 2026 is largely dependent on the performance of the “green” and “extractive” sectors.\n\nAs highlighted by CBZ, the recovery of agricultural productivity and the maintenance of high global prices for minerals such as gold and platinum remain the primary engines for the domestic economy.\n\nBanks are increasingly looking to anchor their growth on these stable indicators while expanding access to credit lines for these productive sectors.\n\nWith traditional brick-and-mortar models facing high overheads, the sector is undergoing a massive shift toward digital innovation.\n\nNMB Bank and First Capital Bank have both signaled that their 2026 strategies prioritise operational efficiency and “customer-centric innovation”.\n\nBy leveraging digital platforms, lenders aim to deliver more cost-effective services to a wider demographic, effectively bypass infrastructure gaps, and build “operational resilience” against local and global shocks."} +{"url": "http://www.newstribune.com/news/2026/apr/12/in-rural-missouri-immigration-crackdown-reaches-beyond-the-workplace/", "title": "In rural Missouri , immigration crackdown reaches beyond the workplace", "publish_date": "2026-04-12T14:40:26Z", "full_text": "Eliseo Affholter noticed a car following him, moving slowly as he walked through the streets of Milan, Missouri.\n\nWalking was his wind-down routine after work at a Kraft Heinz plant, where on Feb. 24, he had just finished a 12-hour overnight shift.\n\nAs he walked along East Grand Avenue, he saw flashing lights and vehicles lined up behind a stopped car, including patrol cars, an SUV and a pickup truck.\n\nAs Affholter stepped closer, he raised his phone to record.\n\nOne agent identified himself as an officer with U.S. Immigration and Customs Enforcement (ICE) and asked in Spanish what country Affholter was a citizen of. “From here,” Affholter replied.\n\n“Do you have papers? … Are you legally in the United States?” the agent asked, as two others stood nearby.\n\nHe stopped recording when an officer grabbed the phone from his hand, according to Affholter.\n\nWhen he asked why he was being detained, he said one agent responded in English: “We have the right to assume that you’re an illegal alien.”\n\nThat same day, federal immigration agents arrested three people in Milan, including two men from Senegal and another from Guatemala.\n\nDuring the past year, President Donald Trump’s deportation campaign has reached deep into agricultural regions that rely heavily on immigrant labor, including raids on farms and at meat-packing facilities.\n\nMilan, a north Missouri town of about 1,800, is home to a large Smithfield Foods pork processing plant. The Kraft Heinz plant, where Affholter worked, is 33 miles east in Kirksville.\n\nBut the February arrests in Milan did not take place inside the local meatpacking plant; they occurred along nearby roads and in residential areas where workers live and travel to and from their shifts.\n\n“They may not be going into the plant, but they’re in the community,” said Axel Fuentes, executive director of the Rural Community Workers Alliance, a worker advocacy organization that supports immigrant and refugee food industry workers in rural Missouri.\n\nAny immigration enforcement expansion within agricultural communities could have been aided by a September 2025 U.S. Supreme Court decision that broadened the scope of what agents can consider “reasonable suspicion.” Arrests appeared to increase after the decision, which allowed agents to consider a mix of factors, including apparent race or ethnicity, language or accent, location, and type of work, when making stops.\n\n“Some would say that the Supreme Court, in effect, encouraged ICE to engage in racial profiling in immigration enforcement,” said Kevin R. Johnson, a law professor at the University of California, Davis School of Law. “The truth of the matter is, I think that’s accurate.”\n\nJohnson said such practices have long been permitted under Supreme Court precedent. In a 1975 decision, United States v. Brignoni-Ponce, the Supreme Court ruled that immigration agents cannot stop someone based solely on “Mexican appearance,” but may consider it as one factor among others.\n\nAffholter, 36, is a U.S. citizen of Mayan descent, born in Guatemala. He arrived in the United States at 13 and was later adopted by a white American man. He has lived here for most of his life.\n\nIn a statement, an ICE spokesperson said Affholter “deliberately interfered” with a federal operation and “verbally” assaulted agents, prompting officers to question him about his immigration status and request identification.\n\n“I feel like I’m an animal, like I’m worthless,” Affholter said. “Like I don’t deserve to be here … because of my skin color, because of the language I speak. I speak Spanish, English and Mayan.” Affholter was referring to Mam, an Indigenous Mayan language spoken in the western highlands of Guatemala and the state of Chiapas, Mexico.\n\nAcross Milan, residents told Investigate Midwest that there is fear immigration enforcement will not only target workplaces but also neighborhoods and streets.\n\nIn the first months of his presidency, Trump sent federal agents to farms and agricultural operations, drawing backlash from some supporters who said the actions made it harder to hire undocumented workers, who make up 44 percent of all farm workers, according to U.S. government surveys.\n\nTrump announced a temporary pause on raids in the agriculture and meat-processing sectors, only to reverse the decision days later.\n\nBy early February 2026, more than 68,000 immigrants were being held in ICE detention nationwide, according to the Transactional Records Access Clearinghouse at Syracuse University. Most were arrested by ICE, and nearly three-quarters had no criminal conviction, often only minor offenses like traffic violations.\n\nAlthough there is no publicly stated directive establishing a formal shift in strategy, advocates and residents say enforcement is increasingly occurring outside plants.\n\n“Since last year, we’ve seen arrests following routine court appearances, such as for traffic violations, where people are then transferred into federal custody,” Fuentes said.\n\nA family divided and displaced\n\nOne of the people arrested by ICE in Milan was Victorino Martínez-Chávez, 46, a Guatemalan national, who worked a cleaning shift at the Smithfield meat-processing plant, the town’s largest employer, according to state workforce data.\n\nIn a statement, an ICE spokesperson said Martínez-Chavez, who had previously been deported, was arrested during a targeted enforcement operation and had “refused to obey lawful commands to exit his vehicle, threatening officer safety and forcing officers to remove him from the vehicle.” The spokesperson added that Martínez-Chavez had previously been deported and reentered the United States, which is a felony offense.\n\nAffholter’s video of the arrest, which was reviewed by Investigate Midwest, shows the driver’s side window of Martínez-Chávez’s vehicle already broken when ICE agents left the scene.\n\nTwo other men — Serigne Ciss, 33, and Thierno Amar, 33, both from Senegal — were also arrested, according to ICE. The agency said they had entered the United States after crossing the “border illegally” during the Biden administration, according to an ICE email.\n\nMinutes before his arrest, Martínez-Chávez had dropped off his daughter and other children at school.\n\nAt home, his wife, who asked not to be identified for fear of retaliation, was waiting for him to return home when she received a call from her stepdaughter, who said Martínez-Chávez had been detained.\n\n“I started crying,” the wife, 42, recalled. “Who’s going to take care of me now?”\n\nMartínez-Chávez was the sole breadwinner. His wife does not work outside the home and cares for the three youngest children, including one who is just 18 months old. She does not speak English and speaks limited Spanish; her primary language is Mam.\n\nThe wife moved to the United States three years ago to join her husband, who was already living in the community. That morning, beyond the fear, they faced immediate uncertainty: a pending paycheck and a week of vacation time they were unsure would be honored.\n\nDays before the arrest, Martínez-Chávez’s wife learned she was pregnant. Although she wants to return to Guatemala to reunite with her husband, who has already been deported, an error on her baby’s birth certificate has prevented her from obtaining a passport to take him out of the country, leaving her effectively trapped.\n\nA workplace under pressure\n\nDuring the past several decades, the meatpacking industry has shifted from major urban centers to smaller rural communities closer to livestock production, driven by larger-scale plants and changing supply-chain economics. Access to labor remains critical everywhere.\n\nThere are more than 7,000 inspected meat, poultry, and egg processing plants operating across the country, with more than one-fifth in rural and nonmetropolitan areas, according to the U.S. Department of Agriculture. Missouri ranks 14th among states in the number of meatpacking plants.\n\nThis shift has brought new economic life to many small towns, including Milan.\n\nThe Smithfield facility in Milan is classified as a large plant, employing at least 500 workers, a workforce equivalent to more than a quarter of the town’s residents.\n\nNearly half of residents identify as Hispanic, and more than a quarter were born outside the United States, more than double the rate in Missouri.\n\nNationwide, nearly half of meat-processing workers are foreign-born workers, according to a 2022 report by the American Immigration Council.\n\n“The American economy, and particularly the American food system, is entirely dependent on various forms of immigration, both legal and not so legal,” said Elizabeth Cullen Dunn, a geography professor at Indiana University who studies migration and labor.\n\nShe said enforcement actions are often designed to be visible without disrupting production.\n\n“They don’t want to shut the meatpacking plants down,” she said. “That would cost the meatpacking companies millions of dollars a day.”\n\nWhile Milan’s Smithfield plant was not raided in February, the effects of area arrests were felt the following day.\n\nRay Atkinson, senior director of external affairs at Smithfield, said in an email that “there was no interruption to our business on Tuesday and we have not had any staffing issues,” referring to the day of the ICE arrests.\n\nWorkers described a different reality.\n\nFour plant workers, who asked not to be identified for fear of retaliation, said operations began later than usual on Wednesday because several overnight sanitation workers failed to report for work. Some were afraid to leave their homes after the arrests, according to the workers.\n\nThe burden shifted onto those who showed up.\n\nA man in his 50s who has worked at the Smithfield plant for about two decades said the pace of repetitive hand movements had increased, raising the risk of injury.\n\n“With the faster pace, you could cause an accident or cut a coworker. … Our hands are constantly moving, and we’re working with knives.”\n\nA woman in her late 40s said that with fewer workers, breaks have become harder to take. She said employees are typically allowed to use the bathroom twice per shift.\n\nAtkinson did not respond to a follow-up email seeking comment on the reported disruptions.\n\nWhile the workers described short-term disruption, the company has warned investors about broader labor shortages, particularly in rural areas where some of its operations are located.\n\nIn its latest annual filing, Smithfield said that new immigration legislation could increase the costs of recruiting, training and retaining employees, as well as compliance costs related to reviewing workers’ immigration status, and could lead to employee shortages. The company also said that increased enforcement of existing immigration laws by government authorities could disrupt portions of its workforce or operations.\n\nIn poultry plants, workers may process as many as 140 birds per minute, said Navina Khanna, executive director of the HEAL Food Alliance, a national coalition that works with food system workers. In pork processing facilities, workers can repeat the same cut up to 9,000 times a day.\n\nThe risks are not new, but they can intensify when fewer workers are on the line. A recent study by the U.S. Department of Agriculture found that 81 percent of poultry-processing workers and 46 percent of pork-processing workers face an increased risk of musculoskeletal disorders, conditions typically characterized by pain and limitations in mobility and dexterity, that can limit a person’s ability to work and participate in daily life.\n\nConcerns about working conditions in meatpacking plants have surfaced in other parts of the country. Last month, at a JBS beef plant in Greeley, Colorado, workers went on strike, citing unsafe conditions, fast line speeds and limited breaks, according to The Associated Press.\n\nWith fewer workers on the line, there is less oversight to ensure “any kind of safety,” forcing employees to work “faster” and “longer,” Khanna said, adding that the combination of staffing shortages and increased line speeds is making conditions “more dangerous” for workers.\n\nEconomic effects in a rural town\n\nIn many rural communities, immigrant workers are not only part of the labor force but also a key source of economic stability. Research shows they contribute more in taxes than they receive in public benefits and help offset population decline, a trend that has become especially important in small towns across the Midwest.\n\nIn congressional testimony in 2023, David Bier of the Cato Institute, a Washington-based public policy research organization, said immigrants “generate, in inflation-adjusted terms, nearly $1 trillion in state, local, and federal taxes, almost $300 billion more than they receive in government benefits.”\n\nAt the center of Milan is the courthouse. On the surrounding four blocks, at least one business on each corner is tied to the town’s Latino community.\n\nMilan, in north-central Sullivan County, is a community shaped in part by immigration. About 46 percent of residents identify as Latino, and more than 28 percent were born outside the United States.\n\n“It’s very, very difficult,” said an immigrant from Guatemala who has lived in Milan for nearly two decades. “It makes my stomach turn to think that you keep fighting and fighting, and the problems don’t go away.”\n\nThe woman, who asked not to be identified for fear of her immigration status, owns a restaurant and a small grocery store that operate out of the same space. She said she started her own business so she would not have to rely on false documents to work and so she could contribute to the town’s economy.\n\nShe said fear in the community over current immigration policies has hurt her business.\n\n“They’re pushing us into a corner,” she said. “You feel like sooner or later, it’s your turn.”\n\nOn a good day, she said, she used to make about $1,000. Now, her sales can sometimes drop to around $100.\n\nShe also operates a money-transfer service. She said weekly money transfers, called remittances, once reached about $40,000, but dropped to roughly $6,000 in the last week of February.\n\nShe said the decline in sales began in 2025 and has forced her to reduce inventory. She used to travel to Kansas four or five times a month to restock products. Now she goes twice, sometimes only once.\n\nAt another store in downtown Milan, money-transfer services have dropped by about half. The owner said she now carries about 15 percent of the goods she once stocked.\n\n“You can’t start rounding up and deporting people, and terrorizing, and getting people to self-deport, when they make up about 20 percent of the workforce without expecting major negative impacts on the economy,” said Daniel Costa, director of immigration law and policy research at the Economic Policy Institute, a Washington-based think tank.\n\nMeat and poultry processing employs about 560,000 workers nationwide, with a combined payroll of $30 billion, underscoring how deeply local economies depend on the industry, according to the Economic Policy Institute.\n\nThe economic effects extend beyond daily routines and local businesses.\n\nAnother woman, who also asked not to be identified because of her immigration status, said fear has reshaped even the most routine parts of her family’s life.\n\nShe avoids going to Walmart on weekends, she said, because the nearest store is a 45-minute drive — and she worries she could be stopped along the way.\n\nShe has two children, ages 7 and 9. The younger child is autistic. Weekend outings, once a regular activity, have largely stopped. The family used to go to Pizza Hut, something the children looked forward to.\n\nHer older daughter has begun to grasp the situation.\n\n“She says that when she grows up, she hopes she’ll be able to fix our papers so we don’t have to live with this fear all the time,” the woman said.\n\nAffholter, the Kraft Heinz employee temporarily held in Milan, has lived in the U.S. for roughly two-thirds of his life. But the possibility of being stopped on the street because of his appearance has made him question his place in a country he considers his own.\n\n“What I am experiencing now is not normal. I can’t accept that this is normal,” he said. “Because that’s not the America I know.”\n\nAsked what he meant, he paused.\n\n“That we are all equal,” he said. “That we are all free. No matter your roots, no matter your color, no matter what language you speak.”\n\nInvestigate Midwest is an independent, nonprofit newsroom. Our mission is to serve the public interest by exposing dangerous and costly practices of influential agricultural corporations and institutions through in-depth and data-driven investigative journalism. Visit us online at www.investigatemidwest.org.\n\n\n\n"} +{"url": "https://news.shm.com.cn/2026-04/12/content_5482767.htm", "title": "中国游记 | 春色不负万里客 ! 老外爱上 春日中国行 - 水母网", "publish_date": "2026-04-12T14:40:26Z", "full_text": "中国游记 | 春色不负万里客!老外爱上“春日中国行”\n\n一朵牡丹,值得飞越万里。近期,马达加斯加姑娘嘉德为一朵牡丹“打飞的”来华,在上海古猗园沉浸式体验花神民俗文化,拍中国古风写真。“我的头饰绣上了牡丹,是一千年前的流行款!”嘉德满意地说。\n\n\n\n\n\n马达加斯加姑娘嘉德(左)在上海古猗园内沉浸式赏花 图源 上观新闻\n\n在这个春天,越来越多的海外游客像嘉德一样,正透过这样的“春日限定”体验,感受到中国蓬勃的生机与深厚的文化。\n\n以花为桥 在中国春色里唤起情感共鸣\n\n\n\n\n\n外交部发言人账号转发贵州春日短片\n\n在贵州贵安,70万株樱花汇成粉色的海洋,让远道而来的海外游客沉醉其中。“我从来没见过这么美的景色,成片的粉色,眼睛都看饱了。”马来西亚游客王燕萍兴奋地说道。“中国外交部发言人”官方账号在海外社媒平台X上转发贵州春日短片,将贵州的烂漫花海推向世界。\n\n\n\n\n\n美国博主“Craig也叫快克”置身于盛开的油菜花中\n\n在江西婺源,金黄的油菜花与山水交织成画,让自驾来此的美国博主“Craig也叫快克”在视频中赞叹不已,“有花、有梯田,还有山……一路开过来,我已经看入迷了。”\n\n杏花、樱花、海棠、迎春花……繁花盛放,海外游客为了中国春色奔赴而来。社交网络将中国的绝美春光推进海外网友的屏幕里,便利的免签政策让他们来得更容易、游得更轻松。据旅游平台数据,3月使用非中国护照预订国内航班的数量同比增长21%,多城跻身热门目的地。其中,西藏林芝的桃花带动海外游客赴游量增长6.3倍,山西大同的杏花与古建组合更让海外游客机票预订量暴涨超9倍,新疆喀什、伊宁的高原与杏花海也迎来超3.5倍的海外游客增长。\n\n海外游客在桃花树下驻足、在杏花海中漫步,本质上是在共赴一场跨越文化的“春日之约”。春日繁花象征的新生与希望,是中外共通的情感寄托,而中国“花与古建共生”的独特图景,更赋予春色别样的韵味。这份对美好事物的共同热爱,突破了文化隔阂界限,构建起了最朴素的情感连接。\n\nN种玩法在体验里感受中国式浪漫\n\n在刚刚过去的清明节假期,外国人出入境84.3万人次,较去年同期增长20.9%。入境外国人中,适用免签政策入境31.9万人次,较去年同期增长30.7%。\n\n\n\n\n\n海外游客打卡上海复兴思南年宵花市图源 上观新闻\n\n从冰雪游、过春节,到“打飞的”来中国赏花踏青,四季常新的体验和玩法,让海外游客在深度游的慢节奏里感受鲜活、浪漫而又真实的中国。品一杯春茶、尝一口春菜,用舌尖体会中国人“顺应天时、感受当下”的生活哲学;打卡非遗项目、乘坐无人驾驶车,感受古今交融的东方智慧……对海外游客而言,这些丰富的体验让“春日中国行”不再只是看花拍照,更是一场为花事、茶香、非遗与科技专程而来的深度奔赴。在一次次驻足、品味与对话中,他们触摸到的不仅是一个国家的风景,更是这片土地上绵延千年的生活智慧与面向未来的澎湃活力。\n\n人在往来中相知,文明在相遇中互鉴。如今,这条以文旅为桥、以交流为路的新纽带,正带动起“春日中国行”的热潮。这股热潮不仅见证了入境游市场的蓬勃发展,更为世界了解中国打开了一扇满含春日诗意的窗口——这里有满目春色,也有文明交融的无限风景。\n\n\n\n"} +{"url": "https://www.jalopnik.com/2142415/how-to-check-vehicle-tires-how-often/", "title": "Here How ( And How Often ) To Inspect Your Vehicle Tires", "publish_date": "2026-04-12T14:40:26Z", "full_text": "We may receive a commission on purchases made from links.\n\nThe tires of your vehicle take a lot of abuse. And, as you probably know, they aren't impervious to age, punctures, and damage caused by worn-out parts. The National Highway Traffic Safety Administration recommends inspecting all tires at least once a month or before taking a road trip. You'll want to keep an eye on any damage or wear, as well as the depth of your treads — but you'll want to start your inspection by focusing on the tire's pressure.\n\nWhile it might seem excessive, it's not a bad idea to check and correct the tire pressure as often as once every week. The reason is simple: tires will gradually lose some air pressure whether you drive the vehicle or not, and they can lose air when impacted by potholes or curbs. Why wait a month when you can do it once a week? Proper inflation can extend the life of any tire, and maintaining the correct air pressure can save a few cents per gallon on fuel. It doesn't sound like much, but it makes a difference in today's world of unstable oil prices.\n\nIt's a bad idea to inflate any tire to its maximum PSI, and it's relatively unwise to go over the recommended tire pressures for the front and rear, which you can easily find on a placard in the driver's side door jamb. Grab a tire pressure gauge, confirm the air pressure, and add or remove air when necessary. Also double-check it when the mercury drastically falls overnight, as the tire pressure will typically drop by a couple of PSI for every 10-degree Fahrenheit drop in temperature."} +{"url": "https://www.latercera.com/pulso/noticia/quienes-son-los-toesca-los-protagonistas-del-momento-en-sanhattan/", "title": "Quiénes son los Toesca : Los protagonistas del momento en Sanhattan", "publish_date": "2026-04-12T14:40:26Z", "full_text": "Si algo llama la atención de quienes visitan Toesca es que buscan las oficinas de los dueños y no las encuentran. Porque no tienen. Su espacio de trabajo, en plantas libres, es el mismo que el de sus colaboradores.\n\n“La comunicación, la cercanía, el ambiente que se da...Los jóvenes lo aprecian mucho”, cuenta un socio.\n\nFue una de las “buenas prácticas” que se trajeron los fundadores de esta administradora general de fondos (AGF) especializada en activos alternativos, de cuando trabajaban en BTG Pactual, antes Celfin, su cuna financiera.\n\nPor estos días Toesca S.A. Administradora de Fondos de Inversión parece vivir sus minutos de fama. Una saga de adquisiciones, incluyendo el ingreso como socio de un histórico del mundo de la inversión institucional, la han fijado en la retina de muchos que sabían de su existencia, pero que no habían calibrado lo relevantes que se han hecho con menos de una década de existencia.\n\nEste año partió de hecho con su primera gran operación. El mismo 1 de enero anunció la compra de la AGF Frontal Trust y sólo 20 días después, los socios de Toesca se unieron al fondo norteamericano TC Latin America Partners para comprar el 90% del factoring Primus Capital.\n\nEntre ambas operaciones, el 20 de enero, sumaron a un histórico hombre de las AFP, Alejandro Bezanilla, ex gerente general de AFP Habitat, como socio.\n\nY en marzo volvieron a la carga para negociar una posible fusión con otra AGF similar en tamaño, Ameris Capital, la que en todo caso todavía no se cierra. “Podría avanzar o caerse”, dice una fuente conocedora de la negociación.\n\nAunque en su historia Toesca ha levantado un total de US$2.500 millones en inversiones, actualmente gestiona en torno a los US$1.500 millones en 25 fondos. Trabajan con 55 personas y Frontal aportará una treintena adicional. Sus ingresos son de unos US$12 millones al año.\n\nAlejandro Reyes ITALO ARRIAZA +56983956683 PHOTO.CL\n\nUn antiguo origen\n\nLa Toesca de hoy nació oficialmente el 4 de noviembre de 2016, con dos socios: Alejandro Reyes y Carlos Saieh.\n\nReyes, ingeniero civil industrial de la Universidad de Concepción, estuvo 15 años en Celfin. Allí creó el área de administración de activos, con énfasis en gestión de patrimonio. Llegó a ser socio hasta que BTG Pactual adquirió el banco de inversión local en 2012, pero se quedó en su puesto hasta abril de 2016, cuando renunció.\n\nSu dimisión, así como la de sus colegas que terminaron siendo sus socios, se produjo sólo meses después de la crisis que sufriera BTG con la detención de su presidente ejecutivo, André Esteve, en Brasil, por acusaciones de corrupción vinculadas al caso Lava Jato. Esto provocó una fuga de inversionistas y una consecuente salida de ejecutivos.\n\nSaieh, ingeniero civil industrial de la U. Católica (UC) con un MBA en Wharton School de la Universidad de Pensilvania, venía de estar a cargo del área de activos alternativos en Celfin Capital, primero, y luego en BTG, donde se quedó hasta agosto de 2016. Su carrera la había iniciado en 2003 como analista de inversiones y luego subgerente de inversiones en Consorcio.\n\nCarlos Saieh, Toesca ITALO ARRIAZA +56983956683 PHOTO.CL\n\nPero la marca Toesca existía desde antes. Es más, su origen se remonta a 1990, cuando fue creada por la aseguradora estadounidense Aetna como su administradora de fondos de inversión (AFI). En 2001, después que el gigante neerlandés ING adquiriera Aetna en el mundo, pasó a denominarse ING AFI.\n\nRecién en mayo de 2003, tomó su actual nombre. Fue el que le puso Moneda Asset Management -hoy Moneda Patria Investments- cuando la adquirió. Pero al cabo de 13 años, sus resultados como AGF de activos alternativos no fueron los mejores, así que la puso en venta.\n\nEn paralelo, Reyes y Saieh, recién dimitidos de BTG, decidieron en octubre de 2016 armar un AGF juntos: arrendaron una pequeña oficina en El Golf 50 y contrataron a un gerente de operaciones, un administrador y un encargado de software. Pero hacerlo desde cero tardaría de 6 meses a un año, por lo que aprovecharon la opción de Moneda y le compraron Toesca con la idea de cambiarle el nombre. Nunca lo hicieron. Lo que sí hicieron fue inyectarle dinero fresco.\n\nSegún documentación pública, pasó de contar con un capital de $524 millones en diciembre de 2016 a $13.700 millones en febrero de 2017. “Pusimos toda la plata que teníamos”, contó Saieh en el podcast Millions: El Arte de Invertir.\n\nRodrigo Rojas ITALO ARRIAZA +56983956683 PHOTO.CL\n\nAunque a fines de 2016 habían conseguido refuerzos. Se les habían unido Rodrigo Rojas y Arturo Irarrázaval, quienes lideraban el negocio de acciones en BTG, con todo su equipo. Irarrázaval, ingeniero comercial de la U. Católica y master en finanzas de la escuela de negocios ESE de la U. de Los Andes, había trabajado como analista de inversiones de dos AFP y como gestor de inversiones en renta variable en BTG. Rojas, a su vez, ingeniero civil y MBA en la UC, fue analista y director de inversiones en acciones de FIT Research entre 2001 y 2003, mismo cargo que asumió en Celfin Capital -luego BTG- para después ser gerente de portafolio de acciones hasta 2016.\n\nEste equipo fue el que creó el primer fondo de la firma, que no fue de activos alternativos, como era la idea: fue el Fondo Mutuo de Acciones Chile Equities, que partió el 30 de diciembre del 2016. Y como la plantilla se duplicó en seis meses, tuvieron que ubicar alguna oficina más adecuada: encontraron una planta libre en el actual edificio del BICE en Apoquindo. Eran sólo 10 personas más algunas mesas en 400 metros cuadrados.\n\nArturo Irarrázaval ITALO ARRIAZA +56983956683 PHOTO.CL\n\nEse mismo mes migró otro más desde BTG: Augusto Rodríguez, ingeniero comercial de la U. de Los Andes, quien manejaba la división inmobiliaria, también heredada de su desempeño en Celfin, aunque su carrera la había iniciado como analista de riesgo en ABN Amro en 2003.\n\nLuego de un verano incierto, en marzo de 2017 arribó Max Vial, quien presidía la corredora de bolsa de BTG y había sido director de gestión de patrimonio. Vial, ingeniero comercial con estudios de posgrado en finanzas y marketing, había llegado en 1997 a Celfin, cuando esta firma compró la corredora de bolsa Gardeweg, de la cual era socio.\n\nEse mismo marzo levantaron el primer fondo de activos alternativos en infraestructura: compraron el 49% de la Ruta del Algarrobo, la autopista que une La Serena y Vallenar y que controlaba con un 51% la española Sacyr. Los inversionistas que suscribieron el fondo eran fundamentalmente compañías de seguros.\n\nAugusto Rodríguez ITALO ARRIAZA +56983956683 PHOTO.CL\n\nY durante el primer semestre de ese año, lanzaron también su primer fondo de rentas inmobiliarias, con el que compraron un strip center en Machalí, y el primero en crédito privado, para invertir en el negocio del factoring de segundo piso, factorizando a otros factoring. Los fondos de la carretera y del strip center los vendieron el año pasado y el de factoring, lo liquidaron poco después.\n\nPero en menos de nueve meses ya habían lanzado fondos en sus cuatro estrategias principales: infraestructura, inmobiliario y crédito privado en activos alternativos, y acciones. En 2017 habían experimentado un crecimiento explosivo.\n\nMax Vial ITALO ARRIAZA +56983956683 PHOTO.CL\n\nEn ese contexto convencieron a Alejandro Montero, su exjefe en BTG, que vivía su tercer año sabático en París con su familia, a que se integrara. Montero, ingeniero comercial de la UC con un MBA en Wharton, había iniciado su carrera como analista en 1993 en Celfin y llegó a ser gerente general en Celfin y la primera etapa de BTG.\n\nLos años siguientes fueron de acelerada expansión. Ya a inicios de 2019 habían levantado el primer billion de activos administrados: US$1.000 millones.\n\nDespués de eso, vino una meseta, que coincidió con el estallido social, la salida de capitales del país y la pandemia.\n\nEse freno en la expansión se relaciona, según quienes conocen a Toesca, con varios factores que se confabularon. En sus primeros años recibieron un gran volumen de dinero fresco y que fue su principal motor de crecimiento, con una alta rentabilidad. Pero luego sobrevino la incertidumbre local, afectada por la salida de capitales de personas naturales, sumada a una reducción de la caja de las compañías de seguros, dado un descenso en su venta de rentas vitalicias, y un cambio regulatorio en la inversión de las AFP en 2020, que “secó” los fondos a activos alternativos nacionales, favoreciendo a los extranjeros. “Nunca más fluyó plata de las AFP a estos activos en Chile”, reclama un conocedor.\n\nAlejandro Montero ITALO ARRIAZA +56983956683 PHOTO.CL\n\nEn estos años más débiles, abrieron una nueva estrategia relacionada con campos agrícolas. Levantaron un fondo llamado Permanent Crops, con la idea de comprar campos para producir fruta. Y en plena pandemia entró el único de los socios que no venía del “universo BTG”: Manuel Ossa. Ingeniero comercial de la UC con un MBA en la escuela Booth de la U, de Chicago, había sido asesor del Ministerio de Vivienda en la primera administración Piñera, para luego trabajar como analista y gerente de portafolio en Inversiones Arizona, el family office de la familia Luksic.\n\nManuel Ossa ITALO ARRIAZA +56983956683 PHOTO.CL\n\nEl repunte y la visión\n\nEl negocio empezó a levantar cabeza en 2023, repuntó firmemente en 2024 y el 2025 fue incluso mejor que el anterior.\n\nEste mejor momento coincidió con una reducción en las tasas de interés, que se habían disparado para contener a la galopante inflación, pues cuando las tasas están altas, los inversores prefieren la seguridad de la renta fija en vez de apostar por activos de riesgo.\n\nCon el impulso de esta nueva primavera de la inversión, Toesca se decidió a crecer tanto orgánica como inorgánicamente. En su área de farmland, por ejemplo, se asociaron en 2024 con la gestora inglesa Astarte para ampliar su cartera de campos: hoy tienen uno de 300 hectáreas en Rapel para paltos y cítricos, otro del mismo tamaño en Molina para cerezas y carozos, y otro en Ñuble para avellanos.\n\nY en enero pasado se robaron la agenda del mercado con las adquisiciones de Frontal Trust y Primus. La primera, que gestiona del orden de los US$600 millones y dado que cuenta con estrategias similares de negocios, debiera integrarse fácilmente. La segunda, seguirá trabajando como un factoring normal, aparte del AGF.\n\nAlejandro Bezanilla ITALO_ARRIAZA WWW.PHOTO.CL\n\nEn el noticioso enero, Alejandro Bezanilla, ingeniero civil de la UC y exgerente de inversiones y gerente general de AFP Habitat, donde trabajó casi 20 años, se integró como socio y director ejecutivo. Su misión: darle un marco más institucional a la firma, que le permita trascender en el tiempo, y al mismo tiempo aprovechar su buen nombre en el mundo institucional para que apoye al equipo comercial en la captación de inversores.\n\nTodo con el objetivo de ir acercándose a una meta que comparten los socios y que ya no es sólo administrar dinero de chilenos en activos chilenos, sino ir a buscar plata al mundo para que invierta en activos regionales."} +{"url": "https://www.sun-sentinel.com/2026/04/12/haitians-cut-back-on-already-scarce-food-and-ask-how-theyll-survive-rising-fuel-prices/", "title": "Haitians cut back on already scarce food and ask how theyll survive rising fuel prices – Sun Sentinel", "publish_date": "2026-04-12T14:40:26Z", "full_text": "By EVENS SANON and DÁNICA COTO\n\nPORT-AU-PRINCE, Haiti (AP) — For a factory worker in Haiti, the war in distant Iran means he now has to walk two hours to work and the same distance home each day, because he can no longer afford public transportation.\n\nOn a recent morning, Alexandre Joseph, 35, fretted about his family’s future in a loud voice, attracting the attention of passersby in Port-au-Prince, Haiti’s capital.\n\n“The government raised the prices of gasoline, diesel and kerosene, hitting my family. I now am unable to feed my two children on the salary I have,” he said.\n\nThe conflict in Iran has caused oil prices in Haiti to surge, disrupting critical supply chains, doubling transportation costs and forcing millions of undernourished people to cut back on already scarce meals.\n\nHaiti, the most impoverished country in the Western Hemisphere, has been hit the hardest by rising oil prices that experts warn will deepen a spiraling humanitarian crisis.\n\n‘One of the most fragile countries in the world’\n\nOn April 2, Haiti’s government announced a 37% increase in the cost of diesel and a 29% increase in the cost of gasoline.\n\n“The consequences are huge,” said Erwan Rumen, deputy country director for the United Nations World Food Program in Haiti. “It’s one of the most fragile countries in the world.”\n\nAlmost half of Haiti’s nearly 12 million inhabitants already face high levels of acute food insecurity. In recent months, Rumen noted, about 200,000 people dropped from the emergency phase to the acute one, a significant milestone.\n\n“What is a bit frightening is to see that so many efforts could be basically wiped out by things that are completely out of our control,” he said. “This part of the population is extremely fragile. They’re on the verge of collapsing completely.”\n\nGang violence has exacerbated hunger, with armed men controlling key roads and disrupting the transportation of goods. An increase in food prices will only worsen hunger in a country where gangs easily recruit children whose families need food and money.\n\nEmmline Toussaint, main coordinator of Mary’s Meals’ BND school-feeding program in Haiti, said that gas stations in some regions are selling fuel 25% to 30% higher than even what the government stipulated because of gang violence and difficulties with trucks trying to access certain areas.\n\nShe said the U.S.-based nonprofit is forced to use boats and take longer and multiple roads to feed the 196,000 children they serve across Haiti to avoid armed groups.\n\n“The humanitarian crisis that we’re facing right now is at its worst,” she said. “So far, we are doing our best not to step back. Now, more than ever, the kids need us. … Most of them, it’s the only meal they receive.”\n\n‘Everything will go up’\n\nFedline Jean-Pierre, a soft-spoken mother of a 7-year-old boy, sat under the shade of a tattered beach umbrella as she mulled increasing the prices of carrots, tomatoes and other produce she sells at an outdoor market in Port-au-Prince.\n\n“People are not buying now because they don’t have money,” she said, noting she likely won’t have a choice but to increase prices to survive. “I have a child to feed.”\n\nThe 35-year-old mother said she and her son have lived for two years in a cramped and unsanitary shelter, among the record 1.4 million Haitians displaced by gang violence in recent years.\n\n“The government doesn’t do anything for me,” she said. “Gas is up now, meaning everything will go up.”\n\nStreet vendor Maxime Poulard buys charcoal from suppliers to resell at a higher price. Occasionally he sells two bags of charcoal a day, but he thinks he soon will only be able to afford to buy half a bag to resell.\n\n“Traveling is expensive; eating is expensive; everything is expensive,” he said. “I’m not sure if I will be able to hold on much more.”\n\nNearly 40% of Haitians are surviving on less than $2.15 a day, according to the World Bank. Meanwhile, Haiti’s economy contracted for the seventh consecutive year, with inflation reaching 32% at the end of fiscal year 2025.\n\nJoseph, the factory worker, said he plans to sell soft drinks at night out of his home to try and earn more money, but even then, that won’t be enough: “We’re also going to reduce the way we normally eat.”\n\n‘Impossible tradeoffs’\n\nOn April 6, Haitians dragged burning tires and other debris to block streets and protest the increase in fuel prices in Port-au-Prince, of which an estimated 90% is controlled by gangs.\n\nLocal media reported gunfire as some Haitians forced the drivers of small colorful buses known as tap-taps to disembark their passengers.\n\nMarc Jean-Louis, a 29-year-old tap-tap driver, said passengers are increasingly bartering fares, but he can’t afford to offer discounts.\n\n“All the money is going toward gas,” he said as he called on the government to reduced prices “so that everyone can breathe.”\n\nHaitians fear more violence as the country’s poverty and hunger deepens.\n\nRumen, with the U.N.’s World Food Program, said they’ve been unable to reach 60,000 people in Haiti’s central region who are awaiting aid. A powerful gang recently attacked the area, killing more than 70 people, according to the U.N.\n\n“We’re going to have more needs and less resources,” he warned.\n\nAllen Joseph, program manager for Mercy Corps in Haiti, said rising oil prices are crushing the country’s fragile economy: “The families already spending most of their income on food will face impossible tradeoffs.”\n\nHe warned the increase will affect access to basic services, including potable water.\n\n“This is not an abstract inflation,” he warned. “It will directly impact survival.”\n\n___\n\nCoto reported from San Juan, Puerto Rico."} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Raw/raw_gdelt_asset_metals_derivatives.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Raw/raw_gdelt_asset_metals_derivatives.jsonl new file mode 100644 index 0000000..341667f --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Raw/raw_gdelt_asset_metals_derivatives.jsonl @@ -0,0 +1,9 @@ +{"url": "https://www.bursadabugun.com/haber/efsane-modellere-veda-turkiye-nin-en-cok-tercih-edilen-iki-otomobili-icin-yolun-sonu-gorundu-1911714.html", "url_mobile": "https://m.bursadabugun.com/haber/amp-efsane-modellere-veda-turkiye-nin-en-cok-tercih-edilen-iki-otomobili-icin-yolun-sonu-gorundu-1911714.html", "title": "Efsane modellere veda : Türkiyenin en çok tercih edilen iki otomobili için yolun sonu göründü", "seendate": "20260412T141500Z", "socialimage": "https://images.bursadabugun.com/haber/2026/04/12/1911714-efsane-modellere-veda-turkiye-nin-en-cok-tercih-edilen-iki-otomobili-icin-yolun-sonu-gorundu-69db8b845cddb.webp", "domain": "bursadabugun.com", "language": "Turkish", "sourcecountry": "Turkey"} +{"url": "https://tech.ifeng.com/c/8sGYfvCKmod", "url_mobile": "", "title": "DeepSeek , 该卸下扫地僧的枷锁了", "seendate": "20260412T133000Z", "socialimage": "https://x0.ifengimg.com/ucms/2026_16/C2E0500EBC6EE7A545C80B1511AF3B6636C38823_size77_w1035_h582.jpg", "domain": "tech.ifeng.com", "language": "Chinese", "sourcecountry": "China"} +{"url": "https://vancouversun.com:443/opinion/columnists/the-bookless-club-cook-with-alcohol-tips", "url_mobile": "", "title": "The Bookless Club : Do you cook with alcohol ? Any tips ? ", "seendate": "20260412T133000Z", "socialimage": "", "domain": "vancouversun.com", "language": "English", "sourcecountry": "Canada"} +{"url": "https://www.swindonadvertiser.co.uk/news/26014087.major-airlines-cut-flights-hike-fares-fuel-costs-rise/", "url_mobile": "", "title": "Major airlines cut flights and hike fares as fuel costs rise", "seendate": "20260412T133000Z", "socialimage": "https://www.swindonadvertiser.co.uk/resources/images/20768302.jpg?type=og-image&xType=0&yType=0", "domain": "swindonadvertiser.co.uk", "language": "English", "sourcecountry": "United Kingdom"} +{"url": "http://www.prnewswire.com/news-releases/earth-day-sale-15-off-organic-mattresses-and-bedding-at-my-green-mattress-302736499.html", "url_mobile": "", "title": "Earth Day Sale : 15 % Off Organic Mattresses and Bedding at My Green Mattress", "seendate": "20260412T133000Z", "socialimage": "", "domain": "prnewswire.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://www.etftrends.com/tactical-allocation-content-hub/gold-volatility-amid-geopolitical-crises-history-tells/", "url_mobile": "https://www.etftrends.com/tactical-allocation-content-hub/gold-volatility-amid-geopolitical-crises-history-tells/amp/", "title": "Gold Volatility Amid Geopolitical Crises : What History Tells Us", "seendate": "20260412T124500Z", "socialimage": "https://www.etftrends.com/wp-content/uploads/2026/04/shutterstock_2373961713.jpg", "domain": "etftrends.com", "language": "English", "sourcecountry": "China"} +{"url": "https://www.huxiu.com/article/4849844.html", "url_mobile": "https://m.huxiu.com/article/4849844.html", "title": "也许是时候想想几个月之后的事情 - 虎嗅网", "seendate": "20260412T124500Z", "socialimage": "https://img.huxiucdn.com/ai/ai-general-cover/202604/12/16978-prod-jm-general-1-1775988736153.png?imageView2/1/w/788/h/444/%7CimageMogr2/strip/interlace/1/quality/85/format/png", "domain": "huxiu.com", "language": "Chinese", "sourcecountry": "China"} +{"url": "https://www.eastbaytimes.com/2026/04/12/horoscopes-april-12-2026-claire-danes-the-timing-is-right-to-branch-out/", "url_mobile": "https://www.eastbaytimes.com/2026/04/12/horoscopes-april-12-2026-claire-danes-the-timing-is-right-to-branch-out/amp/", "title": "Horoscopes April 12 , 2026 : Claire Danes , the timing is right to branch out", "seendate": "20260412T121500Z", "socialimage": "https://www.eastbaytimes.com/wp-content/uploads/2026/04/AP26060822063006.jpg", "domain": "eastbaytimes.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://www.iltempo.it/personaggi/2026/04/12/news/luigi-bisignani-rai-poteri-riforma-governance-lobby-logge-giampaolo-rossi-47241443/", "url_mobile": "https://www.iltempo.it/personaggi/2026/04/12/news/luigi-bisignani-rai-poteri-riforma-governance-lobby-logge-giampaolo-rossi-47241443/amp/", "title": "Rai , in onda il risiko dei poteri tra Bruxelles e Palazzo", "seendate": "20260412T121500Z", "socialimage": "https://img.iltempo.it/images/2026/04/12/102019232-807b67ac-327f-4306-9ab7-22fe6166d009.jpg", "domain": "iltempo.it", "language": "Italian", "sourcecountry": "Italy"} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Raw/raw_gdelt_asset_precious_metals_spot.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Raw/raw_gdelt_asset_precious_metals_spot.jsonl new file mode 100644 index 0000000..05b1fa4 --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Raw/raw_gdelt_asset_precious_metals_spot.jsonl @@ -0,0 +1,10 @@ +{"url": "https://www.jagonews24.com/international/news/1109820", "url_mobile": "https://www.jagonews24.com/amp/1109820", "title": "ক্ষেপণাস্ত্র প্রতিরক্ষা সংকটে যুক্তরাষ্ট্র , একমাত্র ভরসা চীন ? ", "seendate": "20260412T141500Z", "socialimage": "https://cdn.jagonews24.com/media/og-image/2026/04/12/og_1776001524_69dba1f463738.jpeg", "domain": "jagonews24.com", "language": "Bengali", "sourcecountry": "Bangladesh"} +{"url": "https://www.tgrthaber.com/ekonomi/islam-memisten-altin-ve-konut-icin-pazartesi-uyarisi-artik-zamani-geldi-3294009", "url_mobile": "", "title": "İslam Memiş ten altın ve konut için pazartesi uyarısı ! Artık zamanı geldi", "seendate": "20260412T141500Z", "socialimage": "https://i.tgrthaber.com/images/2026/4/12/islam-memisten-altin-ve-konut-icin-pazartesi-uyarisi-artik-zamani-geldi-3294009.jpg", "domain": "tgrthaber.com", "language": "Turkish", "sourcecountry": ""} +{"url": "https://www.bursadabugun.com/haber/efsane-modellere-veda-turkiye-nin-en-cok-tercih-edilen-iki-otomobili-icin-yolun-sonu-gorundu-1911714.html", "url_mobile": "https://m.bursadabugun.com/haber/amp-efsane-modellere-veda-turkiye-nin-en-cok-tercih-edilen-iki-otomobili-icin-yolun-sonu-gorundu-1911714.html", "title": "Efsane modellere veda : Türkiyenin en çok tercih edilen iki otomobili için yolun sonu göründü", "seendate": "20260412T141500Z", "socialimage": "https://images.bursadabugun.com/haber/2026/04/12/1911714-efsane-modellere-veda-turkiye-nin-en-cok-tercih-edilen-iki-otomobili-icin-yolun-sonu-gorundu-69db8b845cddb.webp", "domain": "bursadabugun.com", "language": "Turkish", "sourcecountry": "Turkey"} +{"url": "https://www.dostor.org/5503201", "url_mobile": "", "title": "بكام جرام الذهب ؟.. أسعار الذهب اليوم الأحد 12 إبريل 2026", "seendate": "20260412T141500Z", "socialimage": "", "domain": "dostor.org", "language": "Arabic", "sourcecountry": "Egypt"} +{"url": "https://www.latercera.com/pulso/noticia/quienes-son-los-toesca-los-protagonistas-del-momento-en-sanhattan/", "url_mobile": "https://www.latercera.com/pulso/noticia/quienes-son-los-toesca-los-protagonistas-del-momento-en-sanhattan/?outputType=base-amp-type", "title": "Quiénes son los Toesca : Los protagonistas del momento en Sanhattan", "seendate": "20260412T140000Z", "socialimage": "https://www.latercera.com/resizer/v2/JDYL2FMD4BH5PK2CJOKLG457JQ.jpeg?auth=118390cdb73aa2f6de87f5e4feba50889db11a0f8d8ca4b50457a9f7bdc39a4c&smart=true", "domain": "latercera.com", "language": "Spanish", "sourcecountry": "Chile"} +{"url": "https://www.sun-sentinel.com/2026/04/12/ask-ira-time-for-nba-to-cook-the-books-in-heat-favor-after-hornets-rozier-fiasco/", "url_mobile": "", "title": "Should the NBA do next do right by the Miami Heat ? ", "seendate": "20260412T140000Z", "socialimage": "https://www.sun-sentinel.com/wp-content/uploads/2024/01/Bulls-Hornets-Basketball.jpg", "domain": "sun-sentinel.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://jd.zol.com.cn/1162/11629095.html", "url_mobile": "https://m.zol.com.cn/article/11629095.html", "title": "BRAUN 8517S电动剃须刀秘境银Pro版热卖 ! ", "seendate": "20260412T140000Z", "socialimage": "", "domain": "jd.zol.com.cn", "language": "Chinese", "sourcecountry": "China"} +{"url": "https://tech.ifeng.com/c/8sGYfvCKmod", "url_mobile": "", "title": "DeepSeek , 该卸下扫地僧的枷锁了", "seendate": "20260412T133000Z", "socialimage": "https://x0.ifengimg.com/ucms/2026_16/C2E0500EBC6EE7A545C80B1511AF3B6636C38823_size77_w1035_h582.jpg", "domain": "tech.ifeng.com", "language": "Chinese", "sourcecountry": "China"} +{"url": "https://www.express.co.uk/celebrity-news/2192212/liverpool-boy-band-who-made-history", "url_mobile": "https://www.express.co.uk/celebrity-news/2192212/liverpool-boy-band-who-made-history/amp", "title": "Liverpool band made history - but theyre not the Beatles | Celebrity News | Showbiz & TV", "seendate": "20260412T133000Z", "socialimage": "https://cdn.images.express.co.uk/img/dynamic/79/1200x630/6855175.jpg", "domain": "express.co.uk", "language": "English", "sourcecountry": "United Kingdom"} +{"url": "https://www.boerse-express.com/news/articles/wisdomtree-silver-3x-etc-bestaende-brechen-ein-891172", "url_mobile": "", "title": "WisdomTree Silver 3x ETC : Bestände brechen ein ! ", "seendate": "20260412T133000Z", "socialimage": "https://www.boerse-express.com/assets/588056a0d5/wisdomtree-silver-3x-etc-bestaende-brechen-ein-891172__FillWzEyMDAsMTIwMF0.jpg", "domain": "boerse-express.com", "language": "German", "sourcecountry": "Austria"} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Raw/raw_gdelt_macro_central_banks.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Raw/raw_gdelt_macro_central_banks.jsonl new file mode 100644 index 0000000..f0da0b6 --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Raw/raw_gdelt_macro_central_banks.jsonl @@ -0,0 +1,10 @@ +{"url": "https://www.govtech.com/blogs/lohrmann-on-cybersecurity/why-anthropics-mythos-is-a-systemic-shift-for-global-cybersecurity", "url_mobile": "", "title": "Why Anthropic Mythos Is a Systemic Shift for Global Cybersecurity", "seendate": "20260412T141500Z", "socialimage": "http://erepublic-brightspot.s3.us-west-2.amazonaws.com/14/56/19411bfc4f7393edf3c68c17b85f/adobestock-679761570.jpeg", "domain": "govtech.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://finance.yahoo.com/markets/options/articles/45k-debt-invest-ira-pay-125503481.html", "url_mobile": "", "title": "I Have $45K in Debt . Should I Invest in an IRA or Pay the Bills First ? ", "seendate": "20260412T133000Z", "socialimage": "https://s.yimg.com/ny/api/res/1.2/K7RApAvnURB22baje1xlIw--/YXBwaWQ9aGlnaGxhbmRlcjt3PTEyMDA7aD03Njc-/https://media.zenfs.com/en/24_7_wall_st__718/12706665d52ca94b935a88fa9a051e7c", "domain": "finance.yahoo.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://aninews.in/news/business/no-increase-in-interest-rates-125-bps-repo-cut-benefit-passed-to-customers-pnb-ceo20260412175534/", "url_mobile": "/news/business/no-increase-in-interest-rates-125-bps-repo-cut-benefit-passed-to-customers-pnb-ceo20260412175534?amp=1", "title": " No increase in interest rates , 125 bps repo cut benefit passed to customers : PNB CEO", "seendate": "20260412T133000Z", "socialimage": "https://d3lzcn6mbbadaf.cloudfront.net/media/details/ANI-20260412122515.jpg", "domain": "aninews.in", "language": "English", "sourcecountry": "India"} +{"url": "https://tribunaonline.com.br/economia/trabalhador-podera-sacar-ate-20-do-fgts-para-pagar-dividas-diz-ministro-298957", "url_mobile": "https://tribunaonline.com.br/economia/trabalhador-podera-sacar-ate-20-do-fgts-para-pagar-dividas-diz-ministro-298957?_=amp", "title": "Trabalhador poderá sacar até 20 % do FGTS para pagar dívidas , diz ministro | Tribuna Online", "seendate": "20260412T133000Z", "socialimage": "https://cdn2.tribunaonline.com.br/img/Artigo-Destaque/290000/Trabalhador-podera-sacar-ate-20-do-FGTS-para-pagar0029895700202604120956.jpg?xid=1399473", "domain": "tribunaonline.com.br", "language": "Portuguese", "sourcecountry": "Brazil"} +{"url": "https://www.tinnhanhchungkhoan.vn/co-phieu-can-quan-tam-ngay-134-post388652.html", "url_mobile": "https://m.tinnhanhchungkhoan.vn/co-phieu-can-quan-tam-ngay-134-post388652.amp", "title": "Cổ phiếu cần quan tâm ngày 13 / 4", "seendate": "20260412T133000Z", "socialimage": "https://image.tinnhanhchungkhoan.vn/1200x630/Uploaded/2026/cqjwqcqdh/2025_08_05/mch-385-8228.jpg", "domain": "tinnhanhchungkhoan.vn", "language": "Vietnamese", "sourcecountry": "Vietnam"} +{"url": "https://baomoi.com/truy-to-nhom-dieu-hanh-bankland-lua-gan-500-ty-dong-cua-hon-5-300-bi-hai-c54920488.epi", "url_mobile": "", "title": "Truy tố nhóm điều hành Bankland lừa gần 500 tỷ đồng của hơn 5 . 300 bị hại", "seendate": "20260412T133000Z", "socialimage": "", "domain": "baomoi.com", "language": "Vietnamese", "sourcecountry": "Vietnam"} +{"url": "https://www.reflector.com/news/national/lessons-learned-in-70s-have-made-the-us-and-world-economies-less-vulnerable-to-oil/article_889e87a7-70fd-5892-8f19-f669048a2cd2.html", "url_mobile": "", "title": "Lessons learned in 70s have made the US and world economies less vulnerable to oil shocks", "seendate": "20260412T133000Z", "socialimage": "https://bloximages.newyork1.vip.townnews.com/reflector.com/content/tncms/assets/v3/editorial/7/18/718227f8-338f-55a7-9d71-03402a1ad4d1/69bc41e01ffe6.image.jpg?crop=1763%2C926%2C0%2C124", "domain": "reflector.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://www.prnewswire.com/news-releases/the-conference-board-employment-trends-index-eti-declined-in-march-302734697.html", "url_mobile": "", "title": "The Conference Board Employment Trends Index™ ( ETI ) Declined in March", "seendate": "20260412T133000Z", "socialimage": "", "domain": "prnewswire.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://www.sozcu.com.tr/30-yildir-ilk-kez-yasaniyor-merkez-bankalari-dolardan-kacip-altina-sigindi-p309549", "url_mobile": "https://www.sozcu.com.tr/amp/30-yildir-ilk-kez-yasaniyor-merkez-bankalari-dolardan-kacip-altina-sigindi-p309549", "title": "30 yıldır ilk kez yaşanıyor : Merkez bankaları dolardan kaçıp altına sığındı", "seendate": "20260412T133000Z", "socialimage": "https://sozcu01.sozcucdn.com/sozcu/production/uploads/images/2026/4/altinrez3jpg-cp0On19hi0SzVtFT6NSGKg.jpg?&mode=crop&scale=both", "domain": "sozcu.com.tr", "language": "Turkish", "sourcecountry": "Turkey"} +{"url": "https://www.tinnhanhchungkhoan.vn/tien-re-co-quay-lai-chung-khoan-sang-cua-but-pha-post388709.html", "url_mobile": "https://m.tinnhanhchungkhoan.vn/tien-re-co-quay-lai-chung-khoan-sang-cua-but-pha-post388709.amp", "title": "Tiền rẻ có quay lại , chứng khoán sáng cửa bứt phá ? ", "seendate": "20260412T133000Z", "socialimage": "https://image.tinnhanhchungkhoan.vn/1200x630/Uploaded/2026/sotnza/2021_03_31/dsc-4988-7827.jpg", "domain": "tinnhanhchungkhoan.vn", "language": "Vietnamese", "sourcecountry": "Vietnam"} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Raw/raw_gdelt_macro_geopolitics_risk.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Raw/raw_gdelt_macro_geopolitics_risk.jsonl new file mode 100644 index 0000000..c73d446 --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Raw/raw_gdelt_macro_geopolitics_risk.jsonl @@ -0,0 +1,8 @@ +{"url": "https://www.readingchronicle.co.uk/news/national/26014084.russia-ukraine-trade-blame-violating-orthodox-easter-ceasefire/", "url_mobile": "", "title": "Russia and Ukraine trade blame for violating Orthodox Easter ceasefire", "seendate": "20260412T141500Z", "socialimage": "https://www.readingchronicle.co.uk/resources/images/20777447.jpg?type=og-image", "domain": "readingchronicle.co.uk", "language": "English", "sourcecountry": "United Kingdom"} +{"url": "https://www.jagonews24.com/international/news/1109820", "url_mobile": "https://www.jagonews24.com/amp/1109820", "title": "ক্ষেপণাস্ত্র প্রতিরক্ষা সংকটে যুক্তরাষ্ট্র , একমাত্র ভরসা চীন ? ", "seendate": "20260412T141500Z", "socialimage": "https://cdn.jagonews24.com/media/og-image/2026/04/12/og_1776001524_69dba1f463738.jpeg", "domain": "jagonews24.com", "language": "Bengali", "sourcecountry": "Bangladesh"} +{"url": "https://www.hindustantimes.com/world-news/when-trump-said-iran-never-lost-a-negotiation-old-post-returns-as-talks-fail-101775996913412.html", "url_mobile": "https://www.hindustantimes.com/world-news/when-trump-said-iran-never-lost-a-negotiation-old-post-returns-as-talks-fail-101775996913412-amp.html", "title": "When Trump said Iran never lost a negotiation : His old post returns as Islamabad talks fail", "seendate": "20260412T141500Z", "socialimage": "https://www.hindustantimes.com/ht-img/img/2026/04/12/550x309/Trump-Never-Loses-0_1775997253691_1775997276489.jpg", "domain": "hindustantimes.com", "language": "English", "sourcecountry": "India"} +{"url": "https://www.bordertelegraph.com/news/national/26014105.starmer-urges-us-iran-to-find-way-through-peace-talks-fail/", "url_mobile": "", "title": "Starmer urges US and Iran to find a way through after peace talks fail", "seendate": "20260412T141500Z", "socialimage": "https://www.bordertelegraph.com/resources/images/20777455.jpg?type=og-image", "domain": "bordertelegraph.com", "language": "English", "sourcecountry": "United Kingdom"} +{"url": "https://article.wn.com/view/2026/04/12/China_to_reinstate_some_Taiwan_ties_after_opposition_leaders/", "url_mobile": "", "title": "China to reinstate some Taiwan ties after opposition leader visit", "seendate": "20260412T141500Z", "socialimage": "", "domain": "article.wn.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://www.tanjug.rs/region/politika/244331/viktor-orban-ukrajina-ce-pustiti-naftovod-druzba-cim-pobedimo-odmah-ujutru/vest", "url_mobile": "https://www.tanjug.rs/region/politika/244331/viktor-orban-ukrajina-ce-pustiti-naftovod-druzba-cim-pobedimo-odmah-ujutru/amp", "title": "Viktor Orban : Ukrajina će pustiti naftovod Družba čim pobedimo", "seendate": "20260412T141500Z", "socialimage": "https://www.tanjug.rs/data/images/2026-04-12/377971_hungary-election_s.jpg", "domain": "tanjug.rs", "language": "Croatian", "sourcecountry": "Serbia"} +{"url": "https://www.muensterschezeitung.de/nachrichten/schlagzeilen/ukraine-krieg-tausende-verstoesse-bei-osterwaffenruhe-beklagt-3530354", "url_mobile": "", "title": "Ukraine - Krieg : Tausende Verste bei Osterwaffenruhe beklagt", "seendate": "20260412T141500Z", "socialimage": "https://asc-images.forward-publishing.io/2026/04/12/01cd0b3e-0f89-4152-85d9-03a099f8216d.jpg?rect=0%2C0%2C2048%2C1365&auto=compress%2Cformat", "domain": "muensterschezeitung.de", "language": "German", "sourcecountry": "Germany"} +{"url": "https://www.diariocritico.com/internacional/trump-anuncia-bloqueo-estrecho-ormuz-paguen-a-iran", "url_mobile": "", "title": "Trump anuncia un bloqueo del Estrecho de Ormuz para todos aquellos que paguen a Irán", "seendate": "20260412T141500Z", "socialimage": "https://www.diariocritico.com/fotos/1/380993_donald-trump.jpg", "domain": "diariocritico.com", "language": "Spanish", "sourcecountry": "Spain"} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Raw/raw_gdelt_macro_inflation_employment.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Raw/raw_gdelt_macro_inflation_employment.jsonl new file mode 100644 index 0000000..53f643b --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-12/Raw/raw_gdelt_macro_inflation_employment.jsonl @@ -0,0 +1,10 @@ +{"url": "https://www.ringblad.no/enighet-med-fellesforbundet-i-frontfagsoppgjoret-parat-fortsatt-i-mekling/s/5-45-2209025", "url_mobile": "", "title": "Lønnsforhandlinger , Arbeidsliv | Enighet med Fellesforbundet i frontfagsoppgjøret – Parat fortsatt i mekling", "seendate": "20260412T141500Z", "socialimage": "https://g.acdn.no/obscura/API/dynamic/r1/ece5/tr_2000_2000_s_f/1775995163000/ring/2026/4/12/13/cueres_scp-mangler_navn_9D2iQ17g1MU.jpg?chk=022ED1", "domain": "ringblad.no", "language": "Norwegian", "sourcecountry": "Norway"} +{"url": "https://www.moonofalabama.org/2026/04/war-on-iran-loser-tries-setting-terms-the-strange-idea-of-blockading-blockaders.html/comment-page-2", "url_mobile": "", "title": "War On Iran : – Loser Tries Setting Terms – The Strange Idea Of Blockading Blockaders – Moon of Alabama", "seendate": "20260412T141500Z", "socialimage": "", "domain": "moonofalabama.org", "language": "English", "sourcecountry": "Syria"} +{"url": "https://finance.sina.com.cn/tech/roll/2026-04-12/doc-inhufzfw3094116.shtml", "url_mobile": "", "title": "数码回收网 : 2026年3月废旧手机回收价暴跌30 % ", "seendate": "20260412T141500Z", "socialimage": "", "domain": "finance.sina.com.cn", "language": "Chinese", "sourcecountry": "China"} +{"url": "https://www.elobservador.com.uy/espana/impacto-global/fracasa-la-negociacion-eeuu-e-iran-islamabad-y-vuelven-sonar-los-tambores-guerra-n6040452", "url_mobile": "", "title": "Fracasa la negociación entre EEUU e Irán en Islamabad y vuelven a sonar los tambores de guerra", "seendate": "20260412T141500Z", "socialimage": "https://media.elobservador.com.uy/p/e1b68ea2f4b44771ca627bb9220c6a40/adjuntos/364/imagenes/100/732/0100732019/1200x675/smart/69db384836aec7-31436707r_d1619-765-4267.webp", "domain": "elobservador.com.uy", "language": "Spanish", "sourcecountry": "Uruguay"} +{"url": "https://www.thestandard.co.zw/business/article/200053827/zimbabwes-lenders-hedge-against-global-shocks", "url_mobile": "https://www.newsday.co.zw/thestandard/amp/business/article/200053827/zimbabwes-lenders-hedge-against-global-shocks", "title": "Zimbabwe lenders hedge against global shocks", "seendate": "20260412T141500Z", "socialimage": "", "domain": "thestandard.co.zw", "language": "English", "sourcecountry": "Zimbabwe"} +{"url": "http://www.newstribune.com/news/2026/apr/12/in-rural-missouri-immigration-crackdown-reaches-beyond-the-workplace/", "url_mobile": "", "title": "In rural Missouri , immigration crackdown reaches beyond the workplace", "seendate": "20260412T141500Z", "socialimage": "https://wehco.media.clients.ellingtoncms.com/img/photos/2026/04/12/2-27-26__2026_March_Milan_17-scaled-1-e1775821936280-1536x846_t1200.jpeg?57a0c2296240c280e9492005c3cad63e7cbe80f4", "domain": "newstribune.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://news.shm.com.cn/2026-04/12/content_5482767.htm", "url_mobile": "", "title": "中国游记 | 春色不负万里客 ! 老外爱上 春日中国行 - 水母网", "seendate": "20260412T140000Z", "socialimage": "", "domain": "news.shm.com.cn", "language": "Chinese", "sourcecountry": "China"} +{"url": "https://www.jalopnik.com/2142415/how-to-check-vehicle-tires-how-often/", "url_mobile": "", "title": "Here How ( And How Often ) To Inspect Your Vehicle Tires", "seendate": "20260412T140000Z", "socialimage": "https://www.jalopnik.com/img/gallery/heres-how-and-how-often-to-inspect-your-vehicles-tires/l-intro-1775583371.jpg", "domain": "jalopnik.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://www.latercera.com/pulso/noticia/quienes-son-los-toesca-los-protagonistas-del-momento-en-sanhattan/", "url_mobile": "https://www.latercera.com/pulso/noticia/quienes-son-los-toesca-los-protagonistas-del-momento-en-sanhattan/?outputType=base-amp-type", "title": "Quiénes son los Toesca : Los protagonistas del momento en Sanhattan", "seendate": "20260412T140000Z", "socialimage": "https://www.latercera.com/resizer/v2/JDYL2FMD4BH5PK2CJOKLG457JQ.jpeg?auth=118390cdb73aa2f6de87f5e4feba50889db11a0f8d8ca4b50457a9f7bdc39a4c&smart=true", "domain": "latercera.com", "language": "Spanish", "sourcecountry": "Chile"} +{"url": "https://www.sun-sentinel.com/2026/04/12/haitians-cut-back-on-already-scarce-food-and-ask-how-theyll-survive-rising-fuel-prices/", "url_mobile": "", "title": "Haitians cut back on already scarce food and ask how theyll survive rising fuel prices – Sun Sentinel", "seendate": "20260412T140000Z", "socialimage": "https://www.sun-sentinel.com/wp-content/uploads/2026/04/Haiti_Gas__6723-1.jpg", "domain": "sun-sentinel.com", "language": "English", "sourcecountry": "United States"} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-14/Full_text/full_text_asset_precious_metals_spot.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-14/Full_text/full_text_asset_precious_metals_spot.jsonl new file mode 100644 index 0000000..d3d4192 --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-14/Full_text/full_text_asset_precious_metals_spot.jsonl @@ -0,0 +1,7 @@ +{"url": "https://thoibaotaichinhvietnam.vn/ngay-154-gia-bac-trong-nuoc-va-the-gioi-bat-tang-manh-195669.html", "title": "Ngày 15 / 4 : Giá bạc trong nước và thế giới bật tăng mạnh", "publish_date": "2026-04-15T03:32:11Z", "full_text": "Giá bạc hôm nay vượt 80 triệu/kg. Ảnh minh họa\n\nCập nhật lúc 8h30h sáng 15/4, giá bạc miếng Phú Quý 999 tại Tập đoàn Vàng bạc Đá quý Phú Quý hiện niêm yết ở mức 3.018.000 đồng/lượng (mua vào) và 3.111.000 đồng/lượng (bán ra), tăng so với mức 2.852.000 đồng/lượng (mua vào) và 2.940.000 đồng/lượng (bán ra) niêm yết sáng hôm qua.\n\nTrong khi đó, bạc các thương hiệu khác niêm yết trên Phú Quý cũng tăng so với trước. Cụ thể, bạc 999 10 lượng, 5 lượng ở mức 3.018.000 đồng/lượng (mua vào) và 3.111.000 đồng/lượng (bán ra); đồng bạc mỹ nghệ Phú Quý 999 ở mức 3.018.000 đồng/lượng (mua vào) và 3.551.000 đồng/lượng (bán ra); bạc thỏi Phú Quý 999 1Kilo ở mức 80.479.000 đồng/lượng (mua vào) và 82.959.793 đồng/lượng (bán ra); bạc 999 (miếng - thanh - thỏi) ở mức 2.554.000 đồng/lượng (mua vào) và 3018.000 đồng/lượng (bán ra).\n\nCập nhật bảng giá bạc mới nhất tại Tập đoàn Vàng bạc Đá quý Phú Quý ngày 15/4/2026:\n\nTrên thị trường thế giới, giá bạc phục hồi mạnh vượt mốc 80 USD/ounce. Diễn biến này diễn ra trong bối cảnh Mỹ và Iran phát tín hiệu sẵn sàng nối lại đàm phán, hướng tới một thỏa thuận ngừng bắn dài hạn trước khi lệnh đình chiến hai tuần hiện tại hết hiệu lực. Cập nhật lúc 8h45h sáng 15/4, giá bạc thế giới tăng mạnh. Giá bạc giao ngay hiện đang ở mức 80,470 USD/ounce, tăng 1,11% so với hôm qua.\n\nĐà tăng của bạc trong những phiên gần nhất được đánh giá là tín hiệu tích cực sau giai đoạn điều chỉnh. Thị trường đã nhanh chóng phục hồi, cho thấy lực cầu vẫn đang đóng vai trò chủ đạo, đặc biệt khi giá giảm về vùng hấp dẫn.\n\nMột trong những điểm đáng chú ý trong diễn biến giá bạc hôm nay là sự quay trở lại mạnh mẽ của dòng tiền bắt đáy. Khi giá giảm về vùng thấp trong các phiên trước, nhiều nhà đầu tư đã tận dụng cơ hội để gia tăng vị thế mua.\n\nĐiều này giúp thị trường nhanh chóng lấy lại đà tăng và duy trì trạng thái ổn định, thay vì rơi vào xu hướng giảm sâu. Thực tế cho thấy bạc vẫn là kênh đầu tư hấp dẫn trong bối cảnh nhiều biến động kinh tế toàn cầu./."} +{"url": "https://www.163.com/dy/article/KQI4EG8P0519DDQ2.html", "title": "具身智能百日内 吸金 超345亿元|融资|算法|模态|机器人", "publish_date": "2026-04-15T03:32:11Z", "full_text": "声明:包含AI生成内容\n\n特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。\n\nNotice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services."} +{"url": "https://baomoi.com/gia-vang-ngay-15-4-bang-gia-tai-cac-cong-ty-vang-bac-da-quy-c54939126.epi", "title": "Giá vàng ngày 15 / 4 : Bảng giá tại các công ty vàng bạc đá quý", "publish_date": "2026-04-15T03:32:11Z", "full_text": "Vàng trang sức. (Ảnh: Phan Phương/TTXVN)\n\nGiá vàng thế giới tăng khoảng 2% lên 4.831,78 USD/ounce nhờ đồng USD yếu và kỳ vọng các cuộc đàm phán Mỹ-Iran sẽ được nối lại.\n\nChuyên gia Bob Haberkorn tại RJO Futures nhận định nhà đầu tư đang chuyển hướng quay lại kim loại quý thay vì giữ tiền mặt như giai đoạn đầu xung đột.\n\nCác nhà phân tích tại Commerzbank cho rằng chừng nào Cục Dự trữ Liên bang Mỹ (Fed) chưa có dấu hiệu tăng lãi suất, giá vàng sẽ rất khó giảm sâu. Hiện các nhà giao dịch dự báo chỉ có khoảng 33% khả năng Fed sẽ cắt giảm lãi suất trong năm nay, một con số thấp hơn nhiều so với kỳ vọng trước khi diễn ra xung đột tại Trung Đông.\n\nTại Việt Nam, vào sáng 15/4, công ty Vàng bạc đá quý Sài Gòn niêm yết giá vàng SJC tại thị trường Hà Nội ở mức 173,00-175,50 triệu đồng/lượng (mua vào-bán ra).\n\nDưới đây là bảng giá vàng tại một số công ty vàng bạc đá quý trong nước sáng 15/4:\n\nGiá vàng tại Công ty Trách nhiệm hữu hạn Một thành viên Vàng bạc đá quý Sài Gòn (SJC):\n\nGiá vàng tại Công ty Cổ phần Đầu tư vàng Phú Quý:"} +{"url": "http://www.elpuntavui.cat/politica/article/17-politica/2635259-pisos-turistics-les-cases-per-als-veins-i-els-turistes-als-hotels.html", "title": " Pisos turístics ? Les cases , per als veïns i els turistes , als hotels ", "publish_date": "2026-04-15T03:32:11Z", "full_text": "E\n\nl PP i Vox han aprovat els pressupostos per a 2026. Com valoreu els comptes?\n\nAquests pressupostos són els més elevats de la història, però, així i tot, reflecteixen una realitat preocupant: la inversió als barris ha caigut a mínims històrics, amb només 20 milions d’euros destinats a aquestes partides. A més, l’execució del pressupost per part de l’equip de govern és ineficient, ja que amb prou faenes executen 3 de cada 10 euros pressupostats. Aquesta falta de capacitat de gestió provoca que la resta dels fons acaben sistemàticament en el romanent de tresoreria, un fet que situa Alacant a la cua d’inversió per habitant en comparació amb altres capitals. L’aprovació d’aquests comptes ha estat condicionada per una sèrie de concessions que el PP ha fet a Vox i que es tradueixen en projectes sense competències ni utilitat real. Per exemple, una Oficina Antiocupació, que és una infraestructura buida, sense personal policial ni competències i que té un pressupost que es limita pràcticament a la placa de la porta: uns 30 euros. També l’Oficina del Cuidador: un recurs sense funcions clares ni sistema de cites que, a la pràctica, només ofereix atenció psicològica a les famílies afectades per les mancances del sistema. I, finalment, el que ells en diuen Oficina de la Maternitat, és a dir, l’Oficina Antiavortaments, una iniciativa de dubtosa legalitat que duplica serveis i que no té base competencial. D’altra banda, als comptes també hi ha projectes destinats principalment al turisme, com la instal·lació de fonts, zones wifi per als creueristes o instal·lació puntual de tendals, que no responen a les necessitats estructurals de la ciutadania. Així, mentre s’inauguren aquestes oficines, la realitat és que Alacant és una de les ciutats amb el menor índex de municipalització. S’està externalitzant pràcticament tot i s’han tancat recursos vitals, com el Centre de Dia de la plaça d’Amèrica, l’únic de gestió municipal. Resulta paradoxal que els 400.000 euros destinats a aquest centre s’hagen derivat a l’Oficina del Cuidador: primer es desmantella el sistema públic de cures i, posteriorment, s’ofereix un psicòleg a la família sobrecarregada pel col·lapse d’aquest mateix sistema.\n\nAlacant és una ciutat amb una greu crisi d’habitatge.\n\nPrecisament, l’àrea d’Habitatge ha tingut una retallada del 30%, la qual cosa implica renunciar de facto a la construcció d’habitatge públic. N’és un exemple clar la promoció de 32 habitatges al carrer de Ceuta. En 2021, aquesta iniciativa es va projectar com a habitatge totalment públic, gràcies a l’esforç per aconseguir fons del Consell i del govern d’Espanya. Ara bé, actualment, el govern municipal ha rebutjat una subvenció d’un milió i mig d’euros i ha eliminat la partida pressupostària original. Aquests immobles passaran a ser habitatges de protecció pública (HPP) amb preus que oscil·len entre els 250.000 i els 316.000 euros, imports totalment inaccessibles per a la joventut i les famílies treballadores. Cal dir, a més, que el decret aprovat pel Consell de Mazón en setembre de 2024 ha eliminat els mecanismes de control i transparència en matèria d’habitatge. Amb la baixada dels barems econòmics i la falta d’inspectors, s’ha liberalitzat el sòl públic per a fer-lo atractiu a les constructores. Aquesta flexibilització permet que les mateixes empreses decidisquen qui accedeix als habitatges, i el control per part de l’administració és mínim. En definitiva, s’està utilitzant el sòl de la ciutat com un solar per a l’especulació, mercadejant amb un dret bàsic, mentre es buiden de contingut les institucions públiques.\n\nTanmateix, a la ciutat afecta també especialment l’habitatge turístic.\n\nEn aquest cas, proposem una mesura dràstica per a l’any 2028: no concedir ni renovar cap llicència d’apartament turístic a la ciutat. No es tracta de fer moratòries temporals, sinó d’extingir aquest model en l’àmbit de l’habitatge residencial. L’objectiu és que milers d’immobles destinats actualment al turisme tornen al mercat de lloguer habitual. El turisme ha d’allotjar-se en hotels, aparthotels o edificis dedicats exclusivament a eixa activitat, però les comunitats de veïns han de recuperar la seua funció original: servir per a viure-hi.\n\nQuines propostes més en matèria d’habitatge feu a Compromís?\n\nPer a revertir la situació actual d’emergència residencial, és imprescindible intervindre en el mercat. És absurd confiar que només amb la construcció de nous immobles baixaran els preus, quan la demanda és aclaparadora: hi ha 141 persones esperant per cada habitatge disponible. Així, doncs, la primera mesura urgent és declarar Alacant com a ciutat tensionada. Sense aquesta intervenció administrativa, els preus continuaran disparats. Ara com ara, hi ha unes 20.000 cases buides a la ciutat. Per a traure-les al mercat de lloguer, proposem un sistema de doble incentiu. D’una banda, per als xicotets propietaris, proposem que l’Ajuntament actue com a avalador i hi oferisca garanties jurídiques, patrimonials i econòmiques. Si un propietari lloga sa casa a través d’aquest programa, el consistori garanteix el cobrament de les rendes i la devolució de l’immoble en perfecte estat, quan finalitze el contracte. D’una altra, per als grans tenidors, aquests que posseïsquen més de cinc habitatges, s’hi ha d’aplicar una pressió fiscal dissuasiva, que faça que els isca més a compte traure’ls al mercat de lloguer: proposem duplicar la taxa de fem i triplicar l’IBI per a aquells que mantinguen els immobles tancats i obligar-los, així, a posar-los per a llogar. A diferència d’altres models, més conservadors i que pensem que no resoldrien el problema, nosaltres advoquem perquè l’Ajuntament exercisca el seu dret de tanteig i retracte. Davant l’operació de venda d’una finca sencera, per exemple, l’administració hi ha d’intervindre per interés general, bloquejar l’operació privada i adquirir l’immoble. Comprar edificis ja construïts és una via molt més àgil i efectiva que la construcció des de zero, que sol ser un procediment molt més llarg i complex. De fet, la construcció d’habitatge públic o protegit que s’està fent ara ha de canviar de paradigma: mai ha de passar a ser propietat de particulars. L’Ajuntament ha de mantindre el control permanent del parc públic i blindar-lo. I, és clar, s’han de revertir les modificacions normatives del Consell de Mazón, que faciliten l’especulació.\n\nCom es finançarien totes aquestes iniciatives?\n\nD’una banda, com hem vist, amb una gestió més eficient dels comptes públics, ja que el govern del PP, amb el suport de Vox, no fa inversions: la seua ineficiència fa que els diners necessaris per a fer polítiques públiques es queden en el romanent de tresoreria. D’una banda, amb una taxa turística municipal. És a dir, si el govern del PP amb el suport de Vox al Consell continua bloquejant una taxa turística autonòmica, el que ha de fer l’Ajuntament d’Alacant és actuar en tot allò en què té competències. Per exemple, el govern municipal té competències per a cobrar entrades per accedir als espais turístics: tothom que puge al castell, per exemple, que pague una taxa. Amb aquests diners, projectaríem habitatges, milloraríem els serveis públics, apostaríem per obrir centres de dia, biblioteques, centres comunitaris… Faríem la Revolució Alacant, ja que, en aquests últims vuit anys, els governs del PP no han fet res. Han sigut dos mandats perduts: ni un centre de salut ni una escola. Ho han bloquejat tot. No han fet res de res. Han sigut uns anys de gestió pèssima i de pagar diners als bancs. Hem arribat als 200 milions d’euros de romanent perquè no s’hi ha fet res. I per això els barris estan com estan: totalment abandonats.\n\nA més, hi ha hagut l’escàndol de les adjudicacions en la promoció d’habitatge públic de Les Naus, a la plata de Sant Joan.\n\nAquest cas és d’una obscenitat absoluta. Ens trobem davant una situació en què la mateixa regidora d’Urbanisme és l’encarregada de revisar tècnicament un expedient en el qual tant ella com el seu entorn directe hi tenen interessos. La llista de beneficiaris de la promoció és alarmant: arquitectes municipals, caps de servei, la cap de contractació, la directora general —qui ja va elegir una HPP anteriorment—, així com fills de regidors de Sant Vicent del Raspeig i d’altres municipis. Es tracta de persones vinculades al poder i molt ben posicionades en la ciutat. El canvi en la normativa, fet pel Consell de Mazón, que comentava adés, ha estat la clau per a convertir aquest procés en un colador, ja que s’hi ha eliminat qualsevol mecanisme de transparència, concurs o vigilància. Les conseqüències econòmiques per a la ciutat són nefastes. Per exemple, s’ha venut una parcel·la altament cotitzada per 6 milions d’euros, quan el seu valor de mercat podria haver arribat als 15 milions. A més, encara que el PP no vulga reconèixer-ho, aquests habitatges estan subvencionats: és impossible adquirir un habitatge en la Platja de Sant Joan amb pistes de pàdel, piscina, garatge i traster per 210.000 euros, quan en les promocions veïnes, amb menys serveis, els preus superen els 400.000 euros. El model imposat pel Partit Popular consisteix a cedir sòl públic amb la condició de construir habitatge protegit, però amb trampa, ja que hi ha, d’una banda, arbitrarietat: la constructora té la potestat de triar els beneficiaris; d’una altra, tenim la desregulació: es rebaixen els requisits d’accés per a facilitar que persones de l’entorn polític s’hi puguen beneficiar. I, finalment, el sistema permet els tripijocs posteriors, com la venda en negre, els canvis de titularitat irregulars o el lloguer fraudulent, tal com ja està ocorrent amb les HPP de Les Naus. Des de Compromís, per contra, defensem una transformació radical del model. Proposem que l’habitatge construït sobre sòl públic es mantinga sempre sota titularitat pública o es destine a lloguer assequible, per a garantir, així, que mai passe a mans privades per a l’especulació. Lamentablement, l’equip de govern no té intenció d’aprendre dels errors. Fa només uns dies, com deia, van tornar a modificar el format de la promoció del carrer de Ceuta, al barri de Sant Blai, per a transformar-la novament en HPP i continuar amb aquest sistema de venda de sòl públic al servei de l’especulació."} +{"url": "https://www.stcn.com/article/detail/3750646.html", "title": "永辉超市38亿追款获胜 , 王健林等承担连带保证责任", "publish_date": "2026-04-15T03:32:11Z", "full_text": "时隔一年有余,永辉超市(601933.SH)针对大连御锦贸易有限公司(简称“大连御锦”)未按约支付万达商管股份转让款而进行的追款申请,获终局裁决支持。\n\n4月14日晚间,永辉超市发布公告称,近日收到上海国际经济贸易仲裁委员会(上海国际仲裁中心)(简称“上国仲”)送达的裁决书。根据裁决,第一被申请人大连御锦需向永辉超市支付剩余股份转让价款和加速到期违约金等共计38.57亿元。第二被申请人王健林、第三被申请人孙喜双、第四被申请人大连一方集团对上述债务承担连带保证责任。\n\n公开资料显示,大连御锦的大股东为一方集团,孙喜双为一方集团实际控制人。孙喜双是王健林多年好友,他和一方集团经常出现在王健林的公司股东名单中。\n\n2018年,为了拓展优质物业,永辉超市以35.3亿元,从一方集团手中买下大连万达商管约3.9亿股股权。随着永辉超市业绩出现下滑,以至连年亏损,永辉超市又将其转让。\n\n2023年12月,永辉超市向大连御锦出售所持有的约3.9亿股大连万达商管股份。标的股份对应的股份转让价款超过45亿元,由大连御锦分八期支付。永辉超市称,本次交易目的是为了盘活公司资产,符合公司缩小投资规模战略。\n\n2024年7月26日,永辉超市与大连御锦、王健林、孙喜双、一方集团签订上述股份转让协议的补充协议。补充协议约定,本次转股的剩余股份转让价款合计38.39亿元,共分八期支付。其中,第四期股份转让价款的约定付款时间为2024年9月30日,约定付款金额为3亿元。王健林、孙喜双、一方集团将为剩余转让价款的支付提供担保。由此,王健林成为此次交易的“保人”之一。\n\n图片来源:界面图库\n\n但是大连御锦未按约定履行付款义务,王健林、孙喜双、一方集团也未承担担保责任,为此永辉超市向上国仲提起仲裁申请。\n\n\n\n永辉超市公告显示,经审理,上海国际经济贸易仲裁委员会仲裁庭作出裁决:大连御锦需向永辉超市支付剩余股份转让价款约36.39亿元,支付加速到期违约金2.18亿元,并支付律师费等,合计超过38.57亿元。\n\n永辉超市表示,本裁决为终局裁决,自作出之日起生效。但截至本公告披露日被申请人尚未履行相关义务,暂时无法确定本次仲裁事项对公司本期或期后利润的影响。公司将根据案件的后续进展及结果,依据有关会计准则的要求和实际情况进行相应的会计处理,对公司损益的影响以会计师年度审计确认后的结果为准。\n\n目前,永辉超市业绩承压。永辉超市发布的2025年业绩快报公告显示,报告期内,公司实现营业收入535.08亿元,较上年同期下降20.82%;归属于上市公司股东的净亏损为25.50亿元,较上年同期增亏74.01%;归属于上市公司股东的扣除非经常性损益的净亏损33.99亿元,较上年同期增亏41.00%。\n\n截至2025年底,永辉超市总资产304.82亿元,较报告期初减少28.70%;归属于上市公司股东的所有者权益18.59亿元,较报告期初减少58.13%。\n\n为了尽快盘活资产、回笼资金、聚焦主业,永辉超市仍在继续出售相关资产。3月23日,永辉超市发布公告称,董事会同意公司按与上海派慧科技有限公司协议约定的交易方案,以总价8000万元向其转让云金科技28.095%的股权。本次交易完成后,永辉超市不再持有云金科技的股权。目前该交易协议已生效。\n\n此次永辉超市38亿元追债获得裁决支持,在被申请人履行完相关义务后,有助于其进一步回笼资金。\n\n4月15日开盘,永辉超市股价为3.98元/股,涨幅为1.79%,市值为361.19亿元。"} +{"url": "https://china.qianlong.com/2026/0415/8654785.shtml", "title": "开局之年看中国 · 开放自贸港 : 从 机场流量 迈向 经济增量 - 千龙网 · 中国首都网", "publish_date": "2026-04-15T03:32:11Z", "full_text": "海南自贸港临空产业通过“航空特货超级运营人”项目,打造1公里内完成通关、查验、仓储、加工、离港的高效物流闭环,并依托免税政策、第七航权开放等制度优势,推动飞机维修、航空物流、低空经济等产业集聚发展,实现从“机场流量”向“经济增量”的实质性跃升。\n\n在海南自贸港绿色低碳国际合作示范项目启动区内,一片约800亩的土地正悄然改变区域航空物流格局。\n\n这里紧邻海口美兰国际机场未来三期跑道,规划建设一条400米地下通道,将园区与机场跑道直接相连——货物抵港后,一公里内即可完成通关、查验、仓储、加工、离港全流程。这是海南临空产业发展集团有限公司打造的“航空特货超级运营人”项目,也是临空经济新模式的试验场。\n\n“超级运营人”重塑物流效率\n\n何为“超级运营人”?航空特货超级运营人项目负责人张昊鹏14日接受中新网记者采访时给出明确答案:核心不在于仓库体量,而在于对特殊货物的全面统筹能力。项目聚焦“大、重、危、冷”特货——从航空发动机等超大尺寸货物,到锂电池、高度酒类等危险品,再到冰鲜水产品、重型货物,做到全品类货物的高效通关统筹。\n\n以进口三文鱼、金枪鱼为例,张昊鹏说,目前海南市场上的冰鲜产品多经广东转口,时效与成本不占优势。为此,该项目与美兰机场形成监管场地联动,未来冰鲜与肉类可直接在临空园区完成通关、集散、加工。\n\n园区将建设海南省首个前置货站,让货物在园区完成安检、查验、打板后,通过封闭货车直送停机坪,无需重复查验。“未来将通过下穿通道直连机场跑道,货物在抵港后1公里内,即可完成通关、查验、仓储、加工、离港的全部作业流程,实现‘机场里建园区’。”张昊鹏说。\n\n在冷链物流领域,挪威三文鱼、澳洲冰鲜牛肉未来可在园区完成通关查验和加工后,零关税进入内地市场。“我们的目标是让全球货物运进来、全国货物运出去,为海南打开一扇面向世界的窗口。”海南临空产业发展集团有限公司董事长、海口空港飞机维修工程有限公司董事长兼总经理王海烨说。\n\n产业链加速集聚\n\n海南临空产业的快速集聚,得益于自贸港开放政策的持续加持。航材和自用进口设备免关税、第七航权开放、86国免签等政策,使飞机维修产业的竞争优势从“单点优惠”转向“系统红利”。\n\n过去四年,美兰机场的飞机维修产业规模从80亩扩大至500亩,境外维修业务在2023年至2025年间增长了9倍。王海烨说,目前飞机维修客户覆盖泰国、越南、菲律宾等东南亚及中东市场,飞机喷漆业务订单已排满一年,大型机位满负荷运转。\n\n王海烨给记者算了一笔账:以飞机核心部件APU(辅助动力装置)维修为例,企业在海南采购进口设备,可节省7%的关税和13%的进口环节增值税,综合成本降低20.9%,单台设备节省约60万美元。\n\n在航空科技研发基地,中国民航科学技术研究院、民航二所、鹰之航集团等头部机构已率先入驻,围绕“临空+航空”“临空+低空”打造孵化创新与成果转化空间。\n\n临空产业链加速成型\n\n从“机场里建园区”到“下穿通道直连跑道”,从单台发动机维修节省数十万美元的成本账到境外业务增长9倍的开放账……海南临空产业正用一个个具体场景,诠释自贸港政策的含金量。\n\n王海烨表示,园区正打造涵盖绿色基础设施、绿色产业和绿色服务体系的低碳示范项目,重点发展飞机维修、航空物流、科技研发与高端制造、临空商贸、低空经济、航空配套服务等产业。\n\n截至目前,海南自贸港一站式飞机维修产业基地已累计完成约2800架次的飞机维修,境外业务覆盖20多个国家和地区。这片连接跑道与世界的试验田,正加速从“机场流量”迈向“经济增量”。(完)"} +{"url": "https://thanhtra.com.vn/doanh-nghiep-70CE54C31/phat-trien-nguon-nhan-luc-cong-nghiep-ban-dan-san-sang-cho-tuong-lai-7632e8f4b.html", "title": "Phát triển nguồn nhân lực công nghiệp bán dẫn , sẵn sàng cho tương lai", "publish_date": "2026-04-15T03:32:11Z", "full_text": "(Thanh tra) - Trước làn sóng dịch chuyển chuỗi cung ứng toàn cầu, Việt Nam đang đẩy mạnh đổi mới tư duy quản trị nguồn nhân lực chất lượng cao để nắm bắt cơ hội bứt phá trong ngành bán dẫn. Đây được xem là nền tảng quan trọng để Việt Nam phát triển các công nghệ chiến lược và nâng cao năng lực cạnh tranh quốc gia.\n\nNhu cầu về nhân lực bán dẫn có tay nghề cao đang tăng nhanh (Ảnh minh họa: TNI).\n\nBán dẫn là xương sống của nền kinh tế kỹ thuật số hiện đại, đóng vai trò quan trọng trong mọi quy trình, từ điện thoại thông minh, xe điện đến hệ thống năng lượng tái tạo. Không đứng ngoài xu hướng này, Việt Nam xác định công nghiệp bán dẫn là một trong những lĩnh vực ưu tiên trong phát triển kinh tế.\n\nNhu cầu về nhân lực bán dẫn có tay nghề cao đang tăng vọt, đặc biệt khi nhiều công ty sản xuất chip quốc tế lớn có kế hoạch tăng cường sự hiện diện của mình tại Việt Nam. Tuy vậy, đứng trước cơ hội vàng này, Việt Nam lại đang đối mặt với một khoảng trống lớn trong nhân lực có tay nghề.\n\nViệt Nam hiện đang có nhiều chính sách thiết thực để hiện thực hóa cam kết phát triển lực lượng lao động ngành bán dẫn. Quyết định số 1017/QĐ-TTg của Thủ tướng Chính phủ đề ra Chương trình phát triển nguồn nhân lực ngành công nghiệp bán dẫn đến năm 2030, tầm nhìn đến năm 2050.\n\nGần đây, Nghị quyết 71 - được Bộ Chính trị thông qua vào tháng 8 năm 2025, công nhận vai trò quan trọng của giáo dục nghề nghiệp (GDNN) trong việc trang bị cho lực lượng lao động của Việt Nam các kỹ năng cần thiết, đáp ứng nhu cầu chuyển đổi xanh và chuyển đổi số của nền kinh tế.\n\nNghị quyết này cũng nhấn mạnh việc cần cải thiện chất lượng các chương trình đào tạo hiện tại để nâng tầm vị thế của đào tạo nghề Việt Nam trên trường quốc tế.\n\nThời gian qua, chúng ta liên tục đón nhận các dự án có vốn đầu tư lớn từ những tập đoàn công nghệ hàng đầu thế giới như Intel, Samsung, Amkor, Hana Micron... Đã có hơn 50 doanh nghiệp quốc tế tham gia thị trường, tiêu biểu như Intel, Amkor, Hana Micron (đóng gói, kiểm thử); Marvell, Synopsys, Cadence (thiết kế chip)...\n\nBên cạnh đó, các doanh nghiệp trong nước như Viettel, FPT, VNChip… cũng đã tham gia. Việt Nam đang dồn sức cho ngành công nghệ bán dẫn, được coi là “xương sống” của kinh tế số với trọng tâm là phát triển nguồn nhân lực.\n\nTuy nhiên, ngành công nghiệp bán dẫn vẫn còn khá mới mẻ với Việt Nam, chủ yếu thực hiện khâu thiết kế, kiểm thử và đóng gói chip, chưa có nhà máy chế tạo quy mô lớn. Để hiện thực hóa mục tiêu trở thành mắt xích quan trọng trong hệ sinh thái công nghệ cao, việc giải quyết bài toán thiếu hụt nguồn nhân lực chất lượng cao và khắc phục sự chênh lệch về kỹ năng đang trở thành yêu cầu cấp thiết hơn bao giờ hết.\n\nTrước thực tế này, Chính phủ đặt mục tiêu đào tạo 50 nghìn kỹ sư vi mạch từ nay đến năm 2030. Trong số này, khoảng 15 nghìn người sẽ phục vụ cho thiết kế vi mạch, 35 nghìn người sẽ đảm trách các lĩnh vực sản xuất, đóng gói và kiểm thử sản phẩm.\n\nNgoài ra, sẽ có thêm 5.000 chuyên gia trí tuệ nhân tạo (AI) để hỗ trợ và nâng tầm lĩnh vực bán dẫn, cùng 1.300 giảng viên tại các trường đại học và viện nghiên cứu được bồi dưỡng chuyên sâu, tạo nên đội ngũ giảng dạy tinh hoa, sẵn sàng đưa Việt Nam vươn lên trong cuộc đua công nghệ toàn cầu.\n\nHàng loạt trường đại học mở ngành mới, nhiều chính sách ưu đãi được triển khai, thu hút sinh viên. Đây được xem là cơ hội vàng cho cả người học lẫn cơ sở đào tạo.\n\nTheo Bộ GD&ĐT, có khoảng 35 cơ sở giáo dục đại học đã và đang tham gia đào tạo lĩnh vực này, dự kiến số lượng sẽ tăng đáng kể trong 2-3 năm tới khi các trường cao đẳng nghề, các dự án hợp tác đào tạo với doanh nghiệp cùng lúc vào cuộc.\n\nBa trường thuộc Đại học Quốc gia TPHCM (Trường đại học Bách khoa, Trường đại học Công nghệ thông tin và Trường đại học Khoa học tự nhiên) chính thức mở nhóm ngành công nghệ vi mạch bán dẫn, dự kiến đến năm 2027 đào tạo thêm 1 nghìn kỹ sư, nâng tổng số sinh viên ngành liên quan lên khoảng 6 nghìn người.\n\nDù vậy, khoảng cách giữa kỳ vọng và thực tại vẫn còn khá lớn, nguồn cung hiện tại vẫn chưa thể đáp ứng nhu cầu ngày càng tăng của các doanh nghiệp. Ông Felix Weidenkaff, Chuyên gia Chính sách thị trường lao động và việc làm của Tổ chức Lao động Quốc tế (ILO), nhận định, đối với ngành công nghiệp bán dẫn, chương trình đào tạo tại nhiều cơ sở giáo dục vẫn tồn tại khoảng cách so với thực tế thị trường.\n\nSinh viên thường thiếu hụt các kỹ năng thực hành chuyên sâu trong thiết kế vi mạch, nghiên cứu và phát triển (R&D) hay vận hành dây chuyền sản xuất hiện đại. Điều này dẫn đến tình trạng doanh nghiệp phải mất thêm thời gian và chi phí để đào tạo lại sau tuyển dụng.\n\nViệt Nam đang đối mặt với một khoảng trống lớn về nhân lực ngành bán dẫn có tay nghề (Ảnh minh họa: TNI).\n\nĐể giải quyết bài toán nhân lực, các chuyên gia khẳng định không thể chỉ dựa vào nỗ lực đơn lẻ của từng đơn vị mà cần một chiến lược quản trị nguồn nhân lực bài bản và đồng bộ. Ông Nguyễn Phúc Vinh, Giám đốc kỹ thuật Synopsys Việt Nam cho rằng: “Nhu cầu tuyển dụng kỹ sư thiết kế vi mạch rất lớn, nguồn cung hiện tại chưa đáp ứng đủ. Thực tế, ngay cả sinh viên năm thứ 3 cũng đã được các doanh nghiệp săn đón về làm việc, nhất là ở lĩnh vực thiết kế vật lý và kiểm thử chip. Tuy nhiên, cơ hội rộng mở nhưng ngành vi mạch bán dẫn cũng đòi hỏi rất cao ở người học về năng lực và tố chất”.\n\nTS. Chử Đức Hoàng, Chánh Văn phòng Quỹ Đổi mới Công nghệ Quốc gia, Bộ KH&CN cho rằng, Việt Nam muốn phát triển ngành công nghiệp bán dẫn cần xây dựng hệ sinh thái đầy đủ, không chỉ về nhân lực mà còn cả hạ tầng, logistics và chuỗi cung ứng. Mục tiêu đào tạo 50.000 kỹ sư bán dẫn trong vòng 5 đến 10 năm tới là thách thức lớn nếu thiếu nền tảng chiến lược và hành động cụ thể ngay từ bây giờ.\n\nVì vậy, theo các chuyên gia, Chính phủ tiếp tục ban hành chính sách đặc thù thu hút, hỗ trợ nhân tài; các bộ, ngành cụ thể hóa bằng các văn bản hướng dẫn, trong khi doanh nghiệp cần tham gia sâu vào quá trình đào tạo và phát triển nguồn nhân lực."} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-14/Full_text/full_text_macro_central_banks.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-14/Full_text/full_text_macro_central_banks.jsonl new file mode 100644 index 0000000..8644aac --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-14/Full_text/full_text_macro_central_banks.jsonl @@ -0,0 +1,6 @@ +{"url": "https://baomoi.com/gia-vang-ngay-15-4-bang-gia-tai-cac-cong-ty-vang-bac-da-quy-c54939126.epi", "title": "Giá vàng ngày 15 / 4 : Bảng giá tại các công ty vàng bạc đá quý", "publish_date": "2026-04-15T03:28:27Z", "full_text": "Vàng trang sức. (Ảnh: Phan Phương/TTXVN)\n\nGiá vàng thế giới tăng khoảng 2% lên 4.831,78 USD/ounce nhờ đồng USD yếu và kỳ vọng các cuộc đàm phán Mỹ-Iran sẽ được nối lại.\n\nChuyên gia Bob Haberkorn tại RJO Futures nhận định nhà đầu tư đang chuyển hướng quay lại kim loại quý thay vì giữ tiền mặt như giai đoạn đầu xung đột.\n\nCác nhà phân tích tại Commerzbank cho rằng chừng nào Cục Dự trữ Liên bang Mỹ (Fed) chưa có dấu hiệu tăng lãi suất, giá vàng sẽ rất khó giảm sâu. Hiện các nhà giao dịch dự báo chỉ có khoảng 33% khả năng Fed sẽ cắt giảm lãi suất trong năm nay, một con số thấp hơn nhiều so với kỳ vọng trước khi diễn ra xung đột tại Trung Đông.\n\nTại Việt Nam, vào sáng 15/4, công ty Vàng bạc đá quý Sài Gòn niêm yết giá vàng SJC tại thị trường Hà Nội ở mức 173,00-175,50 triệu đồng/lượng (mua vào-bán ra).\n\nDưới đây là bảng giá vàng tại một số công ty vàng bạc đá quý trong nước sáng 15/4:\n\nGiá vàng tại Công ty Trách nhiệm hữu hạn Một thành viên Vàng bạc đá quý Sài Gòn (SJC):\n\nGiá vàng tại Công ty Cổ phần Đầu tư vàng Phú Quý:"} +{"url": "http://www.europesun.com/news/278983984/producer-prices-rise-sharply-on-energy-surge-from-iran-war", "title": "Producer prices rise sharply on energy surge from Iran war", "publish_date": "2026-04-15T03:28:27Z", "full_text": "WASHINGTON, D.C.: Rising energy costs linked to the Iran war pushed U.S. wholesale prices sharply higher in March, adding to inflation concerns and complicating the Federal Reserve's policy outlook.\n\nOn Tuesday, the Labor Department said its producer price index (PPI), which tracks inflation before it reaches consumers, rose 0.5 percent from February and 4 percent from a year earlier, the largest annual increase in more than three years.\n\nEnergy prices surged 8.5 percent over the month, driving much of the increase.\n\nExcluding volatile food and energy components, core producer prices rose a more modest 0.1 percent from February and 3.8 percent year-on-year. Overall gains were smaller than economists had expected.\n\nThe data adds pressure on Federal Reserve policymakers, who are already grappling with persistent inflation and calls from President Donald Trump to cut interest rates. Some officials, however, are considering rate hikes as rising energy costs threaten to keep inflation elevated.\n\nFood prices offered some relief, falling 0.3 percent in March after a sharp 2.4 percent increase in February.\n\nWholesale prices are closely watched as an early indicator of consumer inflation. Economists also track them because some components, including healthcare and financial services, feed into the Fed's preferred inflation gauge, the personal consumption expenditures (PCE) price index.\n\n\"The decline in food prices is overdue, and welcome news for everyone,\" said Carl Weinberg, chief economist at High Frequency Economics. \"Food price increases are at the core of political arguments over affordability.\"\n\nRecent consumer data has already pointed to mounting inflation pressures. The Labor Department reported last week that consumer prices rose 3.3 percent in March from a year earlier, the biggest annual increase since May 2024, while monthly prices jumped 0.9 percent, the largest gain in nearly four years.\n\nThe broader energy shock is also reshaping global demand patterns. The International Energy Agency said the war in Iran could lead to an annual decline in oil demand for the first time since the COVID-19 pandemic.\n\nThe agency forecast demand would fall by 80,000 barrels per day this year, a sharp reversal from its earlier projection of an 850,000-barrel-per-day increase before the conflict began.\n\nDemand dropped particularly sharply in March due to attacks on energy infrastructure and the closure of the Strait of Hormuz, with the IEA expecting a 1.5 million barrels per day decline in the current quarter.\n\nWhile the initial drop has been concentrated in the Middle East and Asia-Pacific, the agency said that weakening demand is likely to spread as higher prices and supply constraints weigh on consumption."} +{"url": "https://zetatijuana.com/2026/04/banamex-tacha-de-erraticos-los-pronosticos-de-banxico-y-la-shcp-sobre-crecimiento-e-inflacion/", "title": "Banamex tacha de erráticos los pronósticos de Banxico y la SHCP sobre crecimiento e inflación", "publish_date": "2026-04-15T03:28:27Z", "full_text": "El área de Estudios Económicos de Banamex calificó el 14 de abril de 2026 como “erráticos” los pronósticos del Banco de México (Banxico) y la Secretaría de Hacienda y Crédito Público (SHCP) respecto al crecimiento económico del país y la tasa esperada de inflación, y sostuvo que ningún analista del mercado les otorga credibilidad.\n\nSergio Kurczyn, director de Estudios Económicos de Banamex, afirmó durante el foro Diálogos Banamex que Banxico no logra reducir las tasas de interés en el momento adecuado ni con la metodología correcta para ejecutar una política anticíclica efectiva. Según Kurczyn, los análisis de riesgos de la institución y la forma en que utiliza sus proyecciones son incorrectos. “Nadie le cree a Banxico sus pronósticos más allá de seis meses, nosotros tampoco”, señaló el directivo, quien agregó que la medición del grado de holgura —es decir, el PIB potencial frente al PIB observado— también presenta inconsistencias.\n\nPublicidad\n\nEl analista sostuvo que Banxico incurrió en un error al recortar su tasa de referencia a 6.75 por ciento en su más reciente decisión de política monetaria. Según Kurczyn, si la institución tiene como objetivo alcanzar una inflación de 3 por ciento —meta que mantiene desde hace dos décadas sin concretarla—, no debió haber reducido la tasa y debió mantenerla en 10 por ciento. “Desde hace 15 años su verdadero objetivo no es 3 sino 4, entonces más allá de los detalles de exactamente cuánto baja la tasa, ése es el costo de que la credibilidad de este Banxico y de los otros Banxicos de antes, que no logran bajar las tasas de interés cuando se debe, como se debe, para hacer verdadera política anticíclica”, recalcó.\n\nRespecto al crecimiento económico, Banamex descartó que México alcance en 2026 la expansión de 3 por ciento proyectada por la SHCP, y estimó en cambio una tasa de 1.6 por ciento para ese año. Iván Arias, director de Estudios Económicos de la misma institución, advirtió que la previsión de recorte al gasto programable para 2027 también será difícil de ejecutar. Según Arias, la SHCP calcula un crecimiento de 2.4 por ciento para 2027, el Fondo Monetario Internacional (FMI) estima 2.2 por ciento, mientras que Banamex sitúa su proyección en 1.6 por ciento para ese mismo ejercicio fiscal.\n\nPublicidad\n\nArias señaló que el recorte al gasto programable equivalente a 1.6 por ciento del Producto Interno Bruto (PIB) planteado por la SHCP para 2027 es “muy fuerte” y de difícil cumplimiento, dado el volumen de compromisos de gasto vigentes y los reducidos márgenes de ajuste disponibles. Según el directivo, bajo los supuestos de Banamex, el recorte efectivo oscilaría entre 0.8 y 0.9 por ciento del PIB, cifra significativamente menor a la meta oficial."} +{"url": "https://baotintuc.vn/kinh-te/gia-vang-sang-154-dong-loat-tang-manh-20260415082802323.htm", "title": "Giá vàng hôm nay 15 / 4 đồng loạt tăng mạnh", "publish_date": "2026-04-15T03:28:27Z", "full_text": "Lúc 9 giờ, Công ty TNHH MTV Vàng bạc đá quý Sài Gòn SJC niêm yết vàng miếng ở mức 173 - 175,5 triệu đồng/lượng (mua vào - bán ra), tăng 2,5 triệu đồng/lượng ở cả hai chiều mua vào, bán ra.\n\nTương tự, các thương hiệu lớn ở Hà Nội như Bảo Tín Minh Châu, DOJI cũng niêm yết giá vàng miếng SJC ở mức này. Trong khi đó, Phú Quý giao dịch vàng miếng SJC ở mức 172,5 - 175,5 triệu đồng/lượng (mua vào - bán ra).\n\nĐối với vàng nhẫn tròn trơn 9999, Bảo Tín Minh Châu niêm yết ở mức 172 - 175 triệu đồng/lượng (mua vào - bán ra), tăng 2,3 triệu đồng/lượng ở cả hai chiều mua vào, bán ra. Phú Quý cũng niêm yết giá vàng nhẫn ở mức này.\n\nTại DOJI, vàng nhẫn 9999 giao dịch ở mức 172,5 - 175,5 triệu đồng/lượng (mua vào - bán ra). Giá vàng trong nước hiện vẫn đang bám sát xu hướng của giá thế giới.\n\nSản phẩm vàng nhẫn tròn trơn 9999 được người tiêu dùng ưa chuộng.\n\nCùng thời điểm, giá vàng thế giới giao dịch quanh mức 4.850 USD/ounce tăng gần 100 USD so với sáng 14/4. Nếu quy đổi theo tỷ giá Vietcombank, mỗi lượng vàng thế giới có giá khoảng 154 triệu đồng. Trong phiên, giá vàng thế giới dao động trong khoảng 4.751 USD/ounce đến 4.871 USD/ounce.\n\nĐà tăng của giá vàng thế giới được hỗ trợ bởi sự suy yếu của đồng USD khi kỳ vọng về khả năng nối lại đàm phán giữa Mỹ và Iran gia tăng. Đồng bạc xanh đã giảm xuống mức thấp nhất trong khoảng 6 tuần, trong khi giá dầu cũng hạ nhiệt so với các phiên trước, góp phần làm dịu bớt áp lực lạm phát và cải thiện tâm lý đối với kim loại quý.\n\nTuy vậy, đà tăng của kim loại quý vẫn phần nào bị hạn chế khi triển vọng chính sách tiền tệ của Cục Dự trữ Liên bang Mỹ (Fed) chưa rõ ràng. Dù một số dữ liệu lạm phát như chỉ số giá sản xuất (PPI) thấp hơn kỳ vọng, thị trường vẫn nghiêng về khả năng Fed duy trì lãi suất ở mức cao trong thời gian dài, trong bối cảnh rủi ro lạm phát liên quan đến giá năng lượng vẫn hiện hữu."} +{"url": "https://www.thestar.com.my/business/insight/2026/04/15/oil-shock-is-here-are-businessesprepared", "title": "Oil shock is here : Are businesses prepared ? ", "publish_date": "2026-04-15T03:28:27Z", "full_text": "OVER the past one month, escalation in the Middle East conflict sent shockwaves through global energy markets, driving oil prices higher, increasing operational costs and causing disruption to supply chains.\n\nThe biggest risks that the current geopolitical environment-inflicted soaring energy prices pose to businesses are shocks, volatility and uncertainty.\n\nRising oil prices have threatened micro, small and medium enterprises’ (MSMEs) viability.\n\nThe surge in global oil prices towards US$120 per barrel and petrol as well as diesel prices are placing enormous operating cost pressures on businesses, especially SMEs.\n\nSignificant increase in fuel prices cascade through the entire economy – freight, logistics, construction materials, high-energy manufacturing, retail supply chains and hospitality.\n\nThe ripple effects are unavoidable: fuel affects production, logistics, and raw materials, amplifies existing vulnerabilities in supply chains, and all of these influence costs, margins and profitability as well as business planning budgets.\n\nBeneath this operational pressures lie a deeper and more uncomfortable question: Is there a way out? How to build business resilience?\n\nBusinesses are facing five simultaneous pressures as follows:\n\n> Direct and indirect cost shocks. Rising fuel costs increase operating costs across the logistics, construction, manufacturing, retail and hospitality sectors.\n\nIndirect costs are escalating due to severely disrupted maritime traffic, carriers rerouting and extending transit times, cancellation of bookings, and significant increase in freight surcharges, causing “cascading” effects on global supply chains. Suppliers’ price increases quickly erode businesses’ already thin margins.\n\n> Rising raw material costs. Increasing fuel prices are significantly driving up raw material costs, causing a ripple effect in many industries such as contractors, construction, manufacturing, food processing, and heavy machinery, as well as services-related tourism and hospitality sectors.\n\nThe surge in diesel prices increases transport and logistical costs, while also boosting production costs for materials with high embedded energy like cement, steel, chemical products, and machinery operations.\n\n> “Stagflation” squeeze. While businesses have incurred increased operating costs, consumers’ discretionary spending will weaken as households cope with high living costs.\n\nThat means businesses face higher cost expenses at the same time revenue growth slows.\n\n> Margin compression. Rising fuel costs can squeeze business margins as companies cannot fully pass on increasing input costs to consumers, often due to low market power, fierce competition, or long-term fixed-price contracts.\n\nSome companies preserve their margin through small, incremental rate adjustments without causing severe sticker shock for customers.\n\n> Cash flow tightness. Many MSMEs facing rising fuel costs and increasing operating costs will experience cash flow tightness and may face difficulty servicing their loans.\n\nUncertainty has significantly clouded business visibility in the current intense geopolitical landscape.\n\nAmong the dampening factors are surging fuel costs, transportation/logistic costs, raw material costs due to the supply chains disruption, shipping costs and air freight rates.\n\nRaw materials and inputs prices are a critical consideration for firms when making production and pricing decisions.\n\nHeightened uncertainties concerning the supply of raw materials and input prices, the scale and duration of the oil shock, as well as supply chain disruptions have resulted in both suppliers and manufacturers taking a cautious stance in committing to ordering and purchasing.\n\nThere are cases of suppliers being unable to provide pricing of raw materials due to cost fluctuations on a weekly basis, and hence, not taking new orders, pending more clarity.\n\nSome suppliers have sent new price increase notices to their customers while some have already increased prices.\n\nSome manufacturers have adopted a “wait and see” approach, not committing to large purchases, and a just-in-time inventory as they do not want to lock in raw materials at higher prices and be caught with high-cost inventory.\n\nThey are hoping that the war would de-escalate and can purchase new deliveries at lower wholesale prices.\n\nSMEs’ viability is being shaped by cumulative cost pressures. In 2024 to 2025, they were already operating on tight margins, dealing with rising business costs, including wages, new taxes, regulatory and compliance costs.\n\nFuel is another critical input layered on top of that. When multiple cost pressures such as rising fuel prices, raw materials, transportation, including shipping and insurance costs move at once, it reduces the SMEs’ buffer to absorb shocks.\n\nMany are already absorbing higher costs, passing cost increases through where they can. When those costs rise quickly, the pressure flows directly into MSMEs’ margins.\n\nWhen these pressures compound, it can delay investments and reduce hiring. And, in some cases, it can push otherwise viable businesses into cash flow and financial distress.\n\nThe Associated Chinese Chambers of Commerce and Industry of Malaysia’s Quick Take Survey noted 51.2% of the respondents indicated that total cost will increase between 6% and 20%, and 20.2% will experience cost increases by more than 20%.\n\nClose to 46.3% of total respondents will experience “moderate and significant deterioration” in their cash flow. The overall impact on a company’s profitability varies between a slight decrease (as indicated by 31% of respondents), a moderate decrease (33%) and a significant decrease (26.6%).\n\nMost respondents have perceived “moderate to significant deterioration” of business outlook over the next three to six months if the oil shock persists.\n\nThe results indicated that 31% of total respondents can maintain their business operations between three and six months before requiring structural downsizing or seeking additional financing.\n\nThe reality is MSMEs have limited ability to manage soaring fuel prices and supply chains disruption on their own.\n\nUnlike larger corporations with strong balance sheets that can hedge fuel costs or absorb supply chain shocks, smaller operators and SMEs often feel the impact within weeks.\n\nBusiness survivability is indeed crucial. For many enterprises, particularly MSMEs which had suffered sustained increases in operational costs over the past two years, the primary goal is to avoid financial distress or closure.\n\nThe current period of global uncertainty and challenging situation highlights the need for a more stable and supportive operating environment.\n\nBusinesses need lower costs, simpler compliance and the confidence in the government’s ability to navigate this oil shock through a mixture of targeted subsidies, and strengthening structural resilience.\n\nMeasures that can help to ease business costs burden and relieve cash flow include:\n\n> Targeted Repayment Assistance Programme, including loans restructuring for affected MSMES for a specific period.\n\n> Lower service tax rate (currently at between 6% and 8%) imposed on the expanded services (rental/leasing, and professional fees, construction, private healthcare, and education) for a period of three months, subject to review every three months depending on the prevailing situation.\n\n> Lower the current 85% minimum of the estimated tax for the preceding year (CP204) to 50%, suspend the 10% penalty if the final tax exceeds the threshold by more than 30%.\n\nIn addition, to allow any overpaid tax to be offset against the current year’s liabilities, given that businesses have limited visibility on their current performance.\n\n> Review time of use (ToU) electricity tariffs and raise higher the eligibility threshold under the energy efficiency incentive to at least 600kWh from 200kWh to encourage broader energy savings for MSMEs.\n\nThe government should provide targeted support for SMEs to adopt energy-efficient machinery through tax incentives and soft loans, aiming to reduce dependence on fossil fuels and lower operational costs, supporting long-term structural transformation. Other measures to consider are:\n\n> Reducing sales and service tax (SST) on energy products, or implementing “green levies” tax breaks.\n\nThese include electrical equipment, pumps, compressors, boilers, converters, and furnaces used in manufacturing processes, which are subject to a 5% to 10% sales tax.\n\n> A full SST waiver on solar equipment.\n\n> Provide accelerated depreciation, which allows firms to deduct the full cost of energy-efficient equipment from their taxable income in the year of purchase.\n\n> Provide soft interest rate loans for firms to invest in energy-efficient machinery and equipment, automation technology, and advanced motors.\n\nBusinesses can adopt the following strategies for managing fuel price fluctuations:\n\n> Implement a well-structured fuel surcharge formula based on fuel price variations to be reviewed regularly, protecting profit margins while communicating surcharge clearly to customers to maintain transparency.\n\n> Optimise efficient route planning to minimise fuel consumption by reducing unnecessary mileage and idle time.\n\n> Tracking and analysing fuel usage to identify inefficiencies and opportunities for cost reduction.\n\n> Investing in fuel efficiency technology, fuel-efficient vehicles and alternative fuel technologies to help reduce dependency on fluctuating fuel prices.\n\n> Implement strategic pricing which entails small, incremental rate adjustments to offset rising expenses without causing severe sticker shock for customers.\n\n> Renegotiate supplier terms, consolidating orders or exploring new supply chains to minimise disruptions and yield cost efficiencies.\n\nLee Heng Guie is the executive director of the Socio-Economic Research Centre. The views expressed here are the writer’s own."} +{"url": "https://market.bisnis.com/read/20260415/93/1966735/rupiah-hari-ini-154-dibuka-menguat-ke-rp17126-per-dolar-as", "title": "Rupiah Hari Ini ( 15 / 4 ) Dibuka Menguat ke Rp17 . 126 per dolar AS", "publish_date": "2026-04-15T03:28:27Z", "full_text": "Rupiah menguat ke Rp17.126 per dolar AS pada 15 April 2026, didorong pelemahan dolar AS akibat sentimen eksternal dan optimisme pasar.\n\nBisnis.com, JAKARTA — Nilai tukar rupiah terhadap dolar AS hari ini, Rabu (15/4/2026) dibuka menguat pada level Rp17.126 sejalan dengan kombinasi tekanan eksternal yang mendorong pelemahan dolar AS.\n\nBerdasarkan data analis Doo Financial Futures pada pukul 09.10 WIB, nilai tukar rupiah dibuka menguat tipis sebesar 0,01% menuju level Rp17.126.\n\nPenguatan mata uang Garuda terhadap dolar AS juga diikuti baht Thailand yang terapresiasi sebesar 0,37%, peso Filipina terhadap dolar AS menguat 0,05%, ringgit Malaysia menguat sebesar 0,18%.\n\nWon Korea terhadap dolar AS ikut naik sebesar 0,05%, dolar Taiwan juga naik 0,06%, dan dolar Singapura naik 0,02%.\n\nNamun demikian sejumlah mata uang Asia lainnya terpantau melemah. Rupee India terhadap dolar AS turun 0,79%, diikuti mata uang yen Jepang terhadap dolar AS melemah 0,08%, yuan China melemah 0,02%.\n\nSementara itu, dolar Hong Kong terhadap dolar AS juga terpantau masih melemah 0,04%.\n\nAnalis Doo Financial Futures, Lukman Leong mengatakan nilai tukar rupiah diperkirakan berpotensi menguat terhadap dolar Amerika Serikat (AS) pada perdagangan hari ini, seiring tekanan yang masih membayangi mata uang Negeri Paman Sam di pasar global.\n\nPelemahan dolar AS dipicu oleh kombinasi sentimen eksternal, mulai dari turunnya harga minyak mentah dunia hingga meningkatnya optimisme pasar terhadap peluang meredanya tensi geopolitik.\n\nHarapan bahwa AS dan Iran akan kembali melanjutkan perundingan damai mendorong sikap risk-on di kalangan investor, sehingga aset-aset berisiko seperti mata uang negara berkembang menjadi lebih menarik.\n\nSelain itu, data inflasi produsen (producer price index/PPI) AS yang tercatat lebih rendah dari ekspektasi turut menekan dolar AS. Kondisi ini memperkuat ekspektasi bahwa tekanan inflasi di AS mulai mereda, yang berpotensi memengaruhi arah kebijakan moneter ke depan.\n\nMeski demikian, penguatan rupiah diperkirakan tidak akan berlangsung signifikan. Sentimen domestik yang masih cenderung lemah menjadi faktor penahan laju apresiasi.\n\nPelaku pasar juga memilih untuk bersikap hati-hati sambil menunggu hasil Rapat Dewan Gubernur Bank Indonesia (RDG BI) yang akan diumumkan sore ini.\n\nDengan berbagai sentimen tersebut, rupiah diproyeksikan bergerak dalam kisaran Rp17.050 hingga Rp17.200 per dolar AS pada perdagangan hari ini."} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-14/Full_text/full_text_macro_geopolitics_risk.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-14/Full_text/full_text_macro_geopolitics_risk.jsonl new file mode 100644 index 0000000..294e22e --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-14/Full_text/full_text_macro_geopolitics_risk.jsonl @@ -0,0 +1,6 @@ +{"url": "https://radaronline.com/p/trump-assassination-fears-pope-conflict-iran-war/", "title": "Trump Bible - Thumper Assassination Fears Explode Amid Bust - Up With Pope", "publish_date": "2026-04-15T03:31:19Z", "full_text": "Trump, however, has continued to criticize the pontiff in increasingly personal terms. He described Leo as \"weak on crime and terrible on foreign policy\" and rejected calls to moderate his tone.\n\nThe president also dismissed backlash over his AI Christ image, claiming it had been misinterpreted and was intended to show him as a healer rather than a religious figure.\n\nHe said: \"I did post it and I thought it was me as a doctor and had to do with the Red Cross. It's supposed to be me as a doctor, making people better. And I do make people better. I make people a lot better.\"\n\nThe controversy has left swathes of Trump's conservative Christian base deeply unsettled, despite them historically being a cornerstone of his political support. Religious commentators and clergy have also slammed the imagery and rhetoric, with some describing it as offensive and inappropriate.\n\nAnalysts said the situation is unusual in its intensity, marking a rare public breakdown between a sitting US president and the head of the Catholic Church. The feud has also drawn international attention, with political and religious figures weighing in on both sides.\n\nVice President JD Vance, a Catholic convert, defended Trump's position, suggesting disagreements between political and religious leaders were not uncommon. But the unholy row brewing over Trump's messiah comparison is continuing to fuel concern among observers about its broader implications.\n\nThe dispute comes as Pope Leo continues to advocate for an end to the Iran conflict, warning against what he has described as a \"delusion of omnipotence\" driving global tensions, while Trump has maintained a hardline stance on foreign policy and national security."} +{"url": "https://www.whtimes.co.uk/news/national/26021871.half-households-energy-credit-end-winter---poll/", "title": "More than half of households in energy credit at end of winter – poll", "publish_date": "2026-04-15T03:31:19Z", "full_text": "Energy suppliers are holding £3 billion of households’ money built up by direct debit but not used over the winter, a survey for comparison site Uswitch found.\n\nThe average home that is in credit has built up almost £200 with their supplier, according to the poll.\n\nOverall, credit is £179 million higher than last year, which Uswitch said could be due to a milder winter than expected and direct debits not changing as quickly as energy rates.\n\nHouseholds should ideally end the winter with little to no credit, having used it during the colder months.\n\nThey should re-build their credit during the spring and summer when energy usage is generally lower.\n\nHowever, 16 million households (57%) have credit with their energy supplier at the end of this winter, according to the survey.\n\nUswitch said 63% of households on fixed deals were currently in credit, compared with 56% of those on standard variable tariffs.\n\nOne in 10 consumers (12%) have balances over £300, and 4% are more than £500 in credit.\n\nThree in 10 households with credit (31%) intend to ask for some or all of it to be refunded, but 63% plan to leave the money with their supplier to try to reduce their monthly payments.\n\nJust 7% will ask their supplier to return their full balance, while a quarter (24%) will ask their supplier to return some of it, the poll suggests.\n\nUswitch said it advised consumers to keep around two months of average monthly payments as credit in their energy account to guard against higher costs in the coldest months of the year.\n\nIt also urged households without a working smart meter to regularly supply meter readings to keep their account balance and direct debit level accurate to avoid overpaying.\n\nHousehold energy prices fell by 7% from April 1 in a “short-lived respite” for households already braced for a predicted 18% hike from July.\n\nOfgem’s price cap dropped from £1,758 to £1,641 – a reduction of £117 or around £10 a month for the average household using both electricity and gas.\n\nThis is an 11% fall year on year, but still £600 more than bills were in the winter of 2020 to 2021.\n\nThe reduction is lower than the average £150 cut to bills pledged by the Chancellor in November, when she moved 75% of the cost of the renewables obligation from household bills onto general taxation and scrapped the energy company obligation (Eco) scheme.\n\nAnd it comes amid increasing concern about the amount energy bills could rise by from July as a result of the Middle East conflict, with latest predictions from Cornwall Insight suggesting this could be 18% or £288 a year – to almost £900 above pre-crisis levels.\n\nUswitch energy spokesman Ben Gallizzi said: “More than half of UK households are coming out of the coldest time of year with credit in their energy accounts.\n\n“At this time of year households should generally have used up most of their credit over the colder winter months. However, it is advisable to keep about two months’ worth of payments in energy credit to cover higher winter bills ahead.\n\n“With energy prices predicted to rise in July, households with more than two months of energy credit could consider leaving some of it with their supplier to take some of the sting out of winter bills later this year.”\n\nOpinium surveyed 2,021 energy bill-payers between March 24-30."} +{"url": "https://www.wharfedaleobserver.co.uk/news/national/26021877.chancellor-hold-talks-us-counterpart-strong-criticism-iran-war/", "title": "Chancellor to hold talks with US counterpart after strong criticism of Iran war", "publish_date": "2026-04-15T03:31:19Z", "full_text": "The comments by US treasury secretary Scott Bessent put him at odds with the Chancellor, who has gone public with her anger and frustration at the “folly” of America’s actions in the Middle East and its financial fallout on families.\n\nThe pair were due to hold face-to-face talks in Washington DC on Wednesday during the spring meetings of the International Monetary Fund, which will be dominated by the ongoing crisis in the Gulf, which has inflicted a global economic shock and sent energy prices soaring.\n\nUS treasury secretary Scott Bessent (James Manning/PA)\n\nPrior to the Chancellor heading stateside, the influential financial body slashed Britain’s economic growth forecast as a result of the conflict and warned a worldwide recession could be a “close call” in a severe scenario.\n\nHowever, despite the “large” jolt to the global economy, Bank of England governor Andrew Bailey said the UK was much better placed to deal with it because of its resilient banking system, forged in the wake of the 2007-09 financial crisis.\n\nMeanwhile, President Donald Trump has said a second round of talks between the US and Iran could happen “over the next two days”, after negotiations at the weekend collapsed.\n\nTehran’s nuclear ambitions were a key sticking point.\n\nDiplomats have been working behind the scenes as the US imposed its blockade of Iranian ports and Tehran threatened retaliatory strikes across the region, amid a shaky ceasefire.\n\nAt the same time Prime Minister Sir Keir Starmer is seeking to co-ordinate international efforts to ensure the strategic Strait of Hormuz can remain open to shipping after hostilities end.\n\nThe critical waterway, used to move one fifth of the world’s oil and gas supplies, has become a major flashpoint in the conflict, with its effective closure by Iran hiking the cost of fuel, food and other basic goods.\n\nHowever, responding to the spike in prices, Mr Bessent said “a small bit of economic pain for a few weeks is worth taking off the incalculable tail risk of either a nuclear Iran or a nuclear Iran that uses that weapon”.\n\n(PA Graphics)\n\nHe insisted “there is nothing more transient than what we are seeing now”, and added: “So the conflict will end, prices will come down, and then headline inflation will come down, and with that, gasoline prices will come down.”\n\nMr Bessent made his remarks after Ms Reeves told the Mirror newspaper: “I feel very frustrated and angry that the US went into this war without a clear exit plan, without a clear idea of what they were trying to achieve.”\n\nShe branded it a “folly” that impacted households in the UK and around the world.\n\nMr Trump has defended the blockade aimed at putting pressure on Iran, arguing its control of the strait amounted to blackmail and extortion.\n\nHe has warned that any hostile Iranian boats approaching American warships would be “immediately eliminated”.\n\nUS Central Command, which directs military operations in the Middle East, said no vessels have so far run the blockade.\n\nAmong those ships being barred include Chinese tankers.\n\nIn response, the country’s president Xi Jinping said nations should “oppose the world’s retrogression to the law of the jungle”."} +{"url": "https://hotair.com/ed-morrissey/2026/04/14/centcom-24-hours-and-alls-well-on-the-blockade-front-n3813891", "title": "CENTCOM : 24 Hours And All Well On the Blockade Front ( Updated ) ", "publish_date": "2026-04-15T03:31:19Z", "full_text": "But for how long? That question doesn't apply to military resources or effort. It might apply to geopolitical will.\n\nAs far as US Central Command (CENTCOM) goes, the first day of the blockade on Iran's ports succeeded on all measures. No ships made it to the open sea, and no ships entered into the exclusion zone. Six vessels tested the waters, literally as well as figuratively, but did not test the US Navy's will to fight:\n\nAdvertisement\n\nMore than 10,000 U.S. Sailors, Marines, and Airmen along with over a dozen warships and dozens of aircraft are executing the mission to blockade ships entering and departing Iranian ports. During the first 24 hours, no ships made it past the U.S. blockade and 6 merchant vessels… pic.twitter.com/dpWAAknzQp — U.S. Central Command (@CENTCOM) April 14, 2026\n\nThe U.S. Central Command said Tuesday no ships from Iranian ports have gone through the U.S. blockade within its first 24 hours. Meanwhile, six merchant vessels obeyed direction from U.S. forces to reverse course and re-enter an Iranian port on the Gulf of Oman, according to Centcom. More than 10,000 U.S. sailors, marines and airmen were involved in the mission, as well as more than a dozen warships and aircraft, Centcom said. Warships involved include the USS Abraham Lincoln aircraft carrier, the USS Tripoli amphibious assault ship and several guided-missile destroyers. U.S. forces began Monday morning a blockade of all vessels entering or leaving Iranian ports, according to Centcom. The blockade doesn’t stop ships from traveling through the Strait of Hormuz but is designed to prevent vessels entering and leaving Iran’s port and coastline.\n\nOn the other side of the picket line, shipping that had been bottled up began to move through the Strait of Hormuz. The numbers are still small, but the momentum has begun to move in the right direction:\n\nSeveral commercial ships have sailed or started to travel through the Strait of Hormuz since the U.S. blockade of Iranian ports began. Tanker Rich Starry was heading out through the waterway on Tuesday, according to financial-data provider LSEG. The ship, built to carry chemicals and oil products, is owned by a Chinese company and flies a false Malawian flag, according to maritime database Equasis. The U.S. barred Americans from dealing with the tanker in February 2023 under its Iranian sanctions program. The U.S. hasn’t said it would target sanctioned vessels, promising only to act against ships entering and leaving Iranian ports in response to Iran’s effective closure of the strait to Western shipping.\n\nAdvertisement\n\nThree Iranian-linked vessels have transited the strait, but not on behalf of Tehran. Reuters notes that their ports of call are in other Gulf states, and their destinations are also outside of the Persian Gulf. The three ships have been sanctioned in the past for helping Iran evade sanctions, but CENTCOM has already said that the naval blockade would not enforce previous sanctions. It will remain focused solely on the blockade of shipping originating in or traveling to Iranian ports. That would allow China to conduct its merchant traffic with other Gulf states, although it would also force Beijing to pay market rates for oil for the first time in several years.\n\nClearly, a lot more work remains to be done before shippers fully restart operations through the strait. However, the US Navy's blockade forces Iran to suffer from their threats to that traffic for the first time. That may well provide enough pressure to force the IRGC to give up its claims of control over the passage. If not, the missile destroyers and other assets will make those claims moot anyway.\n\nThe question of political will remains, however, and its source may be surprising. The Saudis have reportedly gone wobbly over concerns about escalation from the Houthis:\n\nSaudi Arabia is pressing the U.S. to drop its blockade of the Strait of Hormuz and return to the negotiating table, fearing President Trump’s move to close it off could lead Iran to escalate and disrupt other important shipping routes, Arab officials said. The blockade is aimed at raising the pressure on Iran’s already crippled economy. But the officials said Saudi Arabia has warned Iran might retaliate by closing the Bab al-Mandeb—a Red Sea chokepoint crucial for the kingdom’s remaining oil exports. The pushback is a sign of the risks and limitations of U.S. efforts to pry open the Strait of Hormuz, which Iran shut early in the war by attacking ships in the waterway, cutting off around 13 million barrels a day in oil exports and sending futures prices above $100 a barrel.\n\nAdvertisement\n\nThat is an understandable concern. However, the alternative would be to allow Iran to impose their Mullahgeld on the Strait of Hormuz, putting themselves at the mercy of the lunatics in Tehran. The actual solution to this predicament would be for the Saudis to deal with the Houthis directly in Yemen, as they tried to do initially, but got pushed in a different direction by Joe Biden almost immediately after taking office. If the Saudis want to join the effort to contain Iran, the Houthis might be their most logical target, especially considering the risks to their oil exports in both directions.\n\nMeanwhile, Trump believes the blockade will produce diplomatic movement, he told the New York Post today. However, Trump warned that his redline on nuclear weapons and Iran's highly enriched uranium remain in place:\n\nAdditional US-Iran peace talks “could be happening over next two days” in Pakistan’s capital, President Trump told The Post on Tuesday. In an initial phone interview, Trump had claimed that discussions were “happening, but, you know, a little bit slow” before indicating that a second round of direct negotiations to end the seven-week war would likely happen somewhere in Europe. ... Trump did not say who would represent the US in a potential second round of talks, but confirmed he would not take part. The president also indicated he was not pleased with reports that the US had asked Iran to suspend its uranium enrichment program for at least two decades during this past weekend’s unsuccessful talks. “I’ve been saying they can’t have nuclear weapons” he said, “so I don’t like the 20 years.” Asked about proponents suggesting a moratorium may encourage Iran make an agreement, Trump answered: “I don’t want them [Iran] to feel like they have a win.”\n\nAdvertisement\n\nThe blockade won't feel like a win for the IRGC, especially if the US Navy succeeds in restoring shipping through the strait. The longer the blockade lasts, the worse it gets for the regime remnants and the economic damage they have created. They may need to give Trump a win just to survive ... if they can.\n\nUpdate: This is good analysis of the strategic advantages for the US in this blockade:\n\nI’m going to make many of you spitting mad at me for pointing this out, but now that we have started the naval blockade, Iran’s strategic position (which was already hopeless) has become terminal. They are soon going to run out of storage space for their oil. And we haven’t even… — Ken Gardner (@KenGardner11) April 13, 2026\n\nAnd we haven’t even yet taken Kharg Island. This will force them to shut down current oil production, which itself is a drastic step that will further wreck their economy. Without their oil money, they’re finished. And no one is coming to save them, either. Nobody wants to mess with the two best militaries on the planet. Meanwhile, pretty much the entire rest of the globe is demanding that Iran reopen the strait. And because markets always adjust, the Gulf states are already adopting workarounds in order to avoid this same problem in the future. When the history of this war is written, it will be recorded that the regime’s decision to close the strait was a colossal miscalculation that relied too heavily on short term consequences (a hike in the price of oil, coupled with the belief that nations would unite against us rather than them). In chess, there is a famous quote to the effect that the threat is always stronger than the execution. Here, the threat to close the strait was stronger, especially with Trump and with countries in Europe and the Far East. The decision to close the strait was never going to work as long as we refused to budge. And it has greatly weakened Iran’s position.\n\nAdvertisement\n\nBe sure to read it all. Ken also emphasized the need for American “persistence” to fully succeed. This is abouy geopolitical will, and Ken also remarks that a new round of negotiation may be the greatest threat to success.\n\nEditor's Note: For decades, former presidents have been all talk and no action. Now, Donald Trump is eliminating the threat from Iran once and for all.\n\nHelp us report the truth about the Trump administration’s decisive actions to keep Americans safe and bring peace to the world. Join Hot Air VIP and use promo code FIGHT to get 60% off your membership!"} +{"url": "https://baomoi.com/gia-vang-ngay-15-4-bang-gia-tai-cac-cong-ty-vang-bac-da-quy-c54939126.epi", "title": "Giá vàng ngày 15 / 4 : Bảng giá tại các công ty vàng bạc đá quý", "publish_date": "2026-04-15T03:31:19Z", "full_text": "Vàng trang sức. (Ảnh: Phan Phương/TTXVN)\n\nGiá vàng thế giới tăng khoảng 2% lên 4.831,78 USD/ounce nhờ đồng USD yếu và kỳ vọng các cuộc đàm phán Mỹ-Iran sẽ được nối lại.\n\nChuyên gia Bob Haberkorn tại RJO Futures nhận định nhà đầu tư đang chuyển hướng quay lại kim loại quý thay vì giữ tiền mặt như giai đoạn đầu xung đột.\n\nCác nhà phân tích tại Commerzbank cho rằng chừng nào Cục Dự trữ Liên bang Mỹ (Fed) chưa có dấu hiệu tăng lãi suất, giá vàng sẽ rất khó giảm sâu. Hiện các nhà giao dịch dự báo chỉ có khoảng 33% khả năng Fed sẽ cắt giảm lãi suất trong năm nay, một con số thấp hơn nhiều so với kỳ vọng trước khi diễn ra xung đột tại Trung Đông.\n\nTại Việt Nam, vào sáng 15/4, công ty Vàng bạc đá quý Sài Gòn niêm yết giá vàng SJC tại thị trường Hà Nội ở mức 173,00-175,50 triệu đồng/lượng (mua vào-bán ra).\n\nDưới đây là bảng giá vàng tại một số công ty vàng bạc đá quý trong nước sáng 15/4:\n\nGiá vàng tại Công ty Trách nhiệm hữu hạn Một thành viên Vàng bạc đá quý Sài Gòn (SJC):\n\nGiá vàng tại Công ty Cổ phần Đầu tư vàng Phú Quý:"} +{"url": "http://www.europesun.com/news/278984446/eu-country-suspends-defense-agreement-with-israel", "title": "EU country suspends defense agreement with Israel", "publish_date": "2026-04-15T03:31:19Z", "full_text": "Italian Prime Minister Giorgia Meloni criticizes Israels military campaign in Lebanon\n\nItalian Prime Minister Giorgia Meloni has announced the suspension of a defense agreement with Israel amid tensions over the war in the Middle East.\n\nItaly, whose right-wing government had been seen as one of Israel's closest allies in the EU, has become increasingly critical of the ongoing military campaign in Lebanon, where 2,124 people have been killed in Israeli airstrikes since early March.\n\nSpeaking on Tuesday in Verona, Meloni said her government had decided to \"suspend the automatic renewal\" of the agreement \"in light of the current situation.\"\n\n\"When there are things we don't agree with, we act accordingly,\" Meloni said, according to Reuters.\n\nThe agreement, ratified in 2005 and previously renewed every five years, includes cooperation in the defense industry and procurement policy, military equipment imports and exports, technical data exchanges, and personnel training.\n\nLast week, Italian Foreign Minister Antonio Tajani summoned the Israeli ambassador to Rome, Jonathan Peled, after Israeli troops fired warning shots at an Italian peacekeeping convoy outside Beirut. Meloni described the incident as \"completely unacceptable.\"\n\nOn Monday, Tajani condemned the \"unacceptable attacks by Israel against the civilian population\" in Lebanon, to which the Israeli Foreign Ministry responded by summoning the Italian envoy.\n\nSeveral European countries have formally recognized Palestinian statehood and imposed full or partial embargoes on weapons sales to Israel since 2023. Last year, Spain canceled a number of contracts with Israeli arms manufacturers reportedly totaling $1.18 billion. Spanish Prime Minister Pedro Sanchez described the Israeli campaign in Gaza as genocide, a claim Israel denied.\n\nIsraeli Prime Minister Benjamin Netanyahu has argued that his country is \"defending Europe\" by waging wars against Iran, Hamas, and the Lebanon-based pro-Palestinian armed group Hezbollah. In a speech on Tuesday, Netanyahu accused European countries of \"deep moral weakness\" for not supporting Israel.\n\n(RT.com)"} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-14/Full_text/full_text_macro_inflation_employment.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-14/Full_text/full_text_macro_inflation_employment.jsonl new file mode 100644 index 0000000..b00cf2d --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-14/Full_text/full_text_macro_inflation_employment.jsonl @@ -0,0 +1,7 @@ +{"url": "https://www.wharfedaleobserver.co.uk/news/national/26021877.chancellor-hold-talks-us-counterpart-strong-criticism-iran-war/", "title": "Chancellor to hold talks with US counterpart after strong criticism of Iran war", "publish_date": "2026-04-15T03:29:41Z", "full_text": "The comments by US treasury secretary Scott Bessent put him at odds with the Chancellor, who has gone public with her anger and frustration at the “folly” of America’s actions in the Middle East and its financial fallout on families.\n\nThe pair were due to hold face-to-face talks in Washington DC on Wednesday during the spring meetings of the International Monetary Fund, which will be dominated by the ongoing crisis in the Gulf, which has inflicted a global economic shock and sent energy prices soaring.\n\nUS treasury secretary Scott Bessent (James Manning/PA)\n\nPrior to the Chancellor heading stateside, the influential financial body slashed Britain’s economic growth forecast as a result of the conflict and warned a worldwide recession could be a “close call” in a severe scenario.\n\nHowever, despite the “large” jolt to the global economy, Bank of England governor Andrew Bailey said the UK was much better placed to deal with it because of its resilient banking system, forged in the wake of the 2007-09 financial crisis.\n\nMeanwhile, President Donald Trump has said a second round of talks between the US and Iran could happen “over the next two days”, after negotiations at the weekend collapsed.\n\nTehran’s nuclear ambitions were a key sticking point.\n\nDiplomats have been working behind the scenes as the US imposed its blockade of Iranian ports and Tehran threatened retaliatory strikes across the region, amid a shaky ceasefire.\n\nAt the same time Prime Minister Sir Keir Starmer is seeking to co-ordinate international efforts to ensure the strategic Strait of Hormuz can remain open to shipping after hostilities end.\n\nThe critical waterway, used to move one fifth of the world’s oil and gas supplies, has become a major flashpoint in the conflict, with its effective closure by Iran hiking the cost of fuel, food and other basic goods.\n\nHowever, responding to the spike in prices, Mr Bessent said “a small bit of economic pain for a few weeks is worth taking off the incalculable tail risk of either a nuclear Iran or a nuclear Iran that uses that weapon”.\n\n(PA Graphics)\n\nHe insisted “there is nothing more transient than what we are seeing now”, and added: “So the conflict will end, prices will come down, and then headline inflation will come down, and with that, gasoline prices will come down.”\n\nMr Bessent made his remarks after Ms Reeves told the Mirror newspaper: “I feel very frustrated and angry that the US went into this war without a clear exit plan, without a clear idea of what they were trying to achieve.”\n\nShe branded it a “folly” that impacted households in the UK and around the world.\n\nMr Trump has defended the blockade aimed at putting pressure on Iran, arguing its control of the strait amounted to blackmail and extortion.\n\nHe has warned that any hostile Iranian boats approaching American warships would be “immediately eliminated”.\n\nUS Central Command, which directs military operations in the Middle East, said no vessels have so far run the blockade.\n\nAmong those ships being barred include Chinese tankers.\n\nIn response, the country’s president Xi Jinping said nations should “oppose the world’s retrogression to the law of the jungle”."} +{"url": "https://www.penzcentrum.hu/gazdasag/20260415/kiderult-a-meztelen-igazsag-az-euro-magyarorszagi-bevezeteserol-nagyon-rafazhat-aki-a-2030-as-datumban-remenykedett-1196964", "title": "Kiderült a meztelen igazság az euró magyarországi bevezetéséről : nagyon ráfázhat , aki a 2030 - as dátumban reménykedett", "publish_date": "2026-04-15T03:29:41Z", "full_text": "A GKI Gazdaságkutató Zrt. megvizsgálta az euró magyarországi bevezetésének realitását, feltételeit és várható gazdasági hatásait. Az elemzés elkészítésekor figyelembe vettük mind a maastrichti kritériumok teljesítésének jelenlegi helyzetét, mind a közvélemény várakozásait. Az alábbiakban részletesen bemutatjuk a legfontosabb összefüggéseket.\n\nA választásokon győztes Tisza Párt programja és kommunikációja alapján az euró bevezetéséhez szükséges feltételek 2030–as elérését tűzte ki célul. A célkitűzés vizsgálata során kiemelt figyelmet igényelnek a bevezetés feltételei, illetve annak gazdasági hatásai, a sikeres bevezetés tényezői. Az Eurobarometer 2025-ös felmérése szerint a magyar lakosság 75 százaléka teljes mértékben támogatja az euró bevezetését, azonban a válaszadók 72 százaléka úgy gondolja, hogy nem állunk készen a bevezetésre. A lakosság értékelése reális, ugyanis az euróövezethez való csatlakozás maastrichti kritériumai alapján az elmúlt években távolodtunk a valutaövezethez való csatlakozási lehetőségtől.\n\nA csatlakozáshoz öt fő kritériumnak kell megfelelni, amelyek a következők:\n\nÁrstabilitás: az inflációs ráta nem haladhatja meg 1,5 százalékpontnál többel a három legjobb teljesítményt nyújtó tagállam átlagát.\n\nÁllamháztartási hiány: a költségvetési hiány nem lehet több a GDP 3%-ánál,\n\nÁllamadósság/GDP arány: főszabály szerint közelítenie kell a GDP 60%-ához (ha azt meghaladja).\n\nHosszú távú kamatlábak: a hosszú távú hitelek kamata legfeljebb 2 százalékponttal lehet magasabb a három legalacsonyabb inflációval rendelkező tagország átlagos hitel kamatánál. Ezt a mutatót az EKB a hosszútávú (10 éves vagy azt megközelítő) állampapírok éves hozamával közelíti.\n\nÁrfolyam-stabilitás: legalább két évet kell eltölteni az ERM II. rendszerben, amely egy fix értéken rögzíti a forint-euró árfolyamot, amelytől csak +/- 15%-kal térhet el az árfolyam.\n\nAz árstabilitás szempontjából a magyar fogyasztói árindex 2025-ben 4,4% volt. Az Európai Unió három legalacsonyabb mutatójával rendelkező tagállamának – Ciprus (0,8%), Franciaország (0,9%) és Olaszország (1,6%) – átlaga 1,1%-ot tett ki. Mindezek alapján az árstabilitási kritérium 2,6%-os referenciaértékét – a kormányzati beavatkozások (pl. rezsicsökkentés, hatósági árak) ellenére – jelentős mértékben meghaladta a hazai infláció.\n\nA hosszú távú kamatszintek tekintetében Magyarország továbbra is kiemelkedően magas értékeket mutat az Európai Unión belül. Az ECB adatai alapján a hosszú távú hitelek kamata hazánkban átlagosan 6,9% volt 2025-ben. Mivel az EKB adatbázisa szerinti 2025-ös évre vonatkozó referenciaérték 4,8% lenne, Magyarország ezen a téren sem felelt meg a követelményeknek. Bár a választásokat követően jelentősen hozamcsökkenés ment végbe, jelenleg 6,1%-os a 10 éves hozamszint.\n\nA GDP arányos államháztartási hiány az előzetes adatok alapján 4,7% volt 2025-ben. A magyar költségvetés 2020 óta nem tudta a 3%-os küszöbérték alá szorítani a deficitet, s ez 2026-ban sem várható. A GKI várakozása alapján az államháztartási hiány 6% körül alakul idén.\n\nA bruttó államadósság/GDP értéke 2025-ben 74,6% körül alakult Magyarországon az MNB előzetes pénzügyi számla adatai alapján. Ez az érték emelkedést jelent a 2024-es 73,5%-os szinthez képest, és egyben távolodást a 60%-os küszöbértéktől."} +{"url": "https://sixactualites.fr/retraites/demain-jarrete-quel-montant-faut-il-vraiment-avoir-en-banque-pour-tout-quitter-et-vivre-libre/106597/", "title": " « Demain , jarrête ! » : quel montant faut - il vraiment avoir en banque pour tout quitter et vivre libre ? ", "publish_date": "2026-04-15T03:29:41Z", "full_text": "Indépendance financière et liberté financière ne se réduisent pas à un chiffre : elles exigent un cadre clair, une épargne disciplinée et une gestion financière qui tient la route pour financer un coût de la vie maîtrisé, un montant en banque capable de soutenir l’arrêt du travail et une retraite anticipée qui ne vous laisse pas sur le bas-côté, afin de vivre une vie libre.\n\nTrain de vie mensuel (€) Âge de départ Rendement estimé Capital nécessaire (approx.) 2 000 45 ans 3 % 800 000 € 3 000 45 ans 3 % 1 200 000 € 4 000 45 ans 3 % 1 600 000 €\n\nComprendre les chiffres: combien faut-il vraiment pour arrêter ?\n\nPour beaucoup, l’objectif est limpide, mais les chiffres s’emmêlent vite. La règle des 4 % est la boussole la plus citée dans la communauté FIRE, mais elle prend ses distances avec la réalité française. En pratique, le retrait annuel ne peut pas être figé sur 4 % lorsque les rendements moyens diffèrent et que l’inflation érode le pouvoir d’achat. Je me rappelle d’un entretien avec un conseiller qui me disait: “ici, on ne parle pas de scénarios idéalisés.”\n\nEn clair, la formule est simple à énoncer, mais elle dépend de trois facteurs cruciaux : votre train de vie mensuel, votre espérance de vie restante et le rendement moyen de votre épargne. Si vous dépensez 2 000 € par mois, vous visez théoriquement 600 000 € avec une règle des 25 (4 %). Mais en pratique, avec des rendements plus modérés en France, il faut souvent viser 3 % ou même 3,5 % pour rester prudent, ce qui remodèle le montage financier.\n\nPour 2 000 € par mois, un retrait de 3 % suppose environ 800 000 € de capital. Pour 3 000 €, on tourne autour de 1,2 à 1,3 million selon les hypothèses. Et pour 4 000 €, on franchit facilement le cap du million. Ces chiffres ne sont pas des miracles : ils résument l’enjeu d’aligner épargne, inflation et rendement. J’ai vu des couples qui, en avançant en âge, ajustent progressivement leur train de vie pour rester dans des marges réalistes et préserver une certaine marge de sécurité.\n\nLe coût de la vie, l’inflation et la fiscalité jouent des rôles déterminants. En France, le Livret A tourne autour de 2,5 % en moyenne et l’assurance-vie en fonds euros se situe autour de 2,5 à 3 %. Les actions, même diversifiées, ne garantissent pas 7 % nets sans risque sur 20 ou 30 ans. C’est pourquoi les experts préconisent souvent d’ajuster le taux de retrait dans une fourchette plus prudente, autour de 3 % à 3,5 %. La conséquence est simple : le capital initial nécessaire grimpe et peut remettre en cause l’idée “d’un million suffisant pour tout quitter” sans être prudent.\n\nEt l’inflation dans tout ça ?\n\nL’inflation n’est pas un concept abstrait : elle dévore le pouvoir d’achat. Si vos dépenses restent constantes, 2 000 € aujourd’hui valent moins demain. Sur une inflation moyenne de 2,5 % sur 15 à 20 ans, votre budget réel fonde et le capital doit croître pour compenser. Ce raisonnement pousse certains à démarrer tôt et à adopter une épargne plus agressive, même dès 25 ans, afin d’éviter les fameux ajustements douloureux plus tard.\n\nLe timing et les choix: partir jeune ou partir autrement ?\n\nLa question de l’âge de départ change tout. Si vous quittez à 45 ans, vous devez financer près de 19 années sans revenu salarié avant une éventuelle pension partielle. À 55 ans, vous n’avez plus qu’environ 9 années à couvrir. Cette différence peut être décisive pour le plan financier et les choix de vie. Je me rappelle d’un ami qui a pris le pari de continuer une activité partielle qui lui plaisait, tout en accumulant du capital. Son objectif était clair : ne pas sacrifier le sens, mais préserver sa liberté.\n\nNe pas négliger le coût de la mutuelle : en attendant, la couverture santé peut peser entre 100 et 250 € par mois selon l’âge et les garanties.\n\n: en attendant, la couverture santé peut peser entre 100 et 250 € par mois selon l’âge et les garanties. Intégrer la fiscalité des retraits : les prélèvements et les plus-values peuvent fortement réduire le produit net.\n\n: les prélèvements et les plus-values peuvent fortement réduire le produit net. Privilégier des scénarios mixtes : travail à mi-temps ou activité indépendante peut réduire le capital nécessaire.\n\nPour approfondir certains aspects opérationnels autour du cumul emploi-retraite et des outils disponibles, je cites des ressources pratiques comme ce guide sur le cumul emploi-retraite et d’autres analyses utiles.\n\nLe seuil de liberté: où commencer selon votre réalité\n\nLes experts s’accordent sur un seuil indicatif, surtout pour une vie calme en province : autour de 600 000 à 800 000 € de patrimoine financier net hors résidence principale. En île-de-france ou dans les grandes métropoles, où le coût de la vie est plus élevé, ce seuil peut s’établir entre 1 et 1,5 million d’euros. Beaucoup de personnes qui franchissent ce cap ont soit été cadres ou entrepreneurs, avec une épargne soutenue pendant deux décennies environ. D’autres adoptent une approche progressive : ne pas couper totalement, mais passer à une activité choisie — freelance, temps partiel, projet monétisé. Le capital nécessaire chute alors, car il faut uniquement combler l’écart entre le revenu et les dépenses réelles.\n\nDans ce cadre, voici un conseil concret : si vous parvenez à dégager 1 000 € de revenus complémentaires mensuels, le capital requis pour atteindre l’objectif peut être divisé par deux environ. C’est une alternative réaliste pour beaucoup qui veulent préserver une qualité de vie sans couper brutalement les ponts avec le monde du travail.\n\nUn autre avertissement utile : la santé et la mutuelle restent des postes à planifier avec précision, tout comme la fiscalité. Une assurance santé privée adaptée peut représenter une charge régulière, et les impôts sur les revenus retirés de l’épargne ne doivent pas être sous-estimés. Pour ceux qui veulent aller plus loin, ce contenu de référence peut donner des axes complémentaires.\n\nEt après ? vivre libre ne signifie pas tout abandonner d’un coup\n\nLe vrai luxe, finalement, n’est peut-être pas d’arrêter de travailler à tout prix, mais d’avoir le choix. Vous pouvez opter pour une vie libre sans renoncer à des projets qui donnent du sens. Pour certains, cela se traduit par des activités salariées qui restent épanouissantes; pour d’autres, par des missions ponctuelles ou des activités entrepreneuriales. Dans tous les cas, l’objectif est d’aligner les dépenses avec les ressources, en tenant compte du coût de la vie et des aléas économiques.\n\nPour aller plus loin, j’invite à découvrir des analyses sur l’indépendance financière et les plans de retraite en (re)visitant ces ressources utiles et actualisées : une réflexion sur les pensions et les scénarios 2026 et un séminaire clé pour comprendre la retraite des 20-40 ans.\n\nEn fin de compte, atteindre un niveau de sécurité qui vous donne une vraie vie libre repose sur une chose simple et efficace : la gestion financière et une épargne régulière qui soutiennent votre revenu passif et vous donnent le choix face au coût de la vie. Le chemin peut être long et sinueux, mais le but reste clair: une indépendance financière durable qui vous permet d’arrêter le travail selon vos propres termes, sans compromis.\n\nAutres articles qui pourraient vous intéresser"} +{"url": "https://www.padovanews.it/2026/04/15/confcom-crescita-03-nel-2026-e-rischio-stagnazione/", "title": "Confcom , crescita +0 , 3 % nel 2026 e rischio stagnazione – Padovanews", "publish_date": "2026-04-15T03:29:41Z", "full_text": "ROMA (ITALPRESS) – Prima del conflitto, l’economia italiana mostrava segnali positivi: inflazione all’1,5%, consumi e PIL in aumento e occupazione ai massimi (oltre 24 milioni da luglio 2024). Tuttavia, le tensioni energetiche legate alla guerra rischiano di ridurre reddito disponibile e consumi. E’ quanto emerge dall’analisi dell’Ufficio Studi di Confcommercio, “La scommessa della crescita per superare la crisi”, presentata al Forum Confcom (la nuova denominazione della confederazione) di Villa Miani.\n\nIl presidente Carlo Sangalli ha evidenziato come le tensioni internazionali alimentino l’incertezza, frenino la domanda e colpiscano soprattutto le imprese più legate ai consumi delle famiglie: quando questi si fermano, si arresta anche il motore dell’economia. Da qui la necessità di una nuova capacità di reazione.\n\nNello scenario peggiore, la crescita si fermerebbe allo 0,3% nel 2026 e allo 0,4% nel 2027. Il quadro resta segnato da forte incertezza e preoccupazione: senza interventi strutturali su fisco, lavoro e competenze, il rischio è un nuovo decennio di stagnazione, con effetti duraturi su crescita, occupazione e coesione sociale.\n\nSecondo il direttore dell’Ufficio Studi, Mariano Bella, con il petrolio a 100 dollari fino a febbraio 2027 l’inflazione potrebbe raggiungere il 6% a fine 2026. Ciò comporterebbe minori consumi e PIL, con un’economia vicina alla recessione e una crescita più che dimezzata rispetto allo scenario base. Nel biennio 2026-2027, la perdita arriverebbe fino a 963 euro per famiglia.\n\nIl rallentamento italiano, però, non dipende solo dagli shock internazionali, ma da criticità strutturali di lungo periodo. Dopo il boom economico, la crescita è progressivamente calata: dal 3,7% tra il 1966 e il 1980 all’1,8% tra il 1981 e il 2007, fino a stagnare negli ultimi vent’anni. Parallelamente, la pressione fiscale è salita dal 25,3% al 42,2%, comprimendo investimenti e sviluppo. La cosiddetta “fiscocrazia” – eccesso di tasse e burocrazia – penalizza l’innovazione e riduce la propensione al rischio.\n\nA ciò si aggiungono tre fattori strutturali: minore capitale per occupato, riduzione dell’offerta di lavoro e calo delle competenze. Sul piano demografico, il Paese ha perso circa 9 milioni di under 30 dagli anni Ottanta, con effetti diretti sulla capacità produttiva. Una leva fondamentale è l’aumento dell’occupazione femminile: un allineamento agli standard europei porterebbe circa 290 mila occupate in più all’anno nel prossimo decennio.\n\nConta anche la qualità del lavoro: le competenze crescono meno della domanda delle imprese e l’obsolescenza professionale riduce produttività e capacità di adattamento. Il terziario di mercato resta il principale motore dell’economia, con quasi 4 milioni di posti di lavoro creati tra il 1995 e il 2025, a fronte di un calo nell’industria e nella PA.\n\nIl settore è però indebolito dal dumping contrattuale: circa 154 mila lavoratori sono impiegati con contratti meno tutelanti, con perdite fino a 8 mila euro annui, assenza di welfare e ricadute negative su concorrenza e produttività. Il fenomeno comporta anche minori entrate per lo Stato, stimate in circa 560 milioni nel 2025, e per le imprese coinvolte significa minori investimenti in formazione, bassa produttività e maggior rischio di chiusura.\n\n-foto xi2/Italpress –\n\n(ITALPRESS)."} +{"url": "http://www.europesun.com/news/278983984/producer-prices-rise-sharply-on-energy-surge-from-iran-war", "title": "Producer prices rise sharply on energy surge from Iran war", "publish_date": "2026-04-15T03:29:41Z", "full_text": "WASHINGTON, D.C.: Rising energy costs linked to the Iran war pushed U.S. wholesale prices sharply higher in March, adding to inflation concerns and complicating the Federal Reserve's policy outlook.\n\nOn Tuesday, the Labor Department said its producer price index (PPI), which tracks inflation before it reaches consumers, rose 0.5 percent from February and 4 percent from a year earlier, the largest annual increase in more than three years.\n\nEnergy prices surged 8.5 percent over the month, driving much of the increase.\n\nExcluding volatile food and energy components, core producer prices rose a more modest 0.1 percent from February and 3.8 percent year-on-year. Overall gains were smaller than economists had expected.\n\nThe data adds pressure on Federal Reserve policymakers, who are already grappling with persistent inflation and calls from President Donald Trump to cut interest rates. Some officials, however, are considering rate hikes as rising energy costs threaten to keep inflation elevated.\n\nFood prices offered some relief, falling 0.3 percent in March after a sharp 2.4 percent increase in February.\n\nWholesale prices are closely watched as an early indicator of consumer inflation. Economists also track them because some components, including healthcare and financial services, feed into the Fed's preferred inflation gauge, the personal consumption expenditures (PCE) price index.\n\n\"The decline in food prices is overdue, and welcome news for everyone,\" said Carl Weinberg, chief economist at High Frequency Economics. \"Food price increases are at the core of political arguments over affordability.\"\n\nRecent consumer data has already pointed to mounting inflation pressures. The Labor Department reported last week that consumer prices rose 3.3 percent in March from a year earlier, the biggest annual increase since May 2024, while monthly prices jumped 0.9 percent, the largest gain in nearly four years.\n\nThe broader energy shock is also reshaping global demand patterns. The International Energy Agency said the war in Iran could lead to an annual decline in oil demand for the first time since the COVID-19 pandemic.\n\nThe agency forecast demand would fall by 80,000 barrels per day this year, a sharp reversal from its earlier projection of an 850,000-barrel-per-day increase before the conflict began.\n\nDemand dropped particularly sharply in March due to attacks on energy infrastructure and the closure of the Strait of Hormuz, with the IEA expecting a 1.5 million barrels per day decline in the current quarter.\n\nWhile the initial drop has been concentrated in the Middle East and Asia-Pacific, the agency said that weakening demand is likely to spread as higher prices and supply constraints weigh on consumption."} +{"url": "https://shipandbunker.com/news/world/571889-prospects-of-iran-playing-ball-with-us-causes-oil-to-plunge-by-nearly-8", "title": "Prospects Of Iran Playing Ball With U . S . Causes Oil To Plunge By Nearly 8 % ", "publish_date": "2026-04-15T03:29:41Z", "full_text": "Prospects Of Iran Playing Ball With U.S. Causes Oil To Plunge By Nearly 8%\n\nby Ship & Bunker News Team\n\nHowever, unlikely, the oil market is buoyed by expectations for a de-escalation of hostilities: File Image/Pixabay\n\nHope continued to inform oil trading on Tuesday, supported by reports that Iran was considering pausing shipments through the Strait of Hormuz to avoid spoiling the chance of a new round of peace talks – and accordingly, Brent fell 4.6 percent to settle at $94.79 per barrel.\n\nWest Texas Intermediate, which in the previous session climbed $2.51 to $99.08 per barrel, tumbled by over 7 percent to settle at $91.28 per barrel.\n\nRachel Ziemba, a senior fellow at the Center for a New American Security, said, “If Iran does indeed pause shipments, it would be a sign its government too seeks de-escalation and to avoid the resumption of the hot war.\n\n“ Global markets would likely focus on the possibility of an agreement, not the short-term outage Rachel Ziemba, Center for a New American Security\n\n“Pausing shipping would add to the oil market outages temporarily, though global markets would likely focus on the possibility of an agreement, not the short-term outage.”\n\nPeter Tuz, president of Chase Investment Counsel Corp, said markets were looking at \"temporary risks which will be overcome in fairly short order, as opposed to being the start of a new ... regime of higher inflation, higher energy prices, higher interest rates; because if that were the new regime, there is very little reason to believe the market would be as strong as it is right now.\"\n\nIt fell upon the International Energy Agency to offer a more sobering perspective of the U.S./Iran war’s impact on oil; in its latest monthly report it stated, “Oil demand is expected to contract by 80 kb/d this year, as the Iran war upends our global outlook...this is 730 kb/d less than in last month’s Report and a forecast 1.5 mb/d 2Q26 decline would be the sharpest since Covid-19 slashed fuel consumption.”\n\nThe IEA added, “Initially, the deepest cuts in oil use have come in the Middle East and Asia Pacific, mainly for naphtha, LPG and jet fuel; however, demand destruction will spread as scarcity and higher prices persist.”\n\nIn other oil news on Tuesday, the American Petroleum Institute estimated that U.S. crude inventories rose 6.1 million barrels in the week ending April 10 compared to expectations for a 1.3 million barrel draw; also gasoline inventories rose by 626,000 barrels after plummeting by 4 million barrels the week prior.\n\nInventories in the Strategic Petroleum Reserve continue to draw down, to the tune of 4.1 million barrels during the same time frame, in order to alleviate the pressure on prices."} +{"url": "https://www.noticiasrcn.com/economia/makro-anuncio-nuevo-remate-de-productos-1012163", "title": "Supermercado en Colombia sigue pisando fuerte y lanzó nuevos remates en productos : de esto se trata", "publish_date": "2026-04-15T03:29:41Z", "full_text": "El sector retail en Colombia busca alternativas creativas y directas para incentivar el consumo. Bajo esta premisa, la cadena mayorista Makro ha decidido fortalecer su presencia en el mercado nacional mediante la consolidación de su campaña “Precios Felices”, una iniciativa diseñada específicamente para dinamizar la economía doméstica a través de descuentos agresivos en productos de primera necesidad.\n\nLa estrategia no solo busca aumentar el flujo de clientes en sus tiendas, sino que se posiciona como un salvavidas financiero frente a la inflación de alimentos.\n\nRELACIONADO Reconocido supermercado hizo impactante cambio y será competencia dura de D1 y Ara\n\nEl eje central de esta propuesta es la democratización del ahorro, permitiendo que tanto familias como pequeños negocios accedan a productos de alta calidad sin comprometer su presupuesto mensual.\n\nEstos son los descuentos que tiene esta reconocida cadena\n\nUno de los pilares más robustos de esta campaña se encuentra en la sección de perecederos. Conscientes de que las frutas y verduras representan una de las categorías con mayor fluctuación de precios y mayor peso en el gasto diario, la compañía ha implementado descuentos que alcanzan hasta el 50 %.\n\nEsta reducción del costo impacta directamente en productos básicos de la dieta local, tales como:\n\nVegetales de base: Lechuga y tomate chonto.\n\nFrutas y acompañamientos: Papaya, aguacate, guineo y manzanas.\n\nCarbohidratos esenciales: Plátano verde.\n\nAl reducir a la mitad el valor de estos insumos, la cadena facilita que los consumidores mantengan una dieta equilibrada y nutritiva, un aspecto que suele sacrificarse cuando los precios del mercado tienden al alza.\n\nLa campaña también extiende sus beneficios a la categoría de proteínas, un rubro crítico para la seguridad alimentaria. Las ofertas en este segmento están diseñadas para ofrecer variedad y conveniencia, con rebajas que oscilan entre el 20 % y el 30 %.\n\nEn el sector de pescados y mariscos, los clientes pueden encontrar ahorros significativos en filetes de tilapia, trucha y mezclas de mariscos, ideales para quienes buscan opciones saludables. De igual manera, los productos congelados —que incluyen desde vegetales listos para consumir hasta cazuelas y mojarra— presentan reducciones similares, ofreciendo una solución práctica para el ritmo de vida moderno.\n\nPor otro lado, para los amantes de las carnes blancas y cortes tradicionales, la iniciativa incluye descuentos cercanos al 20 % en pechuga de pollo, nuggets y cortes especializados como el churrasco."} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-14/Raw/raw_gdelt_asset_precious_metals_spot.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-14/Raw/raw_gdelt_asset_precious_metals_spot.jsonl new file mode 100644 index 0000000..3d55526 --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-14/Raw/raw_gdelt_asset_precious_metals_spot.jsonl @@ -0,0 +1,10 @@ +{"url": "https://thoibaotaichinhvietnam.vn/ngay-154-gia-bac-trong-nuoc-va-the-gioi-bat-tang-manh-195669.html", "url_mobile": "", "title": "Ngày 15 / 4 : Giá bạc trong nước và thế giới bật tăng mạnh", "seendate": "20260415T030000Z", "socialimage": "https://thoibaotaichinhvietnam.vn/stores/news_dataimages/2026/042026/15/08/in_social/ngay-154-gia-bac-trong-nuoc-va-the-gioi-dong-loat-bat-tang-manh-20260415085256.jpg?randTime=1776221142", "domain": "thoibaotaichinhvietnam.vn", "language": "Vietnamese", "sourcecountry": "Vietnam"} +{"url": "http://bank.cnfol.com/yinhangyeneidongtai/20260415/32144374.shtml", "url_mobile": "", "title": "四年征集项目超6200个 兴火 · 燎原 创新马拉松大赛推动 创新之火渐成燎原之势 _ 银行业内动态 _ 银行 _ 中金在线", "seendate": "20260415T030000Z", "socialimage": "", "domain": "bank.cnfol.com", "language": "Chinese", "sourcecountry": "China"} +{"url": "https://www.163.com/dy/article/KQI4EG8P0519DDQ2.html", "url_mobile": "https://m.163.com/dy/article/KQI4EG8P0519DDQ2.html", "title": "具身智能百日内 吸金 超345亿元|融资|算法|模态|机器人", "seendate": "20260415T030000Z", "socialimage": "", "domain": "163.com", "language": "Chinese", "sourcecountry": "China"} +{"url": "https://baomoi.com/gia-vang-ngay-15-4-bang-gia-tai-cac-cong-ty-vang-bac-da-quy-c54939126.epi", "url_mobile": "", "title": "Giá vàng ngày 15 / 4 : Bảng giá tại các công ty vàng bạc đá quý", "seendate": "20260415T030000Z", "socialimage": "", "domain": "baomoi.com", "language": "Vietnamese", "sourcecountry": "Vietnam"} +{"url": "http://mp.cnfol.com/32111/article/1776215336-142360699.html", "url_mobile": "", "title": "4月15日周三早间市场信息 _ 中金在线财经号", "seendate": "20260415T030000Z", "socialimage": "", "domain": "mp.cnfol.com", "language": "Chinese", "sourcecountry": "China"} +{"url": "http://www.elpuntavui.cat/politica/article/17-politica/2635259-pisos-turistics-les-cases-per-als-veins-i-els-turistes-als-hotels.html", "url_mobile": "", "title": " Pisos turístics ? Les cases , per als veïns i els turistes , als hotels ", "seendate": "20260415T030000Z", "socialimage": "https://www.elpuntavui.cat/imatges/64/42/4x3/780_0008_6442303_e0d1fc48573b6b2b5b64ca89efa14bc1ver4.jpg", "domain": "elpuntavui.cat", "language": "Catalan", "sourcecountry": "Spain"} +{"url": "https://k.sina.com.cn/article_1747383115_6826f34b02003f5fg.html", "url_mobile": "", "title": "旗舰再进阶 : 吉利银河M9黑金智曜版发布 , 从空间到智驾的 大家之选 - 新浪汽车", "seendate": "20260415T030000Z", "socialimage": "http://n.sinaimg.cn/default/feedbackpics/transform/116/w550h366/20180509/qZpQ-haichqy9477165.png", "domain": "k.sina.com.cn", "language": "Chinese", "sourcecountry": "China"} +{"url": "https://www.stcn.com/article/detail/3750646.html", "url_mobile": "", "title": "永辉超市38亿追款获胜 , 王健林等承担连带保证责任", "seendate": "20260415T030000Z", "socialimage": "", "domain": "stcn.com", "language": "Chinese", "sourcecountry": "China"} +{"url": "https://china.qianlong.com/2026/0415/8654785.shtml", "url_mobile": "", "title": "开局之年看中国 · 开放自贸港 : 从 机场流量 迈向 经济增量 - 千龙网 · 中国首都网", "seendate": "20260415T030000Z", "socialimage": "", "domain": "china.qianlong.com", "language": "Chinese", "sourcecountry": "China"} +{"url": "https://thanhtra.com.vn/doanh-nghiep-70CE54C31/phat-trien-nguon-nhan-luc-cong-nghiep-ban-dan-san-sang-cho-tuong-lai-7632e8f4b.html", "url_mobile": "", "title": "Phát triển nguồn nhân lực công nghiệp bán dẫn , sẵn sàng cho tương lai", "seendate": "20260415T030000Z", "socialimage": "https://media.thanhtra.com.vn/public/uploads/2026/04/14/69de6d49120a9057632e8f4c.jpg", "domain": "thanhtra.com.vn", "language": "Vietnamese", "sourcecountry": "Vietnam"} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-14/Raw/raw_gdelt_macro_central_banks.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-14/Raw/raw_gdelt_macro_central_banks.jsonl new file mode 100644 index 0000000..d7ad2f1 --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-14/Raw/raw_gdelt_macro_central_banks.jsonl @@ -0,0 +1,9 @@ +{"url": "https://baomoi.com/gia-vang-ngay-15-4-bang-gia-tai-cac-cong-ty-vang-bac-da-quy-c54939126.epi", "url_mobile": "", "title": "Giá vàng ngày 15 / 4 : Bảng giá tại các công ty vàng bạc đá quý", "seendate": "20260415T030000Z", "socialimage": "", "domain": "baomoi.com", "language": "Vietnamese", "sourcecountry": "Vietnam"} +{"url": "https://stockbiz.vn/tin-tuc/bo-truong-tai-chinh-my-ung-ho-cat-giam-lai-suat/39474711", "url_mobile": "", "title": "Bộ trưởng Tài chính Mỹ ủng hộ cắt giảm lãi suất", "seendate": "20260415T030000Z", "socialimage": "https://static.fireant.vn/posts/image/3772534", "domain": "stockbiz.vn", "language": "Vietnamese", "sourcecountry": "Vietnam"} +{"url": "https://stockbiz.vn/tin-tuc/ngan-hang-trung-uong-chau-au-than-trong-truoc-ap-luc-lam-phat/39474981", "url_mobile": "", "title": "Ngân hàng Trung ương châu Âu thận trọng trước áp lực lạm phát", "seendate": "20260415T030000Z", "socialimage": "https://static.fireant.vn/posts/image/3772576", "domain": "stockbiz.vn", "language": "Vietnamese", "sourcecountry": "Vietnam"} +{"url": "http://www.europesun.com/news/278983984/producer-prices-rise-sharply-on-energy-surge-from-iran-war", "url_mobile": "", "title": "Producer prices rise sharply on energy surge from Iran war", "seendate": "20260415T030000Z", "socialimage": "https://image.chitra.live/api/v1/wps/7128320/613e15d0-2e38-49ee-a7dc-4c61a22f31a0/1/supermarket-shopping-600x315.jpg", "domain": "europesun.com", "language": "English", "sourcecountry": "Russia"} +{"url": "https://zetatijuana.com/2026/04/banamex-tacha-de-erraticos-los-pronosticos-de-banxico-y-la-shcp-sobre-crecimiento-e-inflacion/", "url_mobile": "", "title": "Banamex tacha de erráticos los pronósticos de Banxico y la SHCP sobre crecimiento e inflación", "seendate": "20260415T030000Z", "socialimage": "https://zetatijuana.com/wp-content/uploads/2026/04/ECONOMIA.jpg", "domain": "zetatijuana.com", "language": "Spanish", "sourcecountry": "Mexico"} +{"url": "https://www.dailynews.co.th/news/5782451/", "url_mobile": "", "title": "ราคาทองวันนี้ 15 เม . ย . 69 ขึ้นพรวดเดียว 700 บาท", "seendate": "20260415T030000Z", "socialimage": "https://www.dailynews.co.th/wp-content/uploads/2026/04/2-26.jpg", "domain": "dailynews.co.th", "language": "Thai", "sourcecountry": "Thailand"} +{"url": "https://baotintuc.vn/kinh-te/gia-vang-sang-154-dong-loat-tang-manh-20260415082802323.htm", "url_mobile": "", "title": "Giá vàng hôm nay 15 / 4 đồng loạt tăng mạnh", "seendate": "20260415T030000Z", "socialimage": "https://cdnmedia.baotintuc.vn/Upload/DUU6RrxzRxC3rhmuFd3A/files/2026/02/gia-vang-24-2.jpg", "domain": "baotintuc.vn", "language": "Vietnamese", "sourcecountry": "Vietnam"} +{"url": "https://www.thestar.com.my/business/insight/2026/04/15/oil-shock-is-here-are-businessesprepared", "url_mobile": "", "title": "Oil shock is here : Are businesses prepared ? ", "seendate": "20260415T030000Z", "socialimage": "https://apicms.thestar.com.my/uploads/images/2026/04/15/3860181.jpeg", "domain": "thestar.com.my", "language": "English", "sourcecountry": "Malaysia"} +{"url": "https://market.bisnis.com/read/20260415/93/1966735/rupiah-hari-ini-154-dibuka-menguat-ke-rp17126-per-dolar-as", "url_mobile": "", "title": "Rupiah Hari Ini ( 15 / 4 ) Dibuka Menguat ke Rp17 . 126 per dolar AS", "seendate": "20260415T030000Z", "socialimage": "https://images.bisnis.com/posts/2026/04/15/1966735/03032025-bi-bio-24-rupiah_dolar_5_1740996814.JPG", "domain": "market.bisnis.com", "language": "Indonesian", "sourcecountry": "Indonesia"} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-14/Raw/raw_gdelt_macro_geopolitics_risk.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-14/Raw/raw_gdelt_macro_geopolitics_risk.jsonl new file mode 100644 index 0000000..ea83ce3 --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-14/Raw/raw_gdelt_macro_geopolitics_risk.jsonl @@ -0,0 +1,10 @@ +{"url": "https://radaronline.com/p/trump-assassination-fears-pope-conflict-iran-war/", "url_mobile": "", "title": "Trump Bible - Thumper Assassination Fears Explode Amid Bust - Up With Pope", "seendate": "20260415T030000Z", "socialimage": "https://media.radaronline.com/brand-img/WtV5aEYvB/1200x628/trump-assassination-fears-pope-conflict-1776201667533.jpg", "domain": "radaronline.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://www.kompas.com/tren/read/2026/04/15/093000765/rusia-dan-ukraina-kembali-lancarkan-serangan-usai-saling-tuduh-langgar", "url_mobile": "https://amp.kompas.com/tren/read/2026/04/15/093000765/rusia-dan-ukraina-kembali-lancarkan-serangan-usai-saling-tuduh-langgar", "title": "Rusia dan Ukraina Kembali Lancarkan Serangan Usai Saling Tuduh Langgar Gencatan Senjata", "seendate": "20260415T030000Z", "socialimage": "https://asset.kompas.com/crops/_Cjf6tGgx90y6yAtfy2dK39dkWk=/0x0:2000x1333/1200x675/filters:watermark(data/photo/2026/01/30/697c818d0ca91.png,0,-0,1)/data/photo/2025/10/22/68f900e9d9235.jpg", "domain": "kompas.com", "language": "Indonesian", "sourcecountry": "Indonesia"} +{"url": "https://www.whtimes.co.uk/news/national/26021871.half-households-energy-credit-end-winter---poll/", "url_mobile": "", "title": "More than half of households in energy credit at end of winter – poll", "seendate": "20260415T030000Z", "socialimage": "https://www.whtimes.co.uk/resources/images/20789458.jpg?type=og-image", "domain": "whtimes.co.uk", "language": "English", "sourcecountry": "United Kingdom"} +{"url": "https://www.wharfedaleobserver.co.uk/news/national/26021877.chancellor-hold-talks-us-counterpart-strong-criticism-iran-war/", "url_mobile": "", "title": "Chancellor to hold talks with US counterpart after strong criticism of Iran war", "seendate": "20260415T030000Z", "socialimage": "https://www.wharfedaleobserver.co.uk/resources/images/20658940.jpg?type=og-image", "domain": "wharfedaleobserver.co.uk", "language": "English", "sourcecountry": "United Kingdom"} +{"url": "https://hotair.com/ed-morrissey/2026/04/14/centcom-24-hours-and-alls-well-on-the-blockade-front-n3813891", "url_mobile": "https://hotair.com/ed-morrissey/2026/04/14/centcom-24-hours-and-alls-well-on-the-blockade-front-n3813891/amp", "title": "CENTCOM : 24 Hours And All Well On the Blockade Front ( Updated ) ", "seendate": "20260415T030000Z", "socialimage": "https://media.townhall.com/cdn/hodl/2026/98/b743b04a-5533-4916-ade0-54f7937e2177.jpg", "domain": "hotair.com", "language": "English", "sourcecountry": "United States"} +{"url": "http://bank.cnfol.com/yinhangyeneidongtai/20260415/32144374.shtml", "url_mobile": "", "title": "四年征集项目超6200个 兴火 · 燎原 创新马拉松大赛推动 创新之火渐成燎原之势 _ 银行业内动态 _ 银行 _ 中金在线", "seendate": "20260415T030000Z", "socialimage": "", "domain": "bank.cnfol.com", "language": "Chinese", "sourcecountry": "China"} +{"url": "http://hkstock.cnfol.com/shichangfenxi/20260415/32144515.shtml", "url_mobile": "", "title": "浙商证券 : 维持中国宏桥 ( 01378 ) 买入 评级 高分红投资价值突出 _ 市场分析 _ 港股 _ 中金在线", "seendate": "20260415T030000Z", "socialimage": "", "domain": "hkstock.cnfol.com", "language": "Chinese", "sourcecountry": "China"} +{"url": "https://baomoi.com/gia-vang-ngay-15-4-bang-gia-tai-cac-cong-ty-vang-bac-da-quy-c54939126.epi", "url_mobile": "", "title": "Giá vàng ngày 15 / 4 : Bảng giá tại các công ty vàng bạc đá quý", "seendate": "20260415T030000Z", "socialimage": "", "domain": "baomoi.com", "language": "Vietnamese", "sourcecountry": "Vietnam"} +{"url": "http://mp.cnfol.com/32111/article/1776215336-142360699.html", "url_mobile": "", "title": "4月15日周三早间市场信息 _ 中金在线财经号", "seendate": "20260415T030000Z", "socialimage": "", "domain": "mp.cnfol.com", "language": "Chinese", "sourcecountry": "China"} +{"url": "http://www.europesun.com/news/278984446/eu-country-suspends-defense-agreement-with-israel", "url_mobile": "", "title": "EU country suspends defense agreement with Israel", "seendate": "20260415T030000Z", "socialimage": "https://image.chitra.live/api/v1/wps/01d310c/19dc0ca9-84b9-419e-a676-b0886b902998/0/ZjEwZDJiN2EtNTU-600x315.jpg", "domain": "europesun.com", "language": "English", "sourcecountry": "Russia"} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-14/Raw/raw_gdelt_macro_inflation_employment.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-14/Raw/raw_gdelt_macro_inflation_employment.jsonl new file mode 100644 index 0000000..ef37ddd --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-14/Raw/raw_gdelt_macro_inflation_employment.jsonl @@ -0,0 +1,10 @@ +{"url": "https://www.wharfedaleobserver.co.uk/news/national/26021877.chancellor-hold-talks-us-counterpart-strong-criticism-iran-war/", "url_mobile": "", "title": "Chancellor to hold talks with US counterpart after strong criticism of Iran war", "seendate": "20260415T030000Z", "socialimage": "https://www.wharfedaleobserver.co.uk/resources/images/20658940.jpg?type=og-image", "domain": "wharfedaleobserver.co.uk", "language": "English", "sourcecountry": "United Kingdom"} +{"url": "https://www.penzcentrum.hu/gazdasag/20260415/kiderult-a-meztelen-igazsag-az-euro-magyarorszagi-bevezeteserol-nagyon-rafazhat-aki-a-2030-as-datumban-remenykedett-1196964", "url_mobile": "https://www.penzcentrum.hu/gazdasag/20260415/kiderult-a-meztelen-igazsag-az-euro-magyarorszagi-bevezeteserol-nagyon-rafazhat-aki-a-2030-as-datumban-remenykedett-1196964/amp", "title": "Kiderült a meztelen igazság az euró magyarországi bevezetéséről : nagyon ráfázhat , aki a 2030 - as dátumban reménykedett", "seendate": "20260415T030000Z", "socialimage": "https://cdn.penzcentrum.hu/images/articles/lead/2026/04/1776184225-b5hikrjMc_lg.jpg", "domain": "penzcentrum.hu", "language": "Hungarian", "sourcecountry": "Hungary"} +{"url": "https://sixactualites.fr/retraites/demain-jarrete-quel-montant-faut-il-vraiment-avoir-en-banque-pour-tout-quitter-et-vivre-libre/106597/", "url_mobile": "", "title": " « Demain , jarrête ! » : quel montant faut - il vraiment avoir en banque pour tout quitter et vivre libre ? ", "seendate": "20260415T030000Z", "socialimage": "https://sixactualites.fr/wp-content/uploads/2026/04/Demain-jarrete-quel-montant-faut-il-vraiment-avoir-en-banque-pour-tout-quitter-et-vivre-libre-.jpg", "domain": "sixactualites.fr", "language": "French", "sourcecountry": "France"} +{"url": "https://stockbiz.vn/tin-tuc/bo-truong-tai-chinh-my-ung-ho-cat-giam-lai-suat/39474711", "url_mobile": "", "title": "Bộ trưởng Tài chính Mỹ ủng hộ cắt giảm lãi suất", "seendate": "20260415T030000Z", "socialimage": "https://static.fireant.vn/posts/image/3772534", "domain": "stockbiz.vn", "language": "Vietnamese", "sourcecountry": "Vietnam"} +{"url": "https://stockbiz.vn/tin-tuc/ngan-hang-trung-uong-chau-au-than-trong-truoc-ap-luc-lam-phat/39474981", "url_mobile": "", "title": "Ngân hàng Trung ương châu Âu thận trọng trước áp lực lạm phát", "seendate": "20260415T030000Z", "socialimage": "https://static.fireant.vn/posts/image/3772576", "domain": "stockbiz.vn", "language": "Vietnamese", "sourcecountry": "Vietnam"} +{"url": "https://news.china.com/socialgd/10000169/20260415/49416933.html", "url_mobile": "", "title": "美股迅速收复伊朗战事失地 市场分化显著 _ 新闻频道 _ 中华网", "seendate": "20260415T030000Z", "socialimage": "", "domain": "news.china.com", "language": "Chinese", "sourcecountry": "China"} +{"url": "https://www.padovanews.it/2026/04/15/confcom-crescita-03-nel-2026-e-rischio-stagnazione/", "url_mobile": "", "title": "Confcom , crescita +0 , 3 % nel 2026 e rischio stagnazione – Padovanews", "seendate": "20260415T030000Z", "socialimage": "", "domain": "padovanews.it", "language": "Italian", "sourcecountry": "Italy"} +{"url": "http://www.europesun.com/news/278983984/producer-prices-rise-sharply-on-energy-surge-from-iran-war", "url_mobile": "", "title": "Producer prices rise sharply on energy surge from Iran war", "seendate": "20260415T030000Z", "socialimage": "https://image.chitra.live/api/v1/wps/7128320/613e15d0-2e38-49ee-a7dc-4c61a22f31a0/1/supermarket-shopping-600x315.jpg", "domain": "europesun.com", "language": "English", "sourcecountry": "Russia"} +{"url": "https://shipandbunker.com/news/world/571889-prospects-of-iran-playing-ball-with-us-causes-oil-to-plunge-by-nearly-8", "url_mobile": "", "title": "Prospects Of Iran Playing Ball With U . S . Causes Oil To Plunge By Nearly 8 % ", "seendate": "20260415T030000Z", "socialimage": "https://shipandbunker.cdn.speedyrails.net/a/img/_mt_d6afe34881134d19842789dd7a5fe7d4.jpg", "domain": "shipandbunker.com", "language": "English", "sourcecountry": "Singapore"} +{"url": "https://www.noticiasrcn.com/economia/makro-anuncio-nuevo-remate-de-productos-1012163", "url_mobile": "https://amp.noticiasrcn.com/economia/makro-anuncio-nuevo-remate-de-productos-1012163", "title": "Supermercado en Colombia sigue pisando fuerte y lanzó nuevos remates en productos : de esto se trata", "seendate": "20260415T030000Z", "socialimage": "https://imagenes.noticiasrcn.com/cms/2025/07/16172632/supermercado-quiebra.webp?&r=1_1", "domain": "noticiasrcn.com", "language": "Spanish", "sourcecountry": "Colombia"} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-16/Full_text/full_text_asset_metals_derivatives.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-16/Full_text/full_text_asset_metals_derivatives.jsonl new file mode 100644 index 0000000..ec1cc5a --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-16/Full_text/full_text_asset_metals_derivatives.jsonl @@ -0,0 +1,6 @@ +{"url": "https://www.eastbaytimes.com/2026/04/15/oral-b-water-flosser-vs-burst-water-flosser/", "title": "Oral - B water flosser vs . Burst water flosser", "publish_date": "2026-04-16T12:32:28Z", "full_text": "Which is the better water flosser?\n\nOften referred to as oral irrigators, water flossers provide an alternative to traditional flossing. They use pressure to send out a constant stream of water that dislodges and removes bacteria and plaque. When used alongside a good brushing routine, this can also help improve bad breath and prevent bleeding gums.\n\nOral-B and Burst both have a line of water flossers that perform a similar function. However, the overall design and way they do this differ between the two brands. When deciding which to go with, consider the cleaning power, effectiveness and any additional features.\n\nOral-B water flosser\n\nPart of Procter & Gamble, Oral-B was founded around 1949 by Dr. Robert W. Hutson. He designed the first Oral-B toothbrush and named the different versions based on the number of nylon bristles they had. Nowadays, the brand has everything from electric toothbrushes to toothpaste to water flossers.\n\nOral-B water flossers are larger than others. They come with innovative jet streams and have three settings: sensitive, medium and intense. They also have a button that lets you trigger a burst of water to flush out any food debris or loosened plaque. These oral tools also come with Oxyjet Technology, which incorporates tiny bubbles of air into the water stream to better remove particles and clean the teeth and gums.\n\nThe oral irrigators also have different nozzles, such as the Aquafloss nozzle and the Precision Jet nozzle, so you can customize how you use them. Similar to other water flossers, they come with a refillable water reservoir and a rechargeable station.\n\nThe average cost of an Oral-B water flosser is $90-$200.\n\nOral-B water flosser pros\n\nIt comes with Oxyjet technology to help eliminate plaque, resulting in healthier teeth and gums.\n\nThe different streams and intensity settings make for a more customized cleaning experience.\n\nThere are three flossing modes, as well as an on-demand button.\n\nThe nozzle is replaceable, so you don’t need to buy a new water flosser.\n\nIt has a convenient charging station and a long-lasting battery.\n\nDespite being large, it’s lightweight.\n\nThe device is easy to use.\n\nOral-B water flosser cons\n\nIt can feel clunky or too big, especially for those with smaller hands or mouths.\n\nThe nozzle design can make it difficult to position the device.\n\nThe different models are all relatively similar, despite some being at a higher price point.\n\nSome don’t have the most durable construction.\n\nBest Oral-B water flossers\n\nOral-B Water Flosser Advanced With Two Nozzles\n\nThis cordless device comes with a charging station and is portable, making it convenient to use at home or while traveling. It has an Aquafloss and a Precision Jet nozzle for targeted cleaning. It also has three flossing modes.\n\nOral-B Water Flosser Advanced With Three Nozzles\n\nWith three jet stream options and three intensity levels, this cordless oral irrigator is an effective tool that helps keep the gums and teeth clean. It comes with two Aquafloss nozzles and a precision jet nozzle. It also has an on-demand button for those who want to target specific areas. Plus, it has Oxyjet technology to reduce plaque and get rid of food particles.\n\nBurst water flosser\n\nBurst was founded in 2017 by Brittany Stewart and Hamish Khayat. The company’s mission is to make oral hygiene devices, such as electric toothbrushes and water flossers, more accessible to the public. Burst collaborates directly with dentists and hygienists to create high-end tools that help with people’s dental health. The brand has a direct-to-consumer and uses a subscription service for many of its devices.\n\nBurst’s line of water flossers is colorful and modern-looking. Each one has tips that can rotate 360 degrees. They also have different pressure modes, such as Turbo, Standard and Pulse, for a targeted clean.\n\nThe water flossers cost $60-$100. With a subscription service, you can also receive regular replacement nozzles for $6 a month.\n\nBurst water flosser pros\n\nDepending on the pressure mode, you can do a basic or a deep clean.\n\nThe rotating nozzles make it easier to reach back into your mouth.\n\nModern and stylish, each one is designed to be convenient to use.\n\nIt has a long battery life and is rechargeable.\n\nThe flosser can turn itself off after a few seconds of inactivity.\n\nThe tips are interchangeable, so you don’t have to replace the base often.\n\nThey’re durable and have a textured grip for added comfort.\n\nWhen you order one, you get a decorative travel bag.\n\nThe subscription service is convenient, inexpensive and innovative.\n\nBurst water flosser cons\n\nIt can be somewhat loud and messy.\n\nCapable of holding 110 milliliters, the water reservoir is a little small.\n\nIt can turn off automatically, which can be inconvenient.\n\nThe main difference between each model is the color.\n\nBest Burst water flossers\n\nBurst Cordless Water Flosser\n\nThis portable water flosser comes in black and has three pressure modes. It’s cordless and water-resistant, making it perfect for use in the shower or while traveling. The tip rotates 360 degrees for a more thorough clean.\n\nBurst Water Flosser Rose Gold\n\nThis chic oral irrigator comes in rose gold. It has three pressure settings: pulse, standard and turbo. It’s also comfortable to hold and durable.\n\nShould you get an Oral-B or a Burst water flosser?\n\nOral-B and Burst both offer reliable water flossers that let you thoroughly clean your teeth and gums and remove food debris and plaque you might have missed with regular brushing. They both have several pressure settings and nozzle types, so there’s something for everyone. Burst is a good option if you want something compact, sleek and modern at a competitive price point. Oral-B, meanwhile, is better if you have a larger mouth and don’t want to pay a monthly subscription.\n\nPrices listed reflect time and date of publication and are subject to change.\n\nCheck out our Daily Deals for the best products at the best prices and sign up here to receive the BestReviews weekly newsletter full of shopping inspo and sales.\n\nBestReviews spends thousands of hours researching, analyzing and testing products to recommend the best picks for most consumers. BestReviews and its newspaper partners may earn a commission if you purchase a product through one of our links."} +{"url": "https://www.finanznachrichten.de/nachrichten-2026-04/68216726-formation-metals-durchteuft-1-8-g-t-au-auf-21-9-m-oestlich-von-1-75-g-t-au-auf-30-4-m-auf-fortgeschrittenem-goldprojekt-n2-bohrungen-bestaetigen-bestae-248.htm", "title": "Formation Metals durchteuft 1 , 8 g / t Au auf 21 , 9 m , östlich von 1 , 75 g / t Au auf 30 , 4 m auf fortgeschrittenem Goldprojekt N2 : Bohrungen bestätigen Beständigkeit von 300 m innerhalb von 5 km entlang von mineralisiertem Streichen", "publish_date": "2026-04-16T12:32:28Z", "full_text": "Höhepunkte:\n\n- N2-25-004: 0,83 g/t Au auf 40,4 m, beginnend in einer Bohrlochtiefe von 180,0 m, 147,4 m vertikal.\n\n- N2-25-006: 1,8 g/t Au auf 21,9 m, beginnend in einer Bohrlochtiefe von 154,4 m, 133,7 m vertikal.\n\n- N2-25-009: 1,37 g/t Au auf 24,0 m, beginnend in einer Bohrlochtiefe von 168,9 m, 146,3 m vertikal.\n\n- N2-25-004, -006 und -009 bestätigen die strukturelle Beständigkeit sowie die Beständigkeit der Gehalte auf einer Streichlänge von 300 m, bauen auf N2-25-007, -008 und -010 auf, die 0,95 g/t Au auf 61,1 m enthielten, und befinden sich neigungsabwärts von 1,75 g/t Au auf 30,4 m in N2-25-005.\n\n- Angesichts dieser Ergebnisse geht das Unternehmen davon aus, dass die A-Zone ein solides mineralisiertes Erzgangsystem beherbergt, das zwischen 20 und 61 m schwankt, mindestens 100 m breit ist und sich über eine Streichlänge von 1,5 km erstreckt. Die A-Zone ist nach wie vor in mehrere Richtungen offen, insbesondere entlang des Streichens (Ost-West) und neigungsabwärts bzw. in die Tiefe (Süden) innerhalb eines 5 km langen strukturellen Korridors, der bereits bebohrt wurde und sich als mineralisiert erwiesen hat.\n\n- Bis dato wurden 48 Bohrlöcher auf insgesamt 15.291 m abgeschlossen, wobei die Analyseergebnisse für 35 Bohrlöcher noch ausstehend sind, was für das gesamte zweite Quartal eine kontinuierliche Reihe bevorstehender Katalysatoren verheißt.\n\n- Das Unternehmen verfügt über ein Working Capital von etwa 10,5 Millionen CAD und ist schuldenfrei.\n\nVancouver, British Columbia / 16. April 2026 / IRW-Press / Formation Metals Inc. (\"Formation\" oder das \"Unternehmen\") (CSE: FOMO) (FWB: VF1) (OTCQB: FOMTF), ein nordamerikanisches Mineralakquisitions- und Explorationsunternehmen, freut sich, die Ergebnisse der Bohrungen N2-25-001, N2-25-002, N2-25-003, N2-25-004, N2-25-006 und N2-25-009 bekannt zu geben, die im Rahmen seines laufenden, vollständig finanzierten 30.000-Meter-Bohrprogramms in seinem Vorzeige-Goldkonzessionsgebiet N2 (\"N2\" oder das \"Konzessionsgebiet\") niedergebracht wurden.\n\nDas 25 km südlich von Matagami (Quebec) gelegene Konzessionsgebiet N2 beherbergt eine globale historische Ressource von ca. 871.000 Unzen, bestehend aus 18 Mio. Tonnen Gestein mit einem Gehalt von 1,4 g/t Au (ca. 810.000 Unzen Au) in vier Zonen (A, Ost, RJ-East und Central)2,3 und 243.000 Tonnen Gestein mit einem Gehalt von 7,82 g/t Au (ca. 61.000 Unzen Au) in der Zone RJ2,4.\n\nDas laufende Bohrprogramm des Unternehmens hat die Erwartungen übertroffen und die geologische Beständigkeit bestätigt, wobei in den Bohrlöchern N2-25-004, N2-25-006 und N2-25-009 solide und durchgehende Goldabschnitte erzielt wurden, die folgende bedeutsame Abschnitte identifizierten:\n\n- N2-25-004: 0,83 g/t Au auf 40,4 m, beginnend in einer Bohrlochtiefe von 180,0 m, 147,4 m vertikal Das bedeutsamste Intervall beinhaltet 1,36 g/t Au auf 9,0 m mit einem Gesamtmetallindex von 38,48.\n\n- N2-25-006: 1,8 g/t Au auf 21,9 m, beginnend in einer Bohrlochtiefe von 154,4 m, 133,7 m vertikal Das bedeutsamste Intervall beinhaltet 3,4 g/t Au auf 4,8 m mit einem Gesamtmetallindex von 79,56.\n\n- N2-25-009: 1,37 g/t Au auf 24,0 m, beginnend in einer Bohrlochtiefe von 168,9 m, 146,3 m vertikal Das bedeutsamste Intervall beinhaltet 2,05 g/t Au auf 13,3 m mit einem Gesamtmetallindex von 81,89.\n\nEine vergleichende Analyse zeigt eine starke Übereinstimmung zwischen dem Phase-1-Datensatz und den historischen Bohrungen auf über 55.000 m, was wesentliche Geologie- und Bergbauparameter bestätigt und das Vertrauen in die bestehende Datenbank stärkt.\n\nDeepak Varshney, CEO von Formation Metals, sagte: \"Die Ergebnisse von Phase 1 übertreffen weiterhin unsere Erwartungen, wobei N2-25-004, N2-25-006 und N2-25-009 zeigen, dass die A-Zone ein bedeutsames Tagebauziel darstellt. Die Ergebnisse bestätigen weiterhin die historischen Bohrungen auf über 55.000 m, wobei die Bohrungen nicht nur die historischen Erkenntnisse hinsichtlich Lithologie, Mineralisierung, Alteration, Erzgänge und struktureller Merkmale bestätigen, sondern auch eine höhere Konsistenz, längere goldhaltige Mischproben sowie wertvollere Mineralisierungsprofile liefern, was das Konzept einer Tagebaulagerstätte bei N2 untermauert.\"\n\nAbbildung 1 - Standorte der Bohrlöcher von 2025 (A-Zone), Phase 1.\n\nDie Bohrungen wurden so konzipiert, dass sie auf Mineralisierungen in verschiedenen Horizonten südlich und unterhalb von N2-25-005 und N2-25-012 abzielen (siehe Pressemitteilung vom 12. Februar 2026), wo das Unternehmen die folgenden mächtigen, kontinuierlichen, oberflächennahen Abschnitte identifiziert hat:\n\n- N2-25-005: 0,91 g/t Au über 42,3 Meter ab 14,0 Metern Bohrlochtiefe, 9,9 Meter vertikale Tiefe. Zu den herausragenden Abschnitten zählen 8,1 Meter mit 2,04 g/t Au bzw. 11,4 Meter mit 1,31 g/t Au mit einem Gesamtmetallindex von 38,36.\n\n- N2-25-012: 1,75 g/t Au über 30,4 Meter ab 64,1 Metern Bohrlochtiefe, 45,3 Meter vertikale Tiefe. Zu den herausragenden Abschnitten zählen 10,5 Meter mit 3,51 g/t Au bzw. 0,51 Meter mit 19,2 g/t Au mit einem Gesamtmetallindex von 62,43.\n\nDiese Bohrlöcher wurden auch konzipiert, um die westliche Erweiterung des Streichens des durch die Bohrlöcher N2-25-007, N2-25-008 und N2-25-010 (siehe Pressemitteilung vom 24. Februar 2026) ermittelten mineralisierten Horizonts zu testen, wo das Unternehmen die folgenden zusätzlichen mächtigen, soliden oberflächennahen Abschnitte identifiziert hat:\n\n- N2-25-007: 1,3 g/t Au über 22,2 Meter, beginnend bei 139,9 Metern Bohrlochtiefe, 121,2 Meter vertikal. Der hervorgehobene Abschnitt umfasst 2,36 g/t Au über 10,5 Meter mit einem Gesamtmetallindex von 51,07.\n\n- N2-25-008: 0,95 g/t Au über 61,1 Meter, beginnend bei 109 Metern Bohrlochtiefe, 94,4 Meter vertikal. Der hervorgehobene Abschnitt umfasst 1,68 g/t Au über 26,5 Meter mit einem Gesamtmetallindex von 67,97.\n\n- N2-25-010: 1,43 g/t Au über 19,4 Meter, beginnend bei 117,5 Metern Bohrlochtiefe, 101,8 Meter vertikal. Der hervorgehobene Abschnitt umfasst 2,23 g/t Au über 7,0 Meter mit einem Gesamtmetallindex von 38,49.\n\nDer Abstand von etwa 55 m zwischen den Bohrlöchern N2-25-004, N2-25-006 und N2-25-009 bestätigt die Beständigkeit eines bedeutsamen Bulk-Tonnage-Systems in der Tiefe. Diese Ergebnisse validieren historische Bohrdaten, stärken das Vertrauen in das geologische 3D-Modell und verringern das technische Risiko für die bevorstehenden Erschließungsphasen.\n\nDie geologische Interpretation, die auf der Beständigkeit des Streichens der Mineralisierung zwischen den beiden Bohrlochsätzen (N2-25-007, N2-25-008 und N2-25-010 sowie N2-25-004, N2-25-006 und N2-25-009) basiert, lässt einen konsistenten, 300 m langen goldhaltigen Korridor erkennen. Dieser Abschnitt weist stark auf beträchtliches Bulk-Tonnage-Potenzial in Oberflächennähe entlang einer Streichlänge von 8 km hin.\n\nDiese Bohrlochreihe bestätigte insbesondere nicht nur die Beständigkeit der primären Zielerzgänge, sondern durchschnitt auch parallel verlaufende, sekundäre und tertiäre Erzgangsysteme, wodurch das potenzielle mineralisierte Profil oberhalb und unterhalb der Hauptzone erheblich erweitert wurde, wo N2-25-004 0,4 g/t Au auf 4,6 m und 0,41 g/t Au auf 4,0 m oberhalb, N2-25-006 0,66 g/t Au auf 38,6 m oberhalb und 0,67 g/t Au auf 22,2 m unterhalb durchteufte und N2-25-009 0,61 g/t Au auf 42,1 m oberhalb und 0,96 g/t Au auf 21,7 m unterhalb durchteufte. Die identifizierte Beständigkeit dieser Bohrlochreihen über eine Strecke von 300 m mit Erweiterungspotenzial über die gesamte Streichlänge von 8 km würde erhebliche positive Auswirkungen auf einen zukünftigen Tagebau haben, wobei sich der potenzielle Abbaubereich deutlich auf eine gesamte mineralisierte Mächtigkeit von bis zu etwa 93 m in der Tiefe des Bohrlochs und eine Mächtigkeit von etwa 100 m erweitern würde.\n\nBis dato hat Formation ein Phase-1-Programm mit 46 Bohrlöchern auf insgesamt 14.466 m erfolgreich abgeschlossen. Da die Analyseergebnisse für 39 Bohrlöcher zurzeit noch ausstehend sind, erwarten wir einen kontinuierlichen Nachrichtenfluss, der als primärer Bewertungskatalysator wirken wird, wobei die Bohrungen voraussichtlich Ende Mai fortgesetzt werden.\n\nDeepak Varshney, CEO von Formation Metals, sagte außerdem: \"Da die historische Ressource eine Streichlänge von nur 1,5 km im nördlichen Korridor umfasst, haben wir über 6 km auf einem Projekt zu bohren, auf dem wir nun nachgewiesen haben, dass die Hauptzone mindestens 20 m mächtig und etwa 95 m breit ist. Über die Bestätigung der durchgehenden Beständigkeit unseres Hauptziels hinaus sind diese Bohrergebnisse insofern von großer Bedeutung, als sie übereinanderliegende oder parallel verlaufende, sekundäre und tertiäre Erzgangsysteme verdeutlichen, die den potenziellen mineralisierten Bereich erheblich erweitern und unseren Spielraum für ein umfassendes, mehrere Erzgänge umfassendes Abbaukonzept vergrößern.\n\nSollte sich diese Beständigkeit über die gesamte Streichlänge von 8 km erstrecken, steht uns eine erhebliche Erweiterung des potenziellen Tagebaugebiets bevor - möglicherweise auf eine Mächtigkeit von etwa 93 m und eine Breite von 100 m in der Tiefe des Bohrlochs. Die vergleichende Analyse unserer jüngsten Phase-1-Bohrungen mit historischen Daten hat unsere Erwartungen übertroffen und eine starke Übereinstimmung sowohl hinsichtlich der geologischen Struktur als auch des Mineralisierungsgehalts aufgezeigt. Diese hohe Wiederholbarkeit validiert unser geologisches Modell und belegt die erhebliche Beständigkeit der Lagerstätte.\"\n\nDas 15.000 Meter umfassende Bohrprogramm der Phase 1 von Formation ist konzipiert für:\n\n- Steigerung des Vertrauensniveaus und Konversion der Ressource: Schließen oberflächennaher Lücken, um das Vertrauensniveau der oberflächennahen Mineralisierung zu steigern.\n\n- Ressourcenwachstum: Überprüfung von Erweiterungen in Fallrichtung und Step-outs im Streichen sowohl nach Osten als auch nach Westen über die historischen Ressourcengrenzen hinaus.\n\n- Metallurgie: Entnahme repräsentativer Bohrkerne zur Bestätigung der metallurgischen Reaktion und Validierung der Gewinnungsraten.\n\nDa die vollständige Finanzierung gesichert ist, treibt Formation ein 30.000 m umfassendes Bohrprogramm voran, dessen Schwerpunkt auf der Abgrenzung einer oberflächennahen Tagebauressource liegt, um eine beträchtliche Tonnage aufzubauen und die Wirtschaftlichkeit des Projekts zu verbessern. Der Schwerpunkt der Explorationsarbeiten liegt zurzeit darauf, das Potenzial eines 8 km langen Korridors zu erschließen, wobei zwei Bohrgeräte in den Zonen \"A\" und \"RJ\" im Einsatz sind. Der Abschluss dieser Phase-1-Bohrungen wird zur Veröffentlichung einer ersten Mineralressourcenschätzung (MRE) im dritten Quartal führen.\n\nIn den kommenden Monaten plant das Unternehmen ein fokussiertes und vielversprechendes Explorationsprogramm bei N2, das die vielfältigen Möglichkeiten des Projekts widerspiegelt und nachhaltige, disziplinierte Explorationsaktivitäten über die aktuelle Bohrphase hinaus unterstützt.\n\nTabelle 1 - Bedeutende Abschnitte aus der A-Zone: N2-25-004, N2-25-006 und N2-25-009\n\nBohrloch-Nr. Au (g/t) Von Bis Länge (m) Metallindex N2-25-004 1,03 14,3 15,6 1,3 1,34 0,41 77,0 79,5 2,5 1,03 0,29 96,0 102,1 6,1 1,77 0,4 129,0 133,6 4,6 1,84 0,29 145,5 148,2 2,7 0,78 0,83 180,0 220,4 40,4 33,53 einschließlich 1,36 180,0 189,0 9 und 1,08 195,3 202,2 6,9 und 1,18 210,0 220,4 10,4 N2-25-006 0,66 69,4 108,0 38,6 25,48 einschließlich 8,85 87,0 88,1 1,1 und 3,66 104,2 106,2 2 1,8 154,4 175,5 21,1 37,98 einschließlich 3,6 154,4 159,2 4,8 und 1,34 161,0 166,7 5,7 und 2,41 168,0 173,0 5 1,6 197,6 199,3 1,7 2,72 0,67 231,0 253,1 22,1 14,81 einschließlich 1,01 231,0 234,1 3,1 und 1,1 243,0 249,8 6,8 N2-25-009 0,61 86,7 128,8 42,1 25,74 einschließlich 1,04 113,3 126,7 13,4 0,34 156,5 159,4 2,9 0,99 1,37 168,9 192,9 24,0 32,88 einschließlich 2,05 177,8 191,1 13,3 und 3,02 177,8 181,1 3,3 und 4,02 185,5 186,7 1,2 2,23 198,7 199,8 1,1 2,45 0,96 207,8 231,0 23,2 22,27 einschließlich 2,98 207,8 211,8 4,0\n\nTabelle 2 - Bedeutende Abschnitte aus der RJ-Zone: N2-25-001, N2-25-002 und N2-25-003\n\nBohrloch-Nr. Au (g/t) Von Bis Länge (m) Metallindex N2-25-001 0,23 261,7 268,3 6,6 1,52 einschließlich 1,28 266,5 267,1 0,6 0,11 271,5 281,7 10,2 1,12 N2-25-002 0,24 98,5 102 3,5 0,84 einschließlich 1,58 99,3 99,8 0,5 0,34 183,1 207,5 24,4 8,30 einschließlich 0,89 183,1 187,9 4,8 und 1,54 186,0 187,9 1,9 und 0,3 196,6 208,5 11,9 0,54 289,3 290,3 1,0 0,54 N2-25-003 3,0 23,1 27,6 4,5 13,50 einschließlich 14,06 23,1 24 0,9 0,6 52,9 64,7 11,8 7,08 einschließlich 1,28 59,6 63,7 4,1 0,76 110 112 2,0 1,52\n\nAnmerkung 1: Die dargestellten Mineralisierungsabschnitte sind nicht direkt repräsentativ für die wahre Mächtigkeit. Basierend auf der Interpretation des Abschnittswinkels entspricht die geschätzte wahre Mächtigkeit der mineralisierten Linse im Allgemeinen 87 % der erbohrten Kernlänge.\n\nAnmerkung 2: Die gemeldeten Abschnitte wurden unter Verwendung eines Mindestgehalts von 0,2 g/t Au für höhergradige Abschnitte zusammengesetzt.\n\nTabelle 3 - Informationen zu den Bohrlöchern von Zone-A\n\nTabelle 4 - Informationen zu den Bohrlöchern von Zone-RJ\n\nÜberblick über das Projekt\n\nDas Vorzeige-Goldprojekt N2 von Formation umfasst 87 Claims mit einer Gesamtfläche von ca. 4.400 ha in der Subprovinz Abitibi im Nordwesten von Quebec und ist ein fortgeschrittenes Goldprojekt mit einer umfassenden historischen Ressource von ca. 871.000 Unzen - bestehend aus 18 Mio. Tonnen mit einem Gehalt von 1,4 g/t Au (ca. 810.000 Unzen Au)2,3 sowie 243.000 Tonnen mit einem Gehalt von 7,82 g/t Au (ca. 61.000 Unzen Au)2.\n\nInsgesamt gibt es sechs primäre goldhaltige mineralisierte Zonen, die jeweils in Streichrichtung und in der Tiefe erweiterbar sind. Die von Balmoral Resources Ltd. (jetzt Wallbridge Mining) von 2010 bis 2018 durchgeführten Zusammenstellungen und geophysikalischen Arbeiten lieferten zahlreiche Ziele, die derzeit erstmals von Formation mit Diamantbohrungen untersucht werden.\n\nZu den historischen Highlights der beiden vorrangigen Zonen gehören:\n\n- Zone A: eine oberflächennahe, sehr beständige, wenig variierende historische Goldlagerstätte mit ca. 522.900 Unzen, die bei einem Gehalt von 1,52 g/t Au identifiziert wurde. In der Vergangenheit wurden über 1,65 km Streichlänge etwa 15.000 Bohrmeter niedergebracht. 84 % der historischen Bohrungen durchteuften goldhaltige Abschnitte mit bis zu 1,7 g/t Au über 35 m.\n\n- Zone RJ: eine hochgradige historische Goldlagerstätte mit ca. 61.100 Unzen, die bei einem Gehalt von 7,82 g/t Au identifiziert wurde, mit hochgradigen Abschnitten aus historischen Bohrungen von bis zu 51 g/t Au über 0,8 m und 16,5 g/t Au über 3,5 m2. Diese Zone war das Ziel der letzten Bohrungen auf dem Konzessionsgebiet durch Agnico-Eagle Mines im Jahr 2008, als der Goldpreis bei ca. 800 US$/Unze lag. Bislang wurden nur ca. 900 m der Streichlänge bebohrt, sodass noch mehr als 4,75 Kilometer der Streichlänge zu erkunden sind.\n\nDie interne Einschätzung des Unternehmens lautet, dass das Projekt N2 das Potenzial für eine mögliche Tagebauressource hat. Dieser Optimismus basiert auf mehreren wesentlichen Faktoren:\n\n- Beträchtliche unerschlossene Streichlänge: Allein die Zone \"A\" weist eine Streichlänge von über 3,1 km auf (nur etwa 35 % davon wurden in der Vergangenheit bebohrt), während in der Zone RJ noch über 4,75 km unerprobt sind, was erheblichen Spielraum für eine seitliche Erweiterung der bekannten Mineralisierung bietet.\n\n- Offen in der Tiefe und entlang des Streichens: Alle Zonen sind weiterhin offen, da die bisherigen Bohrungen auf geringe Tiefen (etwa 350 m) beschränkt waren, sodass in einem bewährten Goldlager beträchtliches vertikales Potenzial besteht.\n\n- Mächtige, beständige oberflächennahe Abschnitte: Jüngste Bohrungen haben mächtige Zonen (100 bis über 200 m) der Zielmineralisierung bestätigt, die in Oberflächennähe beginnen und ideal für Tagebauszenarien mit großen Tonnagen, geringen Abraumverhältnissen und hohem Tonnagenpotenzial sind.\n\n- Regionale Analogie und Herkunft: N2 befindet sich im Abschnitt Casa Berardi, der mehrere Lagerstätten mit mehreren Millionen Unzen beherbergt (z. B. Casa Berardi: über 2 Mio. Unzen produziert sowie wahrscheinliche und nachgewiesene Reserven von 14,3 Mio. Tonnen mit 2,75 g/t Au; Douay: Ressourcen von über 3 Mio. Unzen (10 Mio. Tonnen mit 1,59 g/t Au in der Kategorie angedeutet und 76,7 Mio. Tonnen mit 1,02 g/t Au in der Kategorie vermutet), und weist ähnliche geologische und strukturelle Merkmale auf. Die nahe gelegene Mine Vezza produzierte aus höhergradigem Untertagebau, doch die oberflächennäheren, mächtigeren Zonen von N2 lassen auf eine überlegene Wirtschaftlichkeit des Tagebaus schließen.\n\n- Unerprobte Ziele: Bei der Zusammenstellung der Daten wurden zahlreiche geophysikalische Anomalien (IP, EM, VTEM) identifiziert, die noch nicht bebohrt wurden und über die bekannten Zonen hinaus Entdeckungspotenzial aufweisen.\n\n- Steigende Goldpreise und wirtschaftliche Machbarkeit: Bei den aktuellen Goldpreisen werden niedriggradigere Lagerstätten mit großen Tonnagen äußerst attraktiv, was das Potenzial des Projekts erhöht.\n\nDieser erstklassige Standort in einer strategisch günstigen Lage, 25 km südlich der Bergbaustadt Matagami (Quebec), bietet ganzjährigen Zugang über Provinzstraßen und Holzabfuhrstraßen sowie die Nähe zu qualifizierten Arbeitskräften, Energieinfrastruktur und etablierten Bergbaudienstleistungen in einer Jurisdiktion, die für ihre frühere Goldproduktion von über 200 Mio. Unzen bekannt ist. Das Projekt liegt entlang des Minenabschnitts Casa Berardi, der Goldlagerstätten mit mehreren Millionen Unzen beherbergt, und befindet sich etwa 1,5 km östlich der vormals produzierenden Goldmine Vezza, die zwischen 2013 und 2019 von Nottaway Resources betrieben wurde und über 100.000 Unzen Gold im Untertagebau förderte.\n\nDie robuste Infrastruktur der Region bietet Möglichkeiten für die Lohnvermahlung, mit potenziellem Zugang zu nahe gelegenen Verarbeitungsanlagen wie jenen bei Casa Berardi oder anderen Mühlen in Abitibi, was eine kostengünstige Erschließung ohne die Errichtung einer eigenen Mühle am Standort ermöglicht.\n\nAbbildung 3 - Historische Bohrlochstandorte. Formation geht davon aus, dass im Konzessionsgebiet N2 eine Streichlänge von über 15 km zu erkunden ist.\n\nAbbildung 4 - Das Konzessionsgebiet im Überblick mit einer Zusammenfassung der historischen Arbeiten, die in jeder der sechs mineralisierten Zonen durchgeführt wurden, und den jeweiligen historischen Ressourcen.\n\nDas Unternehmen ist außerdem der Ansicht, dass N2 ein erhebliches Potenzial für Basismetalle aufweist. In diesem Zusammenhang hat es kürzlich einen Neubewertungsprozess abgeschlossen, der bedeutende Kupfer- und Zinkabschnitte in historischen Bohrungen zeigte, von denen bekannt ist, dass sie bedeutende Goldgehalte (>1 g/t Au) aufweisen. Die Analyseergebnisse reichen von 200 bis 4.750 ppm Kupfer und von 203 ppm bis 6.700 ppm Zink, was auf ein starkes Potenzial für erhöhte Basismetallkonzentrationen (Cu-Zn) im gesamten Konzessionsgebiet hinweist, insbesondere in den Zonen A und RJ. Die geologische Beschaffenheit des gesamten Konzessionsgebiets N2 ist durch vulkanische und sedimentäre Gesteine gekennzeichnet, die sich in regionalen Antiklinal- und Synklinalstrukturen gebildet haben. Drei Hauptdeformationsstrukturen, die entlang der bekannten von Nordwest nach Südost bis Westnordwest nach Ostsüdost verlaufenden Strukturtrends ausgerichtet sind, die für VMS-Lagerstätten in der Region Matagami typisch sind, fungieren als kritische geologische Kontrollen für die Mineralisierung im Konzessionsgebiet.\n\nQualifizierter Sachverständiger\n\nDer technische Inhalt dieser Pressemitteilung wurde von Herrn Babak V. Azar, P.Geo., géo (OGQ#10876), einem unabhängigen Auftragnehmer und qualifizierten Sachverständigen im Sinne der Vorschrift National Instrument 43-101, geprüft und genehmigt. Die vom Optionsgeber vorgelegten historischen Berichte wurden vom qualifizierten Sachverständigen geprüft.\n\nQualitätssicherung und Qualitätskontrolle\n\nDie Qualitätssicherungs- und Qualitätskontrollprotokolle umfassten die Hinzugabe von Leer- und Standardproben (von Canadian Resource Laboratories akkreditiert) im Schnitt alle 10 Proben während des Analyseprozesses. Die Goldanalyse erfolgte mittels Brandprobe (FA) mit abschließendem Atomabsorptions- und ICP-Verfahren an 50 Gramm Material in den Einrichtungen von Laboratoire Expert Inc. in Rouyn-Noranda, Quebec, Kanada, und AGAT Laboratories Ltd. in Val d'Or, Quebec, Kanada. Jede Probe mit einem Gehalt von 10,0 g/t Gold oder mehr wurde nochmals anhand FA analysiert gefolgt von einer gravimetrischen Untersuchung. Die Proben, die eine große Variation ihres Goldgehalts aufwiesen oder sichtbares Gold enthielten, wurden einer Gesamtgoldanalyse (metallische Siebung) unterzogen.\n\nÜber Formation Metals Inc.\n\nFormation Metals Inc. ist ein nordamerikanisches Mineralakquisitions- und -explorationsunternehmen, das sich auf die Entwicklung hochwertiger, bohrbereiter Konzessionsgebiete mit hohem Wertschöpfungs- und Expansionspotenzial konzentriert. Das Vorzeigeprojekt von Formation ist das Goldprojekt N2, ein fortgeschrittenes Goldprojekt mit einer umfassenden historischen Ressource von ca. 871.000 Unzen (18 Mio. Tonnen mit 1,4 g/t Au (ca. 810.000 Unzen Au) in vier Zonen (A, East, RJ-East und Central)2, 3 und 243.000 Tonnen mit 7,82 g/t Au (ca. 61.000 Unzen Au) in der Zone RJ2, 4) und sechs mineralisierten Zonen, die jeweils entlang des Streichens und in der Tiefe für eine Erweiterung offen sind. Dazu gehören die Zone \"A\", in der nur etwa 35 % des Streichens bebohrt wurden (>3,1 km offen), und die Zone \"RJ\", in der historische hochgradige Abschnitte mit bis zu 51 g/t Au auf 0,8 Metern vorkommen.\n\nFORMATION METALS INC.\n\nDeepak Varshney, CEO und Direktor\n\nNähere Informationen erhalten Sie unter der Rufnummer 778-899-1780, per E-Mail an dvarshney@formationmetalsinc.com oder unter www.formationmetalsinc.com.\n\nDie Canadian Securities Exchange und ihr Regulierungsorgan übernehmen keine Verantwortung für die Angemessenheit oder Genauigkeit dieser Mitteilung.\n\nHinweise und Quellennachweis:\n\nLeser werden darauf hingewiesen, dass die Geologie benachbarter Konzessionsgebiete nicht unbedingt Rückschlüsse auf die Geologie des Konzessionsgebiets zulässt. Die oben genannten Ressourcenschätzungen sind nicht in Kategorien eingestuft, gelten als historisch und basieren auf früheren Daten, die von einem früheren Konzessionseigentümer erfasst wurden und nicht den aktuellen CIM-Kategorien entsprechen.\n\nDas Unternehmen hält die Schätzungen zwar für grundsätzlich zuverlässig, jedoch hat ein qualifizierter Sachverständiger keine ausreichenden Arbeiten durchgeführt, um die historischen Schätzungen gemäß den aktuellen CIM-Kategorien als aktuelle Mineralressourcen zu klassifizieren, und das Unternehmen behandelt die historischen Schätzungen daher nicht als aktuelle Mineralressourcen. Bei der Erstellung der historischen Schätzungen wurde ein Cutoff-Gehalt von 0,5 g/t Au bei einer Mindestabbaubreite von 2,5 m zugrunde gelegt.\n\nBevor die historischen Schätzungen als aktuelle Ressourcen klassifiziert werden können, müssen möglicherweise umfangreiche Datenzusammenstellungen, erneute Bohrungen, erneute Probenahmen und Datenüberprüfungen durch einen qualifizierten Sachverständigen durchgeführt werden. Es kann nicht garantiert werden, dass die historischen Mineralressourcen, weder ganz noch teilweise, jemals wirtschaftlich nutzbar sein werden. Darüber hinaus sind Mineralressourcen keine Mineralreserven und ihre wirtschaftliche Nutzbarkeit ist nicht nachgewiesen. Dem Unternehmen sind keine neueren Schätzungen für das Konzessionsgebiet N2 bekannt.\n\nNeedham, B. (1994), 1993 Diamond Drill Report, Northway Joint Venture, Northway Property; Cypress Canada Inc.; 492 Seiten. Guy K. (1991), Exploration Summary May 1, 1990 to May 1, 1991 Vezza Joint Venture Northway Property; Total Energold; 227 Seiten.\n\nZukunftsgerichtete Aussagen:\n\nDiese Pressemitteilung enthält \"zukunftsgerichtete Aussagen\" gemäß den geltenden kanadischen Wertpapiergesetzen, einschließlich, aber nicht beschränkt auf Aussagen zu: den Plänen des Unternehmens für das Konzessionsgebiet und dem voraussichtlichen Zeitplan und Umfang des Bohrprogramms auf dem Konzessionsgebiet; und dem geplanten 30.000-Meter-Bohrprogramm des Unternehmens. Solche zukunftsgerichteten Informationen spiegeln die aktuellen Einschätzungen des Managements wider und basieren auf einer Reihe von Schätzungen und/oder Annahmen sowie Informationen, die dem Unternehmen derzeit zur Verfügung stehen und die zwar als angemessen erachtet werden, jedoch bekannten und unbekannten Risiken, Ungewissheiten und anderen Faktoren unterliegen, die dazu führen können, dass die tatsächlichen Ergebnisse und zukünftigen Ereignisse wesentlich von den in solchen zukunftsgerichteten Aussagen ausgedrückten oder implizierten Ergebnissen abweichen. Leser werden darauf hingewiesen, dass solche zukunftsgerichteten Aussagen weder Versprechen noch Garantien darstellen und bekannten und unbekannten Risiken und Unsicherheiten unterworfen sind, einschließlich, aber nicht beschränkt auf allgemeine geschäftliche, wirtschaftliche, wettbewerbsbezogene, politische und soziale Unsicherheiten, ungewisse und volatile Aktien- und Kapitalmärkte, Mangel an verfügbarem Kapital, tatsächliche Ergebnisse von Explorationsaktivitäten, Umweltrisiken, zukünftige Preise für Basis- und andere Metalle, Betriebsrisiken, Unfälle, Arbeitsprobleme, Verzögerungen bei der Erlangung behördlicher Genehmigungen und Zulassungen sowie andere Risiken in der Bergbauindustrie.\n\nDas Unternehmen befindet sich derzeit in der Explorationsphase. Die Exploration ist von Natur aus hochspekulativ, mit vielen Risiken verbunden, erfordert erhebliche Ausgaben und führt möglicherweise nicht zur Entdeckung von Minerallagerstätten, die rentabel abgebaut werden können. Darüber hinaus verfügt das Unternehmen derzeit über keine Reserven auf seinen Konzessionsgebieten. Daher kann nicht garantiert werden, dass sich solche zukunftsgerichteten Aussagen als zutreffend erweisen, und die tatsächlichen Ergebnisse und zukünftigen Ereignisse können erheblich von den in solchen Aussagen erwarteten abweichen.\n\nHinweis/Disclaimer zur Übersetzung (inkl. KI-Unterstützung): Die Originalmeldung in der Ausgangssprache (in der Regel Englisch) ist die einzige maßgebliche, autorisierte und rechtsverbindliche Fassung. Diese deutschsprachige Übersetzung/Zusammenfassung dient ausschließlich der leichteren Verständlichkeit und kann gekürzt oder redaktionell verdichtet sein. Die Übersetzung kann ganz oder teilweise mithilfe maschineller Übersetzung bzw. generativer KI (Large Language Models) erfolgt sein und wurde redaktionell geprüft; trotzdem können Fehler, Auslassungen oder Sinnverschiebungen auftreten. Es wird keine Gewähr für Richtigkeit, Vollständigkeit, Aktualität oder Angemessenheit übernommen; Haftungsansprüche sind ausgeschlossen (auch bei Fahrlässigkeit), maßgeblich ist stets die Originalfassung. Diese Mitteilung stellt weder eine Kauf- noch eine Verkaufsempfehlung dar und ersetzt keine rechtliche, steuerliche oder finanzielle Beratung. Bitte beachten Sie die englische Originalmeldung bzw. die offiziellen Unterlagen auf www.sedarplus.ca, www.sec.gov, www.asx.com.au oder auf der Website des Emittenten; bei Abweichungen gilt ausschließlich das Original.\n\nDie englische Originalmeldung finden Sie unter folgendem Link:https://www.irw-press.at/press_html.aspx?messageID=83798Die übersetzte Meldung finden Sie unter folgendem Link:https://www.irw-press.at/press_html.aspx?messageID=83798&tr=1\n\n\n\nNEWSLETTER REGISTRIERUNG:\n\nAktuelle Pressemeldungen dieses Unternehmens direkt in Ihr Postfach:http://www.irw-press.com/alert_subscription.php?lang=de&isin=CA34638F1053Mitteilung übermittelt durch IRW-Press.com. Für den Inhalt ist der Aussender verantwortlich.Kostenloser Abdruck mit Quellenangabe erlaubt."} +{"url": "https://www.hellenicshippingnews.com/the-commodities-feed-oil-trades-lower-on-de-escalation-hopes/", "title": "The Commodities Feed : Oil trades lower on de - escalation hopes | Hellenic Shipping News Worldwide", "publish_date": "2026-04-16T12:32:28Z", "full_text": "Energy- US oil exports jump to record levels\n\nThe oil market continues to edge lower amid hopes that the US and Iran extend their ceasefire by another 2 weeks, along with a potential resumption in talks to bring an end to the war. However, the physical market is becoming tighter every day that passes without a restart of oil flows through the Strait of Hormuz. After taking into consideration pipeline diversions and the trickle of tankers through the Strait of Hormuz, we estimate that roughly 13m b/d has been disrupted. But with the US blockade, this number could creep higher. The divergence between the futures and physical markets is clear: dated Brent traded around $117/bbl, while front-month Brent futures settled a little below $95/bbl yesterday. The key upside risk for the market is that peace talks between the US and Iran break down. This isn’t an unrealistic scenario, given that US and Iranian demands remain fairly wide apart.\n\nThe latest data from the Energy Information Administration (EIA) shows that US crude oil exports jumped by 1.08m b/d week-on-week to 5.23m b/d- the highest volume since September 2025. However, total oil and refined product exports surged by 1.03 m b/d WoW, hitting a record 12.74 m b/d. These stronger US exports reflect buyers turning to other markets for supply amid disruptions in the Middle East. Despite strong exports, US crude oil inventories declined only marginally over the week, falling by 913k barrels. Refined product stocks saw more meaningful declines, with gasoline and distillate inventories falling by 6.33m barrels and 3.12m barrels, respectively.\n\nWith buyers shifting toward US barrels, the domestic market is set to tighten as long as Middle East disruptions persist, likely prompting a supply response from US producers. US drilling activity, however, has barely moved since the start of the conflict. According to Baker Hughes data the US oil rig count stood at 411 last week, up from 407 prior to the war. The lack of drilling activity also ties in with the EIA’s domestic crude oil production forecasts, which suggest little change in output this year. If we see a pickup in US drilling activity, it would have a more meaningful impact on oil output over 2027.\n\nEuropean gas prices continue to edge lower amid hopes of de-escalation in the Middle East, while EU gas storage levels move closer to 30% full as the region moves deeper into the injection season. High LNG send-outs in Europe have kept the market comfortable. Investment funds also reduced their net long in TTF by 37.4 TWh over the last week to 271.8 TWh. Clearly, the longer disruptions in the Middle East persist, the more competition we’ll see from Asia as buyers seek alternative supplies. JKM continues to trade at a premium to TTF, so we should be seeing cargoes being redirected towards Asia.\n\nMetals – Copper trades near one month high on Iran optimism\n\nCopper rose to around a one‑month high this week, with broader gains across industrial metals as markets priced in easing macro risks. Optimism that the US and Iran could restart talks helped unwind some of the recent pressure from fears of higher energy costs and weaker growth.\n\nHowever, the market remains highly headline‑driven. Any escalation in the conflict, renewed spikes in energy prices or signs of softer demand could quickly reverse sentiment. In a de‑escalation scenario, copper would likely outperform, supported by expectations of eventual rate cuts, a weaker dollar and a broader improvement in risk appetite.\n\nDownstream supply risks are also gaining attention. Sulfuric acid is emerging as a bottleneck for SX‑EW copper output, with around half of seaborne sulfur transiting the Strait of Hormuz. China’s sulfuric acid prices have risen around 90% since the start of the Iran war. Export bans introduced following the Hormuz shipping halt are raising disruption risks to acid-dependent supply in Chile, Peru and the Democratic Republic of the Congo.\n\nPositioning data points to improved sentiment. Speculators increased their bullish LME copper bets by 2,329 net‑long positions to 48,225, the most bullish stance in more than three months, according to weekly futures and options data.\n\nIn precious metals, gold remains supported amid renewed optimism around de‑escalation. The pullback in oil prices is easing some of the inflation concerns that weighed on prices earlier in the conflict. The move reflects a broader shift in market focus. While gold initially fell sharply as liquidity pressures forced selling, losses have since partially recovered as growth concerns have re‑emerged and price swings have become less extreme. While higher real rates, a firmer dollar, and profit-taking could weigh on near-term price action, recent pullbacks suggest underlying demand remains resilient.\n\nSource: ING"} +{"url": "https://sudanile.com/%D8%A7%D9%84%D8%A7%D9%82%D8%AA%D8%B5%D8%A7%D8%AF-%D8%A7%D9%84%D8%B3%D9%88%D8%AF%D8%A7%D9%86%D9%8A-%D9%81%D9%8A-%D8%B8%D9%84-%D8%AD%D8%B1%D8%A8%D9%8A%D9%86/", "title": "الاقتصاد السوداني في ظل حربين", "publish_date": "2026-04-16T12:32:28Z", "full_text": "شاركها Facebook\n\nTwitter\n\nالاقتصاد السوداني في ظل حربين\n\nالسلطة والموارد واستدامة الصراع\n\nمجتزأ من ورقة بحثية\n\no.sidahmed09@gmail.com\n\nعمر سيد احمد\n\n‎باحث في الاقتصاد السوداني — خبير مصرفي ومالي وتمويل مستقل\n\nأبريل ٢٠٢٦\n\nالسودان يمتلك أكبر إمكانات زراعية في أفريقيا — لكنه في هذه اللحظة بالذات بات في حاجة ماسة إلى من يُطعمه\n\nفي أبريل 2023، اندلعت في الخرطوم حرب لم تُبقِ شيئاً على حاله. انهارت المستشفيات، واحترقت الأسواق، وتحوّلت المدينة التي كانت تحتضن ثلث اقتصاد البلاد إلى ساحة معركة. لكن السودان لم يكتفِ بهذه الصدمة — ففي مطلع 2026، جاءته حرب ثانية من بعيد، حرب لم تُطلق رصاصة واحدة على أراضيه ومع ذلك ألقت بثقلها على كل مواطن وكل مزارع وكل تاجر: إنها توترات مضيق هرمز وحرب الخليج التي أشعلت أسعار الوقود وأطالت خطوط الإمداد وأرهقت فاتورة الاستيراد.\n\nبين هاتين الحربين، يجد السودان نفسه في موقع استثنائي من الهشاشة: يدفع كامل تبعات الأزمة الإقليمية دون أن يجني حبة واحدة من ارتفاع أسعار النفط. بل الأمر أكثر مفارقة: السودان محاط بأربع دول نفطية على حدوده — ليبيا وتشاد وجنوب السودان والسعودية — لكنه يستورد 80 إلى 90% من احتياجاته من الوقود. هذا ليس قدراً، بل نتيجة قرار سياسي واحد صدر عام 2011: انفصال جنوب السودان الذي أخذ معه 75% من الاحتياطيات النفطية المشتركة، فتحوّل السودان بين ليلة وضحاها من منتج إلى مستورد، دون أن يبني احتياطياً استراتيجياً، ولا طاقة تكريرية بديلة.\n\nقبل الحرب — إمكانات هائلة وجرح مفتوح\n\nكان المشهد قبيل أبريل 2023 يجمع بين نقيضين لا يُريح النظر إليهما معاً. على جهة النعمة: أكثر من 84 مليون هكتار صالح للزراعة، و110 مليون رأس من الثروة الحيوانية، و70% من صادرات الصمغ العربي عالمياً، واحتياطيات ذهبية مؤكدة تبلغ 533 طناً مع احتياطيات أخرى قيد التقييم تتجاوز 1,100 طن. بلد كان يُطعم نفسه وجيرانه، وتجري في أرضه ثروات قد يحسده عليها كثيرون.\n\nوعلى الجهة الأخرى: شمول مالي لا يتجاوز 7% من البالغين — أدنى من معظم دول أفريقيا جنوب الصحراء. اقتصاد يعتمد شبه كلياً على استيراد طاقته دون أي احتياطي استراتيجي. سعر صرف يقف عند 570 جنيهاً للدولار كاشفاً عن هشاشة نقدية مزمنة. والأخطر: منظومة الذهب خارج الدولة بنسبة 70%، ومنظومة النفط مشلولة، والأرض خصبة لكن المزارع لا يجد تمويلاً للموسم. لم تكن تلك هشاشة عارضة — بل كانت قنبلة موقوتة تنتظر الشرارة.\n\nفي 2022، كان سعر الدولار 570 جنيهاً. في أبريل 2026 أصبح 4,150 جنيهاً في السوق الموازي. هذا ليس انخفاضاً في قيمة العملة — هذا انهيار نظام.\n\nبعد الحرب — الانهيار الذي لا تحتمله الأرقام\n\nفي أقل من ثلاث سنوات، تحوّل اقتصاد هش إلى كارثة موثقة بالأرقام. انكمش الناتج المحلي بنسبة 37.5% في عام 2023 وحده وفق البنك الأفريقي للتنمية — رقم لم تشهده إلا دول تمر بحروب تدميرية شاملة أو كوارث طبيعية كبرى. وبحلول 2025، بلغ الانكماش التراكمي 42%، أي أن الاقتصاد السوداني فقد قرابة نصف حجمه في أقل من ثلاث سنوات.\n\nلكن الأرقام الكلية تبقى باردة إذا لم تُترجم إلى حياة بشرية: 4.6 مليون وظيفة اختفت، والبطالة قفزت من 32% عام 2022 إلى 58% عام 2024. 64% من السودانيين يعيشون اليوم في فقر مدقع — ارتفاعاً من 35% قبل الحرب. 8.8 مليون نازح داخلياً في أكبر أزمة نزوح يشهدها العالم. أكثر من 25 مليون شخص يعانون انعدام الأمن الغذائي الحاد. وأكثر من 150 ألف حالة وفاة مباشرة منذ اندلاع القتال.\n\nالسودان يمتلك أكثر من 200 مليون فدان) صالح للزراعة، لكن 41% من سكانه يعانون انعدام الأمن الغذائي و64% تحت حد الفقر. هذه ليست أزمة موارد — بل أزمة حوكمة وسلام\n\nوعلى صعيد البنية الاقتصادية، توقف أكثر من 60% من المصانع عن العمل. تراجع قطاع الخدمات بنسبة 43.2% والصناعة أكثر من 50%. انهار القطاع المصرفي إذ خرج 90 إلى 95% من الكتلة النقدية خارج الجهاز المصرفي، وغادرت أكثر من ستة بنوك أجنبية السوق وعاد بعضها بعد عامين والتضخم تجاوز 177% وفق صندوق النقد الدولي لعام 2024، في بيئة ركود تضخمي نادرة يجمع بين انكماش الإنتاج وارتفاع الأسعار في آنٍ واحد\n\nالصدمة الثانية — حين جاءت الحرب من البحر\n\nكانت تلك هي الحال حين فتح عام 2026 على توترات مضيق هرمز. يمر عبر هذا الممر الضيق ما يقارب 21 مليون برميل نفط يومياً — 21% من الاستهلاك العالمي. حين تضطرب سلاسل الإمداد عند هرمز، لا يكون السودان في القائمة الأولى للمتضررين في تصورات المحللين — لكنه في الواقع من أكثر الاقتصادات العالمية هشاشةً أمام هذه الصدمة، وذلك بالضبط لأنه جاء إلى هذه الأزمة منهكاً بالفعل.\n\nأقساط التأمين البحري على ناقلات النفط قفزت من 0.1–0.2% من قيمة السفينة إلى ما بين 0.5% و1% في ذروة الأزمة — ما يعادل إضافة مليون دولار لتكلفة رحلة الناقلة الواحدة. وأسعار الشحن على خطوط الخليج–البحر الأحمر ارتفعت 200 إلى 300% مقارنة بما قبل أزمة البحر الأحمر عام 2023. أما مسارات الشحن فقد تحوّلت عبر رأس الرجاء الصالح مضيفةً 10 إلى 14 يوماً لكل رحلة، وهو ما انعكس في تراجع البضائع العابرة عبر ميناء بورتسودان بأكثر من 30% في الربع الأول من 2026.\n\nسعر الجازولين في السودان بلغ 6,867 جنيهاً للتر في أبريل 2026. والديزل ليس هنا وقوداً للسيارات فحسب — بل المحرك الذي تدور حوله منظومة الإنتاج الزراعي كلها: مضخات الري، وآلات الحراثة، ونقل المحاصيل.\n\nإجمالي الزيادة في تكلفة وحدة الطاقة المستوردة جراء الأزمتين الداخلية والإقليمية معاً يتجاوز 1,200% مقارنة بما كان عليه الوضع قبيل أبريل 2023. بمعنى آخر: ما كان يكلف جنيهاً صار يكلف اثني عشر جنيهاً وأكثر\n\nالزراعة — حين يجوع المزارع في أخصب بقاع الأرض\n\nفي عالم عادل، يُفترض أن يكون السودان سلة غذاء للقارة. لكن الواقع في 2026 يقول شيئاً آخر تماماً: إنتاج الحبوب انخفض 46% عام 2023، وأسعار الغذاء ارتفعت 350% مقارنة بمتوسط السنوات الخمس الماضية. ويشير معهد بحوث السياسات الغذائية الدولية IFPRI إلى أن 7.5 مليون شخص إضافي قد ينضمون إلى صفوف الفقر في السيناريو المتطرف.\n\nمشروع الجزيرة — الذي يُنتج 50% من القمح السوداني و10% من الذرة، ويضم أكثر من 4,300 كيلومتر من شبكة القنوات — يمثل النموذج الأوضح للانهيار المتسلسل: تعطّل الري بسبب شُح الديزل، وانهار التمويل مع شلل البنك الزراعي السوداني، واستُولي على المحاصيل والأسمدة على نطاق واسع. وقفز سعر اليوريا من 490 دولاراً للطن قبل الحرب إلى نحو 700 دولار، مضاعفاً تكلفة الموسم الزراعي في وقت انهارت فيه القدرة التمويلية للمزارعين.\n\nأما الثروة الحيوانية التي كانت ركيزة صادرات البلاد بأكثر من 110 مليون رأس، فباتت تواجه ثلاثة تهديدات متزامنة: انعدام المسارات الرعوية التقليدية جراء الحرب، وعلقت إمدادات الأدوية البيطرية في مراكز الشحن الخليجية مُعرِّضةً القطيع لأوبئة قد تكون كارثية، وفقد ميناء بورتسودان قدرته على استقبال السفن الكبيرة. النتيجة: صادرات الثروة الحيوانية خسرت 55% من قيمتها منذ اندلاع الحرب.\n\nالذهب — أرض الثروة وخزينة الحرب\n\nكلمة “نوب” (NOB) في لغات النوبيين تعني الذهب. ومنها اشتُق اسم “نوبيا” — أرض الذهب. وقد شنّ الفراعنة حملات متكررة على هذه الأرض للسيطرة على مناجمها دون أن يُفلحوا في إخضاعها بالكامل. اليوم، لا تحتاج أرض الذهب إلى فراعنة خارجيين — فقواتها المتحاربة تنهبها بنفسها.\n\nالفجوة الإحصائية تكشف القصة بجلاء صادم: في الفترة من 2022 إلى 2024، ارتفع إنتاج الذهب من 34.5 طن إلى 65 طناً — زيادة 88%. وفي الوقت نفسه، ارتفعت أسعار الذهب العالمية أكثر من 30%. لكن العائدات الرسمية انخفضت من 2.02 مليار دولار إلى 1.6 مليار دولار. إنتاج أعلى، وأسعار أعلى، وعائدات أقل — لا تفسير لهذه المعادلة المعكوسة إلا تضخّم التهريب.\n\nتُقدَّر نسبة الذهب المُهرَّب بين 50% و70% من الإنتاج الفعلي سنوياً — وهو ما يعادل بأسعار الذهب اليوم ما بين 7.5 و10.5 مليارات دولار تتسرب سنوياً خارج الخزينة. والأكثر إيلاماً أن إجمالي الإنتاج المُعلَن البالغ 64.4 طناً عام 2024 تبلغ قيمته اليوم نحو 9.8 مليار دولار، في حين لم تحصّل الحكومة رسمياً سوى 1.6 مليار دولار، أي ما لا يتجاوز 16% من القيمة الحقيقية لإنتاجها المُعلَن وحده. فضلاً عن الإنتاج غير المُصرَّح به في مناطق الدعم السريع — الذي تُقدّره مؤسسات بحثية كـ SWISSAID وChatham House بما يرفع الإجمالي الفعلي إلى 80–90 طناً سنوياً، أي ما يعادل 12 إلى 13.7 مليار دولار بأسعار اليوم. هذه ليست فجوة إحصائية بل نزيف سيادي منظَّم — ثروة تكفي لإعادة بناء ما دمّرته الحرب تتسرب يومياً من خزينة الشعب إلى شبكات التهريب والمليشيات.\n\nأفرزت الحرب اقتصادَين ذهبيَّين متوازيَين لا يلتقيان: الجيش السوداني يسيطر على التعدين الصناعي في الشمال ونهر النيل والبحر الأحمر، ويُموّل عملياته جزئياً عبر تصدير الذهب إلى مصر ثم الإمارات، فضلاً عن صفقات مع روسيا سُدِّدت بالذهب مقابل السلاح. وقوات الدعم السريع تسيطر على التعدين الأهلي في دارفور وغرب كردفان، وتدير مناطقها عبر شركة الجنيد للأنشطة المتعددة، ومن بينها مصنع في سنقو بجنوب دارفور يُشغَّل بمشاركة روسية عبر أفريقا كوربس.\n\nهذه ليست مجرد أرقام اقتصادية — بل صورة بالغة الدلالة عن دولة تفككت: حين يصبح الذهب الوطني عملة الحرب الداخلية، ووسيلة الحصول على السلاح الخارجي، وأداة التمويل لميليشيات تقاتل في الأراضي السودانية نفسها — فإن السؤال لم يعد كيف تُحسَّن عائدات الذهب، بل كيف تستعيد الدولة سيادتها على مواردها. وفي أبريل 2026، يبلغ سعر الذهب 4,830 دولاراً للأونصة — أي 152 مليون دولار للطن. ثروة سودانية هائلة تذهب يومياً إلى مصافي الإمارات ومنظومات السلاح والمليشيات وجيوب الطفيليين وأثرياء الاقتصاد الموازي — بينما يموت السودانيون فوق أرضهم الذهبية فقراً وحرباً.\n\nسادساً: النفط والموارد — وقود الحرب لا الاقتصاد\n\nحقل هجليج في غرب كردفان كان قلب الإنتاج النفطي السوداني — يُنتج أكثر من 60% من إجمالي الإنتاج البالغ 65–70 ألف برميل يومياً قبل الحرب. سيطرت عليه قوات الدعم السريع في ديسمبر 2025 مُعلنةً إياه مصدراً لتمويل عملياتها، قبل أن يستعيده الجيش مطلع 2026 في معركة وصفها المحللون بأنها الأعنف منذ اندلاع الحرب. أما مصفاة الجيلي — بطاقة 100 ألف برميل يومياً تُغطّي 70% من الاستهلاك المحلي — فقد دُمِّرت شبه كامل بخسائر تجاوزت 3 مليارات دولار.\n\nالدرس الأعمق ليس في الأرقام — بل في المعادلة التي كشفتها الحرب: طرفا النزاع لا يُريدان وقف الموارد، بل يُريدان امتلاكها. طوّر كلاهما منظومة موازية للإيرادات تشمل بيع الوقود المُهرَّب وفرض رسوم عبور والتفاوض مع شركات أجنبية. النتيجة: لم يُؤدِّ تعطّل النفط إلى الضغط نحو التسوية، بل أعاد تشكيل اقتصاد الحرب بآليات أكثر مرونة وخطورة.\n\nالصمغ العربي — سلعة يستحوذ السودان على 70% من إنتاجها العالمي — لم تسلم هي الأخرى. كشف تقرير أممي عام 2025 أن 14.6 مليون دولار من الصمغ المنهوب وُظِّفت لتمويل أنشطة قوات الدعم السريع في ستة أشهر فحسب، فيما بلغت خسائر تجارته الرسمية 200 مليون دولار حتى مطلع 2025. ويبدو المشهد الكلي صورة واحدة متماسكة المعنى: كل مورد يمتلكه السودان — ذهب، نفط، صمغ، ثروة حيوانية — تحوّل إلى وقود لحرب تأكله من الداخل.\n\nسابعاً: الجنيه والمصارف — حين تتفكك الثقة\n\nانهيار الجنيه لا يمكن اختزاله في عامل واحد. صحيح أن استيراد الوقود أصبح أحد أهم المحركات المباشرة للطلب على الدولار — إذ تحوّل السودان بعد تدمير مصفاة الجيلي إلى دولة تستورد 80 إلى 90% من مشتقاتها النفطية في توقيت عالمي شديد التعقيد. لكن الوقود يظل جزءاً من صورة أوسع وأعمق.\n\nالصورة الكاملة: واردات تقارب 9.9 مليار دولار مقابل صادرات لا تتجاوز 3 إلى 4 مليارات — فجوة هيكلية مزمنة. وعائدات الذهب تتسرب عبر قنوات الأسواق الموازية بنسبة 70 إلى 80%. والبنك المركزي يموّل العجز بالإصدار النقدي مُشعلاً تضخماً يتجاوز 200%. والثقة في العملة الوطنية انهارت كلياً — دفعت الأفراد والتجار والمؤسسات إلى الدولار ملاذاً وحيداً لحفظ الثروة.\n\nوفي القطاع المصرفي، الصورة لا تقل قتامة: أصول البنوك السودانية لا تتجاوز 12 مليار دولار — أي 20% من الناتج المحلي، مقارنة بـ470 مليار دولار في مصر (70% من الناتج). الشمول المالي 7% من البالغين، في مقابل 83% في كينيا و64% في مصر. نسبة القروض المتعثرة تجاوزت 21%. ونسبة القروض إلى الودائع قفزت من 68% عام 2022 إلى 183.6% بحلول 2025 — رقم يعني ببساطة أن البنوك باتت تُقرض من مال لا تمتلكه.\n\nحين يخرج 95% من النقد خارج الجهاز المصرفي، لا يعني ذلك أن الناس فقراء فحسب — بل يعني أن الدولة فقدت رؤية اقتصادها وقدرتها على توجيهه.\n\nثامناً: المغتربون والمساعدات — الشرايين المقطوعة\n\nكان المغتربون السودانيون — أكثر من مليونين في دول الخليج وحدها، وخمسة ملايين في بقية أنحاء العالم — يشكّلون الشريان الأهم خارج الدولة: تحويلاتهم تمثل ما بين 7.6% و15% من الناتج المحلي الإجمالي، وهي في كثير من الأحيان الفارق بين العيش والجوع لملايين الأسر. لكن حرب الخليج جاءت لتقطع هذا الشريان أيضاً: أكثر من 220 ألف عامل أُعيدوا من منطقة الخليج خلال مارس 2026 وحده.\n\nوفيما يتعلق بالمساعدات الإنسانية، وثّقت منظمة Think Global Health أن ما يزيد على 600 ألف دولار من الأدوية الأساسية المخصصة لـ90 مرفقاً صحياً علقت في دبي جراء إغلاق المطار. واضطر برنامج الغذاء العالمي إلى تحويل شحنات من المكملات الغذائية عبر رأس الرجاء الصالح. ولم يُموَّل سوى 21% من نداء الأمم المتحدة الإنساني لعام 2025، في حين قلّصت الدول المانحة ميزانياتها الإنسانية 40% مقارنة بعام 2024.\n\nتاسعاً: مسارات النهضة — إذا جاء السلام\n\nثمة جملة لافتة في صميم أي تحليل جاد للوضع السوداني: كل توصية اقتصادية في هذا المقال — دون استثناء — مشروطة بوقف الحرب. هذا ليس كلاماً خطابياً، بل حقيقة رياضية: لا يمكن استعادة الإنتاج الزراعي في ظل معارك تُهجّر المزارعين، ولا إعادة تشغيل مصفاة الجيلي في ظل قصف متواصل، ولا إعادة الثقة في الجهاز المصرفي في ظل اقتصاد حرب يستوعب 90% من النشاط الموازي.\n\nالذهب: من وقود الحرب إلى رافعة النهضة\n\nإذا جاء السلام، فإن الذهب يمثل نقطة الانطلاق الأجدى والأسرع. المطلوب ثلاث مراحل متتابعة:\n\n• أولاً: استعادة الولاية المؤسسية للدولة على كل الموارد المعدنية — بإلغاء تراخيص الجهات النظامية، ونشر عقود الامتياز علناً، وإنشاء سجل وطني إلكتروني شفاف.\n\n• ثانياً: ضبط السوق وتجفيف التهريب عبر بورصة سودانية للذهب ومراكز شراء متنقلة في مناطق التعدين بأسعار تنافسية تُقلّص الفارق الذي يُغذي التهريب.\n\n• ثالثاً: أدوات سيادية لتحويل الذهب إلى ثروة وطنية: سبيكة سيادية على غرار التجربة التركية، وسندات ذهبية مضمونة تستهدف المغتربين والمستثمرين الإقليميين، ومدينة ذهب سودانية تُكرِّر المعدن محلياً بدلاً من تصدير الخام لمصافي الخليج.\n\nالزراعة: الثروة النائمة\n\nمفارقة أن تمتلك أخصب أرض في أفريقيا وتستورد 80% من قمحك. استراتيجية النهضة الزراعية تبدأ بخطوة واحدة عاجلة: إعادة تشغيل مشروع الجزيرة الذي يُنتج نصف القمح السوداني. ثم تليها خطوات بنيوية: تأمين الديزل والأسمدة، وإصلاح البنك الزراعي المشلول، وتوطين إنتاج البذور تدريجياً. والأهم على المدى البعيد: التحول من تصدير الخام إلى التصدير المُصنَّع — الذهب يُكرَّر محلياً، والصمغ العربي يُحوَّل صناعياً، والثروة الحيوانية تتحول إلى صناعات لحوم وألبان وجلود.\n\nعقد اجتماعي جديد\n\nلكن الإصلاح الاقتصادي وحده لا يكفي. الجذر الحقيقي للأزمة ليس اقتصادياً في جوهره — بل هو أزمة سلطة وموارد وعدالة. إعادة بناء السودان تستلزم عقداً اجتماعياً جديداً يقوم على خمسة أركان:\n\n• عدالة انتقالية تحاسب من نهبوا الموارد العامة\n\n• مشاركة وطنية شاملة تضمن تمثيل كل مكونات السودان\n\n• توزيع عادل لعائدات الموارد بين الأقاليم والمركز يعالج الجذر الاقتصادي للصراع\n\n• حوكمة رشيدة تفكك شبكات الاقتصاد الموازي\n\n• إصلاح منظومتَي التعليم والصحة بوصفهما استثماراً في رأس المال البشري لا ترفاً\n\nدروس من العالم\n\nلا تقرأ هذه الأزمة في فراغ. رواندا خرجت من إبادة جماعية عام 1994 راح ضحيتها مليون شخص، لتحقق نمواً متوسطه 8% سنوياً لعقدين وتتحول إلى مركز إقليمي للتكنولوجيا — بفضل العدالة الانتقالية والرؤية الوطنية الواضحة. وفيتنام تحوّلت من دولة تستورد الأرز إلى ثاني أكبر مُصدِّر له في العالم بعد إصلاح زراعي جذري عام 1986 يُمكِّن صغار المزارعين. وألمانيا نهضت من دمار الحرب العالمية الثانية خلال عقدين بفضل الدعم الدولي والإصلاح النقدي الجذري والتركيز على الصناعات التحويلية.\n\nالقاسم المشترك في هذه التجارب ليس الثروة الطبيعية — بل القرار السياسي بتحويل تلك الثروة إلى استثمار في الإنسان والمؤسسة. والسودان يمتلك من الموارد الطبيعية ما يفوق رواندا وفيتنام معاً. ما ينقصه هو السلام والإرادة والرؤية.\n\nخاتمة: الثروة في خزينة الشعب\n\nفي عام 2026، تجاوزت أسعار الذهب العالمية 4,800 دولار للأونصة — وللطن الواحد 152 مليون دولار. والسودان يمتلك 533 طناً من الاحتياطيات المؤكدة مع أكثر من 1,100 طن قيد التقييم. وينتج 65 طناً سنوياً من الذهب. وتحت أراضيه مزيد من الذهب والنفط والمعادن. وفوق أراضيه أخصب أرض في القارة. وفي سمائه مطر يُروي 84 مليون هكتار.\n\nكل هذا حاضر. لكن 64% من السودانيين يعيشون في فقر مدقع. و8.8 مليون نازح داخلياً. و25 مليون يعانون انعدام الأمن الغذائي. وجنيه انهار من 570 إلى 4,150 للدولار. والذهب يُهرَّب بنسبة 70 إلى 80% خارج الحدود — تبلغ قيمته بأسعار اليوم ما بين 7.5 و10.5 مليارات دولار سنوياً. وموارد البلاد تُحوَّل يومياً إلى ذخيرة ووقود للحرب.\n\nهذه المفارقة الصارخة بين ثروة الأرض وفقر أهلها ليست قدراً — بل هي نتيجة خيارات سياسية وحروب متعمدة ونهب ممنهج. وبالقدر ذاته، فإن تجاوزها ممكن — حين يتوقف القتال، وتعود الدولة إلى الدولة، والثروة إلى أصحابها.\n\n★ السودان يمتلك من الذهب ما يكفي لإعادة بناء ما دمّرته الحرب. شريطة أن يُعاد توجيهه من خزينة المليشيات إلى خزينة الشعب.\n\nالسودان لا يحتاج إلى مساعدة مؤقتة — بل إلى سلام دائم يُعيد للموارد وظيفتها الإنتاجية بدلاً من أن تكون وقوداً للحرب.\n\nمصادر ومراجع رئيسية\n\n• البنك الدولي — Sudan Economic Monitor, Spring 2024\n\n• صندوق النقد الدولي — World Economic Outlook, April 2025 & 2026\n\n• البنك الأفريقي للتنمية — Macroeconomic Performance and Outlook 2024\n\n• منظمة الأغذية والزراعة (FAO) — تقرير السودان، مارس 2025\n\n• برنامج الغذاء العالمي (WFP) — تقارير الطوارئ 2025\n\n• لجنة خبراء الأمم المتحدة بشأن السودان — تقرير 2024\n\n• Chatham House — Gold and the War in Sudan, March 2025\n\n• SWISSAID / African Gold Report — Sudan Gold Report 2024–2025\n\n• وكالة الطاقة الدولية (IEA) — Oil Market Report Q1 2026\n\n• UNCTAD — Maritime Transport Report, Red Sea Disruptions, Q1 2026\n\n• JM Bullion / Fortune — Gold Spot Price April 15, 2026: $4,830/oz (~$152,180/kg)\n\nمقال مجتزأ من ورقة بحثية *\n\nعمر سيد أحمد | o.sidahmed09@gmail.com | أبريل ٢٠٢٦"} +{"url": "https://www.capital.gr/agores/3985670/xrimatistirio-epilektikes-kiniseis-kai-auximeni-metablitotita/", "title": "Χρηματιστήριο : Επιλεκτικές κινήσεις και αυξημένη μεταβλητότητα", "publish_date": "2026-04-16T12:32:28Z", "full_text": "ΤΕΛΕΥΤΑΙΑ ΕΝΗΜΕΡΩΣΗ 14:10\n\nτου Μάνου Χαχλαδάκη\n\nΣυντηρείται το θετικό κλίμα στην αγορά της Αθήνας που δείχνει διάθεση να κινηθεί για τρίτη ημέρα ανοδικά, αν και με χαμηλούς ρυθμούς εν μέσω της αυξημένης μεταβλητότητας που χαρακτηρίζει τις συναλλαγές.\n\nΕιδικότερα, ο Γενικός Δείκτης βρέθηκε έως και τις 2.311 μονάδες (+0,96%) αλλά πλέον διαπραγματεύεται στις 2.294 μονάδες με μικρά κέρδη 0,2% και τον τζίρο στα 145 εκατ. ευρώ, ενώ έχουν διακινηθεί 23 εκατ. τεμάχια.\n\nΟ τραπεζικός δείκτης βρέθηκε να ενισχύεται έως και κατά 1,3% (2.707 μον.) αλλά πλέον έχει γυρίσει ελαφρώς αρνητικός στις 2.668 μονάδες, ο FTSE της υψηλής κεφαλαιοποίησης σημειώνει άνοδο κατά 0,2% στις 5.840 μον. και ο FTSEM της μεσαίας στις 2.822 μον. με +0,4%\n\nΟυσιαστικά η συνεδρίαση δείχνει να εξελίσσεται σε διελκυστίνδα μεταξύ ορισμένων blue chips που διαφοροποιούνται έντονα θετικά, πρωτίστως της Metlen αλλά και των ΓΕΚ ΤΕΡΝΑ, Λάμδα και Aegean και από την άλλη πλευρά των τραπεζών, που έχασαν το αρχικό τους μομέντουμ και σταδιακά περνάνε σε αρνητικό έδαφος - πιθανώς και από το βάρος του profit taking που προκαλεί το ράλι 5,6% της Τρίτης.\n\nΚατά τα άλλα, η συνεδρίαση ξεκίνησε με κεκτημένη ταχύτητα από χθες (FTSEM +1,5%) για τα mid caps αλλά στην πορεία επήλθε επίσης κάποια εξισορρόπηση, με εμφανές και εδώ το χαρακτήρα stock picking στις τοποθετήσεις.\n\nΓενικότερα πάντως, το θετικό κλίμα διατηρείται στις αγορές διεθνώς καθώς οι επενδυτές δείχνουν να προεξοφλούν θετική έκβαση στις διαπραγματεύσεις ΗΠΑ - Ιράν.\n\nΕνδεικτικό είναι ότι στην Wall Street, αφότου μάζεψαν όλες τις απώλειες του πολέμου, οι S&P 500 και Nasdaq κατέγραψαν χθες νέα ιστορικά υψηλά (+0,8% και +1,6% αντίστοιχα), με τον πρόεδρο Τραμπ να επαναλαμβάνει ότι \"ο πόλεμος είναι πολύ κοντά στο να τελειώσει\" και αξιωματούχους του Λευκού Οίκου να αναφέρουν ότι σχεδιάζεται ένας νέος, δεύτερος, γύρος διαπραγματεύσεων.\n\nΣτην Ευρώπη οι κινήσεις είναι μάλλον πιο συγκρατημένες, αν και οι δείκτες σήμερα δείχνουν διάθεση να επιστρέψουν σε θετικό έδαφος μετά την ήπια οπισθοχώρηση χθες, κυρίως υπό το βάρος της πτώσης του κλάδου πολυτελείας που δέχθηκε σημαντικό πλήγμα από τον πόλεμο.\n\nΟι κινήσεις στο ταμπλό\n\nΗ Metlen επιχειρεί σταθερά από το άνοιγμα να δώσει ώθηση στον ΓΔ με εντολές έως τα 36,9 ευρώ (+4,1%).\n\nΙσχυρή άνοδο 2,4% καταγράφουν επίσης η ΓΕΚ ΤΕΡΝΑ που ανακτά τα 40 ευρώ και η Λάμδα στα 6,3 με την Aegean να ακολουθεί από κοντά στα 13,4 με +2%.\n\nΣτις τράπεζες είναι εξαιρετικά έντονη η κινητικότητα στην Πειραιώς που έχει κάνει τζίρο ήδη άνω των 42 εκατ. μόνη της (το 1/4 της συνεδρίασης) αλλά με αισθητή μεταβλητότητα - από τα 8,63 ευρώ (+1,4%) έως τα 8,48 (-0,4%) - ενώ επί του παρόντος βρίσκεται πέριξ του αμετάβλητου.\n\nΗ Alpha κινείται σταθερά ανοδικά με +0,5%, ενώ η ΕΤΕ και η Eurobank υποχωρούν ελαφρώς κατά 0,3%.\n\nΣημειώνεται ότι οι συστημικές έλαβαν ακόμα μία ψήφο εμπιστοσύνης, από την Euroxx που ανέβασε τις τιμές - στόχους κάνοντας λόγο για ευκαιρία για αγορά ενός σημαντικού story ανάπτυξης.\n\nΕκτός ΔΤΡ, η Credia κινείται δυναμικά στις παρυφές του 1,20 με +1,9%.\n\nΟι επιλογές των πωλητών στον 25άρη εστιάζουν κυρίως στις ΔΕΗ και Coca Cola αμφότερες περί του -0,9%.\n\nΣτα mid caps ξεχωρίζει πλέον το ράλι 4% του ΟΛΘ με ιδιαίτερα υψηλό τζίρο άνω των 640 χιλ. ευρώ όλα στο ταμπλό, αφότου ανακοίνωσε νέο ιστορικό υψηλό σε έσοδα και κερδοφορία το 2025.\n\nΗ Alter Ego ενισχύεται επίσης κατά 3% και η Qualco κατά 2%.\n\nΣτον αντίποδα, η Intralot έχει περάσει σε αρνητικό έδαφος στα 1,03 με -0,7%.\n\nΣτο σύνολο το ταμπλό 75 τίτλοι κινούνται ανοδικά, έναντι 50 πτωτικών.\n\nΗ εικόνα διεθνώς\n\nΠεριορισμένες είναι οι διακυμάνσεις των τιμών του πετρελαίου που πλέον κινούνται χαμηλότερα των 100 δολαρίων το βαρέλι. Το Brent στα 95,7 δολ. με +0,8% σήμερα και το αμερικανικό WTI στα 91,7 δολ. με +0,4%.\n\nΣταθεροποιητικές τάσεις δείχνει και το ευρωπαϊκό φυσικό αέριο που κινείται στα 41,7 ευρώ η μεγαβατώρα με +0,7%.\n\nΣτις μετοχές, τα συμβόλαια των δεικτών της Wall Street κινούνται ελαφρώς ανοδικά με την τεχνολογία να διατηρεί προβάδισμα, μετά τα ρεκόρ χθες (S&P 500, Nasdaq).\n\nΤα futures του Dow Jones στο +0,1%, του S&P 500 στο +0,1% και του Nasdaq στο +0,2%.\n\nΉπια ανοδική είναι η τάση και στην Ευρώπη. Ο γερμανικός DAX στο +0,5%, ο γαλλικός CAC 40 στο +0,5%, ο βρετανικός FTSE 100 στο +0,6%, ο ιταλικός FTSE MIB στο +0,35%, ο ισπανικός IBEX 35 στο +0,2% και η πανευρωπαϊκή υψηλή κεφαλαιοποίηση του Stoxx 50 στο +0,4%.\n\nΟι αγοραστές έχουν προβάδισμα και στην αγορά ομολόγων, με τις αποδόσεις να υποχωρούν ως εκ τούτου. Του δεκαετούς ΗΠΑ στο 4,27%, του γερμανικού τίτλου στο 3,01% και του γαλλικού στο 3,65%, με τον ελληνικό στο 3,75%.\n\nΤέλος, ελαφρώς ανοδική είναι η τάση και στα μέταλλα, ο χρυσός στα 4.848 δολάρια η ουγγιά με +0,5% και το ασήμι στα 80,4 δολ. με +1%."} +{"url": "https://www.newratings.de/du/main/company_headline.m?nid=19666857", "title": "newratings . de", "publish_date": "2026-04-16T12:32:28Z", "full_text": "IRW-News: Formation Metals Inc.: Formation Metals durchteuft 1,8 g/t Au auf 21,9 m, östlich von 1,75 g/t Au auf 30,4 m auf fortgeschrittenem Goldprojekt N2: Bohrungen bestätigen Beständigkeit von 300 m innerhalb von 5 km entlang von mineralisiertem Strei\n\n13:14\n\nIRW-PRESS: Formation Metals Inc.: Formation Metals durchteuft 1,8 g/t Au auf 21,9 m, östlich von 1,75 g/t Au auf 30,4 m auf fortgeschrittenem Goldprojekt N2: Bohrungen bestätigen Beständigkeit von 300 m innerhalb von 5 km entlang von mineralisiertem Streichen\n\nHöhepunkte:\n\n- N2-25-004: 0,83 g/t Au auf 40,4 m, beginnend in einer Bohrlochtiefe von 180,0 m, 147,4 m vertikal.\n\n- N2-25-006: 1,8 g/t Au auf 21,9 m, beginnend in einer Bohrlochtiefe von 154,4 m, 133,7 m vertikal.\n\n- N2-25-009: 1,37 g/t Au auf 24,0 m, beginnend in einer Bohrlochtiefe von 168,9 m, 146,3 m vertikal.\n\n- N2-25-004, -006 und -009 bestätigen die strukturelle Beständigkeit sowie die Beständigkeit der Gehalte auf einer Streichlänge von 300 m, bauen auf N2-25-007, -008 und -010 auf, die 0,95 g/t Au auf 61,1 m enthielten, und befinden sich neigungsabwärts von 1,75 g/t Au auf 30,4 m in N2-25-005.\n\n- Angesichts dieser Ergebnisse geht das Unternehmen davon aus, dass die A-Zone ein solides mineralisiertes Erzgangsystem beherbergt, das zwischen 20 und 61 m schwankt, mindestens 100 m breit ist und sich über eine Streichlänge von 1,5 km erstreckt. Die A-Zone ist nach wie vor in mehrere Richtungen offen, insbesondere entlang des Streichens (Ost-West) und neigungsabwärts bzw. in die Tiefe (Süden) innerhalb eines 5 km langen strukturellen Korridors, der bereits bebohrt wurde und sich als mineralisiert erwiesen hat.\n\n- Bis dato wurden 48 Bohrlöcher auf insgesamt 15.291 m abgeschlossen, wobei die Analyseergebnisse für 35 Bohrlöcher noch ausstehend sind, was für das gesamte zweite Quartal eine kontinuierliche Reihe bevorstehender Katalysatoren verheißt.\n\n- Das Unternehmen verfügt über ein Working Capital von etwa 10,5 Millionen CAD und ist schuldenfrei.\n\nVancouver, British Columbia / 16. April 2026 / IRW-Press / Formation Metals Inc. (Formation oder das Unternehmen) (CSE: FOMO) (FWB: VF1) (OTCQB: FOMTF), ein nordamerikanisches Mineralakquisitions- und Explorationsunternehmen, freut sich, die Ergebnisse der Bohrungen N2-25-001, N2-25-002, N2-25-003, N2-25-004, N2-25-006 und N2-25-009 bekannt zu geben, die im Rahmen seines laufenden, vollständig finanzierten 30.000-Meter-Bohrprogramms in seinem Vorzeige-Goldkonzessionsgebiet N2 (N2 oder das Konzessionsgebiet) niedergebracht wurden.\n\nDas 25 km südlich von Matagami (Quebec) gelegene Konzessionsgebiet N2 beherbergt eine globale historische Ressource von ca. 871.000 Unzen, bestehend aus 18 Mio. Tonnen Gestein mit einem Gehalt von 1,4 g/t Au (ca. 810.000 Unzen Au) in vier Zonen (A, Ost, RJ-East und Central)2,3 und 243.000 Tonnen Gestein mit einem Gehalt von 7,82 g/t Au (ca. 61.000 Unzen Au) in der Zone RJ2,4.\n\nDas laufende Bohrprogramm des Unternehmens hat die Erwartungen übertroffen und die geologische Beständigkeit bestätigt, wobei in den Bohrlöchern N2-25-004, N2-25-006 und N2-25-009 solide und durchgehende Goldabschnitte erzielt wurden, die folgende bedeutsame Abschnitte identifizierten:\n\n- N2-25-004: 0,83 g/t Au auf 40,4 m, beginnend in einer Bohrlochtiefe von 180,0 m, 147,4 m vertikal Das bedeutsamste Intervall beinhaltet 1,36 g/t Au auf 9,0 m mit einem Gesamtmetallindex von 38,48.\n\n- N2-25-006: 1,8 g/t Au auf 21,9 m, beginnend in einer Bohrlochtiefe von 154,4 m, 133,7 m vertikal Das bedeutsamste Intervall beinhaltet 3,4 g/t Au auf 4,8 m mit einem Gesamtmetallindex von 79,56.\n\n- N2-25-009: 1,37 g/t Au auf 24,0 m, beginnend in einer Bohrlochtiefe von 168,9 m, 146,3 m vertikal Das bedeutsamste Intervall beinhaltet 2,05 g/t Au auf 13,3 m mit einem Gesamtmetallindex von 81,89.\n\nEine vergleichende Analyse zeigt eine starke Übereinstimmung zwischen dem Phase-1-Datensatz und den historischen Bohrungen auf über 55.000 m, was wesentliche Geologie- und Bergbauparameter bestätigt und das Vertrauen in die bestehende Datenbank stärkt.\n\nDeepak Varshney, CEO von Formation Metals, sagte: Die Ergebnisse von Phase 1 übertreffen weiterhin unsere Erwartungen, wobei N2-25-004, N2-25-006 und N2-25-009 zeigen, dass die A-Zone ein bedeutsames Tagebauziel darstellt. Die Ergebnisse bestätigen weiterhin die historischen Bohrungen auf über 55.000 m, wobei die Bohrungen nicht nur die historischen Erkenntnisse hinsichtlich Lithologie, Mineralisierung, Alteration, Erzgänge und struktureller Merkmale bestätigen, sondern auch eine höhere Konsistenz, längere goldhaltige Mischproben sowie wertvollere Mineralisierungsprofile liefern, was das Konzept einer Tagebaulagerstätte bei N2 untermauert.\n\nhttps://www.irw-press.at/prcom/images/messages/2026/83798/FormationMetals_160426_DEPRCOM.001.jpeg\n\nAbbildung 1 - Standorte der Bohrlöcher von 2025 (A-Zone), Phase 1.\n\nDie Bohrungen wurden so konzipiert, dass sie auf Mineralisierungen in verschiedenen Horizonten südlich und unterhalb von N2-25-005 und N2-25-012 abzielen (siehe Pressemitteilung vom 12. Februar 2026), wo das Unternehmen die folgenden mächtigen, kontinuierlichen, oberflächennahen Abschnitte identifiziert hat:\n\n- N2-25-005: 0,91 g/t Au über 42,3 Meter ab 14,0 Metern Bohrlochtiefe, 9,9 Meter vertikale Tiefe. Zu den herausragenden Abschnitten zählen 8,1 Meter mit 2,04 g/t Au bzw. 11,4 Meter mit 1,31 g/t Au mit einem Gesamtmetallindex von 38,36.\n\n- N2-25-012: 1,75 g/t Au über 30,4 Meter ab 64,1 Metern Bohrlochtiefe, 45,3 Meter vertikale Tiefe. Zu den herausragenden Abschnitten zählen 10,5 Meter mit 3,51 g/t Au bzw. 0,51 Meter mit 19,2 g/t Au mit einem Gesamtmetallindex von 62,43.\n\nDiese Bohrlöcher wurden auch konzipiert, um die westliche Erweiterung des Streichens des durch die Bohrlöcher N2-25-007, N2-25-008 und N2-25-010 (siehe Pressemitteilung vom 24. Februar 2026) ermittelten mineralisierten Horizonts zu testen, wo das Unternehmen die folgenden zusätzlichen mächtigen, soliden oberflächennahen Abschnitte identifiziert hat:\n\n- N2-25-007: 1,3 g/t Au über 22,2 Meter, beginnend bei 139,9 Metern Bohrlochtiefe, 121,2 Meter vertikal. Der hervorgehobene Abschnitt umfasst 2,36 g/t Au über 10,5 Meter mit einem Gesamtmetallindex von 51,07.\n\n- N2-25-008: 0,95 g/t Au über 61,1 Meter, beginnend bei 109 Metern Bohrlochtiefe, 94,4 Meter vertikal. Der hervorgehobene Abschnitt umfasst 1,68 g/t Au über 26,5 Meter mit einem Gesamtmetallindex von 67,97.\n\n- N2-25-010: 1,43 g/t Au über 19,4 Meter, beginnend bei 117,5 Metern Bohrlochtiefe, 101,8 Meter vertikal. Der hervorgehobene Abschnitt umfasst 2,23 g/t Au über 7,0 Meter mit einem Gesamtmetallindex von 38,49.\n\nDer Abstand von etwa 55 m zwischen den Bohrlöchern N2-25-004, N2-25-006 und N2-25-009 bestätigt die Beständigkeit eines bedeutsamen Bulk-Tonnage-Systems in der Tiefe. Diese Ergebnisse validieren historische Bohrdaten, stärken das Vertrauen in das geologische 3D-Modell und verringern das technische Risiko für die bevorstehenden Erschließungsphasen.\n\nDie geologische Interpretation, die auf der Beständigkeit des Streichens der Mineralisierung zwischen den beiden Bohrlochsätzen (N2-25-007, N2-25-008 und N2-25-010 sowie N2-25-004, N2-25-006 und N2-25-009) basiert, lässt einen konsistenten, 300 m langen goldhaltigen Korridor erkennen. Dieser Abschnitt weist stark auf beträchtliches Bulk-Tonnage-Potenzial in Oberflächennähe entlang einer Streichlänge von 8 km hin.\n\nDiese Bohrlochreihe bestätigte insbesondere nicht nur die Beständigkeit der primären Zielerzgänge, sondern durchschnitt auch parallel verlaufende, sekundäre und tertiäre Erzgangsysteme, wodurch das potenzielle mineralisierte Profil oberhalb und unterhalb der Hauptzone erheblich erweitert wurde, wo N2-25-004 0,4 g/t Au auf 4,6 m und 0,41 g/t Au auf 4,0 m oberhalb, N2-25-006 0,66 g/t Au auf 38,6 m oberhalb und 0,67 g/t Au auf 22,2 m unterhalb durchteufte und N2-25-009 0,61 g/t Au auf 42,1 m oberhalb und 0,96 g/t Au auf 21,7 m unterhalb durchteufte. Die identifizierte Beständigkeit dieser Bohrlochreihen über eine Strecke von 300 m mit Erweiterungspotenzial über die gesamte Streichlänge von 8 km würde erhebliche positive Auswirkungen auf einen zukünftigen Tagebau haben, wobei sich der potenzielle Abbaubereich deutlich auf eine gesamte mineralisierte Mächtigkeit von bis zu etwa 93 m in der Tiefe des Bohrlochs und eine Mächtigkeit von etwa 100 m erweitern würde.\n\nBis dato hat Formation ein Phase-1-Programm mit 46 Bohrlöchern auf insgesamt 14.466 m erfolgreich abgeschlossen. Da die Analyseergebnisse für 39 Bohrlöcher zurzeit noch ausstehend sind, erwarten wir einen kontinuierlichen Nachrichtenfluss, der als primärer Bewertungskatalysator wirken wird, wobei die Bohrungen voraussichtlich Ende Mai fortgesetzt werden.\n\nDeepak Varshney, CEO von Formation Metals, sagte außerdem: Da die historische Ressource eine Streichlänge von nur 1,5 km im nördlichen Korridor umfasst, haben wir über 6 km auf einem Projekt zu bohren, auf dem wir nun nachgewiesen haben, dass die Hauptzone mindestens 20 m mächtig und etwa 95 m breit ist. Über die Bestätigung der durchgehenden Beständigkeit unseres Hauptziels hinaus sind diese Bohrergebnisse insofern von großer Bedeutung, als sie übereinanderliegende oder parallel verlaufende, sekundäre und tertiäre Erzgangsysteme verdeutlichen, die den potenziellen mineralisierten Bereich erheblich erweitern und unseren Spielraum für ein umfassendes, mehrere Erzgänge umfassendes Abbaukonzept vergrößern.\n\nSollte sich diese Beständigkeit über die gesamte Streichlänge von 8 km erstrecken, steht uns eine erhebliche Erweiterung des potenziellen Tagebaugebiets bevor - möglicherweise auf eine Mächtigkeit von etwa 93 m und eine Breite von 100 m in der Tiefe des Bohrlochs. Die vergleichende Analyse unserer jüngsten Phase-1-Bohrungen mit historischen Daten hat unsere Erwartungen übertroffen und eine starke Übereinstimmung sowohl hinsichtlich der geologischen Struktur als auch des Mineralisierungsgehalts aufgezeigt. Diese hohe Wiederholbarkeit validiert unser geologisches Modell und belegt die erhebliche Beständigkeit der Lagerstätte.\n\nDas 15.000 Meter umfassende Bohrprogramm der Phase 1 von Formation ist konzipiert für:\n\n\n\nAdvertisement\n\n- Steigerung des Vertrauensniveaus und Konversion der Ressource: Schließen oberflächennaher Lücken, um das Vertrauensniveau der oberflächennahen Mineralisierung zu steigern.\n\n- Ressourcenwachstum: Überprüfung von Erweiterungen in Fallrichtung und Step-outs im Streichen sowohl nach Osten als auch nach Westen über die historischen Ressourcengrenzen hinaus.\n\n- Metallurgie: Entnahme repräsentativer Bohrkerne zur Bestätigung der metallurgischen Reaktion und Validierung der Gewinnungsraten.\n\nDa die vollständige Finanzierung gesichert ist, treibt Formation ein 30.000 m umfassendes Bohrprogramm voran, dessen Schwerpunkt auf der Abgrenzung einer oberflächennahen Tagebauressource liegt, um eine beträchtliche Tonnage aufzubauen und die Wirtschaftlichkeit des Projekts zu verbessern. Der Schwerpunkt der Explorationsarbeiten liegt zurzeit darauf, das Potenzial eines 8 km langen Korridors zu erschließen, wobei zwei Bohrgeräte in den Zonen A und RJ im Einsatz sind. Der Abschluss dieser Phase-1-Bohrungen wird zur Veröffentlichung einer ersten Mineralressourcenschätzung (MRE) im dritten Quartal führen.\n\nIn den kommenden Monaten plant das Unternehmen ein fokussiertes und vielversprechendes Explorationsprogramm bei N2, das die vielfältigen Möglichkeiten des Projekts widerspiegelt und nachhaltige, disziplinierte Explorationsaktivitäten über die aktuelle Bohrphase hinaus unterstützt.\n\nTabelle 1 - Bedeutende Abschnitte aus der A-Zone: N2-25-004, N2-25-006 und N2-25-009\n\nBohrloch-Nr. Au (g/t) Von Bis Länge (m) Metallindex\n\nN2-25-004 1,03 14,3 15,6 1,3 1,34\n\n0,41 77,0 79,5 2,5 1,03\n\n0,29 96,0 102,1 6,1 1,77\n\n0,4 129,0 133,6 4,6 1,84\n\n0,29 145,5 148,2 2,7 0,78\n\n0,83 180,0 220,4 40,4 33,53\n\neinschließlich 1,36 180,0 189,0 9\n\nund 1,08 195,3 202,2 6,9\n\nund 1,18 210,0 220,4 10,4\n\nN2-25-006 0,66 69,4 108,0 38,6 25,48\n\neinschließlich 8,85 87,0 88,1 1,1\n\nund 3,66 104,2 106,2 2\n\n1,8 154,4 175,5 21,1 37,98\n\neinschließlich 3,6 154,4 159,2 4,8\n\nund 1,34 161,0 166,7 5,7\n\nund 2,41 168,0 173,0 5\n\n1,6 197,6 199,3 1,7 2,72\n\n0,67 231,0 253,1 22,1 14,81\n\neinschließlich 1,01 231,0 234,1 3,1\n\nund 1,1 243,0 249,8 6,8\n\nN2-25-009 0,61 86,7 128,8 42,1 25,74\n\neinschließlich 1,04 113,3 126,7 13,4\n\n0,34 156,5 159,4 2,9 0,99\n\n1,37 168,9 192,9 24,0 32,88\n\neinschließlich 2,05 177,8 191,1 13,3\n\nund 3,02 177,8 181,1 3,3\n\nund 4,02 185,5 186,7 1,2\n\n2,23 198,7 199,8 1,1 2,45\n\n0,96 207,8 231,0 23,2 22,27\n\neinschließlich 2,98 207,8 211,8 4,0\n\nTabelle 2 - Bedeutende Abschnitte aus der RJ-Zone: N2-25-001, N2-25-002 und N2-25-003\n\nBohrloch-Nr. Au (g/t) Von Bis Länge (m) Metallindex\n\nN2-25-001 0,23 261,7 268,3 6,6 1,52\n\neinschließlich 1,28 266,5 267,1 0,6\n\n0,11 271,5 281,7 10,2 1,12\n\nN2-25-002 0,24 98,5 102 3,5 0,84\n\neinschließlich 1,58 99,3 99,8 0,5\n\n0,34 183,1 207,5 24,4 8,30\n\neinschließlich 0,89 183,1 187,9 4,8\n\nund 1,54 186,0 187,9 1,9\n\nund 0,3 196,6 208,5 11,9\n\n0,54 289,3 290,3 1,0 0,54\n\nN2-25-003 3,0 23,1 27,6 4,5 13,50\n\neinschließlich 14,06 23,1 24 0,9\n\n0,6 52,9 64,7 11,8 7,08\n\neinschließlich 1,28 59,6 63,7 4,1\n\n0,76 110 112 2,0 1,52\n\nAnmerkung 1: Die dargestellten Mineralisierungsabschnitte sind nicht direkt repräsentativ für die wahre Mächtigkeit. Basierend auf der Interpretation des Abschnittswinkels entspricht die geschätzte wahre Mächtigkeit der mineralisierten Linse im Allgemeinen 87 % der erbohrten Kernlänge.\n\nAnmerkung 2: Die gemeldeten Abschnitte wurden unter Verwendung eines Mindestgehalts von 0,2 g/t Au für höhergradige Abschnitte zusammengesetzt.\n\nTabelle 3 - Informationen zu den Bohrlöchern von Zone-A\n\nTabelle 4 - Informationen zu den Bohrlöchern von Zone-RJ\n\nÜberblick über das Projekt\n\nDas Vorzeige-Goldprojekt N2 von Formation umfasst 87 Claims mit einer Gesamtfläche von ca. 4.400 ha in der Subprovinz Abitibi im Nordwesten von Quebec und ist ein fortgeschrittenes Goldprojekt mit einer umfassenden historischen Ressource von ca. 871.000 Unzen - bestehend aus 18 Mio. Tonnen mit einem Gehalt von 1,4 g/t Au (ca. 810.000 Unzen Au)2,3 sowie 243.000 Tonnen mit einem Gehalt von 7,82 g/t Au (ca. 61.000 Unzen Au)2.\n\nInsgesamt gibt es sechs primäre goldhaltige mineralisierte Zonen, die jeweils in Streichrichtung und in der Tiefe erweiterbar sind. Die von Balmoral Resources Ltd. (jetzt Wallbridge Mining) von 2010 bis 2018 durchgeführten Zusammenstellungen und geophysikalischen Arbeiten lieferten zahlreiche Ziele, die derzeit erstmals von Formation mit Diamantbohrungen untersucht werden.\n\nZu den historischen Highlights der beiden vorrangigen Zonen gehören:\n\n- Zone A: eine oberflächennahe, sehr beständige, wenig variierende historische Goldlagerstätte mit ca. 522.900 Unzen, die bei einem Gehalt von 1,52 g/t Au identifiziert wurde. In der Vergangenheit wurden über 1,65 km Streichlänge etwa 15.000 Bohrmeter niedergebracht. 84 % der historischen Bohrungen durchteuften goldhaltige Abschnitte mit bis zu 1,7 g/t Au über 35 m.\n\n- Zone RJ: eine hochgradige historische Goldlagerstätte mit ca. 61.100 Unzen, die bei einem Gehalt von 7,82 g/t Au identifiziert wurde, mit hochgradigen Abschnitten aus historischen Bohrungen von bis zu 51 g/t Au über 0,8 m und 16,5 g/t Au über 3,5 m2. Diese Zone war das Ziel der letzten Bohrungen auf dem Konzessionsgebiet durch Agnico-Eagle Mines im Jahr 2008, als der Goldpreis bei ca. 800 US$/Unze lag. Bislang wurden nur ca. 900 m der Streichlänge bebohrt, sodass noch mehr als 4,75 Kilometer der Streichlänge zu erkunden sind.\n\nDie interne Einschätzung des Unternehmens lautet, dass das Projekt N2 das Potenzial für eine mögliche Tagebauressource hat. Dieser Optimismus basiert auf mehreren wesentlichen Faktoren:\n\n- Beträchtliche unerschlossene Streichlänge: Allein die Zone A weist eine Streichlänge von über 3,1 km auf (nur etwa 35 % davon wurden in der Vergangenheit bebohrt), während in der Zone RJ noch über 4,75 km unerprobt sind, was erheblichen Spielraum für eine seitliche Erweiterung der bekannten Mineralisierung bietet.\n\n- Offen in der Tiefe und entlang des Streichens: Alle Zonen sind weiterhin offen, da die bisherigen Bohrungen auf geringe Tiefen (etwa 350 m) beschränkt waren, sodass in einem bewährten Goldlager beträchtliches vertikales Potenzial besteht.\n\n- Mächtige, beständige oberflächennahe Abschnitte: Jüngste Bohrungen haben mächtige Zonen (100 bis über 200 m) der Zielmineralisierung bestätigt, die in Oberflächennähe beginnen und ideal für Tagebauszenarien mit großen Tonnagen, geringen Abraumverhältnissen und hohem Tonnagenpotenzial sind.\n\n- Regionale Analogie und Herkunft: N2 befindet sich im Abschnitt Casa Berardi, der mehrere Lagerstätten mit mehreren Millionen Unzen beherbergt (z. B. Casa Berardi: über 2 Mio. Unzen produziert sowie wahrscheinliche und nachgewiesene Reserven von 14,3 Mio. Tonnen mit 2,75 g/t Au; Douay: Ressourcen von über 3 Mio. Unzen (10 Mio. Tonnen mit 1,59 g/t Au in der Kategorie angedeutet und 76,7 Mio. Tonnen mit 1,02 g/t Au in der Kategorie vermutet), und weist ähnliche geologische und strukturelle Merkmale auf. Die nahe gelegene Mine Vezza produzierte aus höhergradigem Untertagebau, doch die oberflächennäheren, mächtigeren Zonen von N2 lassen auf eine überlegene Wirtschaftlichkeit des Tagebaus schließen.\n\n- Unerprobte Ziele: Bei der Zusammenstellung der Daten wurden zahlreiche geophysikalische Anomalien (IP, EM, VTEM) identifiziert, die noch nicht bebohrt wurden und über die bekannten Zonen hinaus Entdeckungspotenzial aufweisen.\n\n- Steigende Goldpreise und wirtschaftliche Machbarkeit: Bei den aktuellen Goldpreisen werden niedriggradigere Lagerstätten mit großen Tonnagen äußerst attraktiv, was das Potenzial des Projekts erhöht.\n\nDieser erstklassige Standort in einer strategisch günstigen Lage, 25 km südlich der Bergbaustadt Matagami (Quebec), bietet ganzjährigen Zugang über Provinzstraßen und Holzabfuhrstraßen sowie die Nähe zu qualifizierten Arbeitskräften, Energieinfrastruktur und etablierten Bergbaudienstleistungen in einer Jurisdiktion, die für ihre frühere Goldproduktion von über 200 Mio. Unzen bekannt ist. Das Projekt liegt entlang des Minenabschnitts Casa Berardi, der Goldlagerstätten mit mehreren Millionen Unzen beherbergt, und befindet sich etwa 1,5 km östlich der vormals produzierenden Goldmine Vezza, die zwischen 2013 und 2019 von Nottaway Resources betrieben wurde und über 100.000 Unzen Gold im Untertagebau förderte.\n\nDie robuste Infrastruktur der Region bietet Möglichkeiten für die Lohnvermahlung, mit potenziellem Zugang zu nahe gelegenen Verarbeitungsanlagen wie jenen bei Casa Berardi oder anderen Mühlen in Abitibi, was eine kostengünstige Erschließung ohne die Errichtung einer eigenen Mühle am Standort ermöglicht.\n\nhttps://www.irw-press.at/prcom/images/messages/2026/83798/FormationMetals_160426_DEPRCOM.002.jpeg\n\nAbbildung 3 - Historische Bohrlochstandorte. Formation geht davon aus, dass im Konzessionsgebiet N2 eine Streichlänge von über 15 km zu erkunden ist.\n\nhttps://www.irw-press.at/prcom/images/messages/2026/83798/FormationMetals_160426_DEPRCOM.003.jpeg\n\nAbbildung 4 - Das Konzessionsgebiet im Überblick mit einer Zusammenfassung der historischen Arbeiten, die in jeder der sechs mineralisierten Zonen durchgeführt wurden, und den jeweiligen historischen Ressourcen.\n\nDas Unternehmen ist außerdem der Ansicht, dass N2 ein erhebliches Potenzial für Basismetalle aufweist. In diesem Zusammenhang hat es kürzlich einen Neubewertungsprozess abgeschlossen, der bedeutende Kupfer- und Zinkabschnitte in historischen Bohrungen zeigte, von denen bekannt ist, dass sie bedeutende Goldgehalte (>1 g/t Au) aufweisen. Die Analyseergebnisse reichen von 200 bis 4.750 ppm Kupfer und von 203 ppm bis 6.700 ppm Zink, was auf ein starkes Potenzial für erhöhte Basismetallkonzentrationen (Cu-Zn) im gesamten Konzessionsgebiet hinweist, insbesondere in den Zonen A und RJ. Die geologische Beschaffenheit des gesamten Konzessionsgebiets N2 ist durch vulkanische und sedimentäre Gesteine gekennzeichnet, die sich in regionalen Antiklinal- und Synklinalstrukturen gebildet haben. Drei Hauptdeformationsstrukturen, die entlang der bekannten von Nordwest nach Südost bis Westnordwest nach Ostsüdost verlaufenden Strukturtrends ausgerichtet sind, die für VMS-Lagerstätten in der Region Matagami typisch sind, fungieren als kritische geologische Kontrollen für die Mineralisierung im Konzessionsgebiet.\n\nQualifizierter Sachverständiger\n\nDer technische Inhalt dieser Pressemitteilung wurde von Herrn Babak V. Azar, P.Geo., géo (OGQ#10876), einem unabhängigen Auftragnehmer und qualifizierten Sachverständigen im Sinne der Vorschrift National Instrument 43-101, geprüft und genehmigt. Die vom Optionsgeber vorgelegten historischen Berichte wurden vom qualifizierten Sachverständigen geprüft.\n\nQualitätssicherung und Qualitätskontrolle\n\nDie Qualitätssicherungs- und Qualitätskontrollprotokolle umfassten die Hinzugabe von Leer- und Standardproben (von Canadian Resource Laboratories akkreditiert) im Schnitt alle 10 Proben während des Analyseprozesses. Die Goldanalyse erfolgte mittels Brandprobe (FA) mit abschließendem Atomabsorptions- und ICP-Verfahren an 50 Gramm Material in den Einrichtungen von Laboratoire Expert Inc. in Rouyn-Noranda, Quebec, Kanada, und AGAT Laboratories Ltd. in Val d'Or, Quebec, Kanada. Jede Probe mit einem Gehalt von 10,0 g/t Gold oder mehr wurde nochmals anhand FA analysiert gefolgt von einer gravimetrischen Untersuchung. Die Proben, die eine große Variation ihres Goldgehalts aufwiesen oder sichtbares Gold enthielten, wurden einer Gesamtgoldanalyse (metallische Siebung) unterzogen.\n\nÜber Formation Metals Inc.\n\nFormation Metals Inc. ist ein nordamerikanisches Mineralakquisitions- und -explorationsunternehmen, das sich auf die Entwicklung hochwertiger, bohrbereiter Konzessionsgebiete mit hohem Wertschöpfungs- und Expansionspotenzial konzentriert. Das Vorzeigeprojekt von Formation ist das Goldprojekt N2, ein fortgeschrittenes Goldprojekt mit einer umfassenden historischen Ressource von ca. 871.000 Unzen (18 Mio. Tonnen mit 1,4 g/t Au (ca. 810.000 Unzen Au) in vier Zonen (A, East, RJ-East und Central)2, 3 und 243.000 Tonnen mit 7,82 g/t Au (ca. 61.000 Unzen Au) in der Zone RJ2, 4) und sechs mineralisierten Zonen, die jeweils entlang des Streichens und in der Tiefe für eine Erweiterung offen sind. Dazu gehören die Zone A, in der nur etwa 35 % des Streichens bebohrt wurden (>3,1 km offen), und die Zone RJ, in der historische hochgradige Abschnitte mit bis zu 51 g/t Au auf 0,8 Metern vorkommen.\n\nFORMATION METALS INC.\n\nDeepak Varshney, CEO und Direktor\n\nNähere Informationen erhalten Sie unter der Rufnummer 778-899-1780, per E-Mail an dvarshney@formationmetalsinc.com oder unter www.formationmetalsinc.com.\n\nDie Canadian Securities Exchange und ihr Regulierungsorgan übernehmen keine Verantwortung für die Angemessenheit oder Genauigkeit dieser Mitteilung.\n\nHinweise und Quellennachweis:\n\n1. Leser werden darauf hingewiesen, dass die Geologie benachbarter Konzessionsgebiete nicht unbedingt Rückschlüsse auf die Geologie des Konzessionsgebiets zulässt.\n\n2. Die oben genannten Ressourcenschätzungen sind nicht in Kategorien eingestuft, gelten als historisch und basieren auf früheren Daten, die von einem früheren Konzessionseigentümer erfasst wurden und nicht den aktuellen CIM-Kategorien entsprechen.\n\nDas Unternehmen hält die Schätzungen zwar für grundsätzlich zuverlässig, jedoch hat ein qualifizierter Sachverständiger keine ausreichenden Arbeiten durchgeführt, um die historischen Schätzungen gemäß den aktuellen CIM-Kategorien als aktuelle Mineralressourcen zu klassifizieren, und das Unternehmen behandelt die historischen Schätzungen daher nicht als aktuelle Mineralressourcen. Bei der Erstellung der historischen Schätzungen wurde ein Cutoff-Gehalt von 0,5 g/t Au bei einer Mindestabbaubreite von 2,5 m zugrunde gelegt.\n\nBevor die historischen Schätzungen als aktuelle Ressourcen klassifiziert werden können, müssen möglicherweise umfangreiche Datenzusammenstellungen, erneute Bohrungen, erneute Probenahmen und Datenüberprüfungen durch einen qualifizierten Sachverständigen durchgeführt werden. Es kann nicht garantiert werden, dass die historischen Mineralressourcen, weder ganz noch teilweise, jemals wirtschaftlich nutzbar sein werden. Darüber hinaus sind Mineralressourcen keine Mineralreserven und ihre wirtschaftliche Nutzbarkeit ist nicht nachgewiesen. Dem Unternehmen sind keine neueren Schätzungen für das Konzessionsgebiet N2 bekannt.\n\n3. Needham, B. (1994), 1993 Diamond Drill Report, Northway Joint Venture, Northway Property; Cypress Canada Inc.; 492 Seiten.\n\n4. Guy K. (1991), Exploration Summary May 1, 1990 to May 1, 1991 Vezza Joint Venture Northway Property; Total Energold; 227 Seiten.\n\nZukunftsgerichtete Aussagen:\n\nDiese Pressemitteilung enthält zukunftsgerichtete Aussagen gemäß den geltenden kanadischen Wertpapiergesetzen, einschließlich, aber nicht beschränkt auf Aussagen zu: den Plänen des Unternehmens für das Konzessionsgebiet und dem voraussichtlichen Zeitplan und Umfang des Bohrprogramms auf dem Konzessionsgebiet; und dem geplanten 30.000-Meter-Bohrprogramm des Unternehmens. Solche zukunftsgerichteten Informationen spiegeln die aktuellen Einschätzungen des Managements wider und basieren auf einer Reihe von Schätzungen und/oder Annahmen sowie Informationen, die dem Unternehmen derzeit zur Verfügung stehen und die zwar als angemessen erachtet werden, jedoch bekannten und unbekannten Risiken, Ungewissheiten und anderen Faktoren unterliegen, die dazu führen können, dass die tatsächlichen Ergebnisse und zukünftigen Ereignisse wesentlich von den in solchen zukunftsgerichteten Aussagen ausgedrückten oder implizierten Ergebnissen abweichen. Leser werden darauf hingewiesen, dass solche zukunftsgerichteten Aussagen weder Versprechen noch Garantien darstellen und bekannten und unbekannten Risiken und Unsicherheiten unterworfen sind, einschließlich, aber nicht beschränkt auf allgemeine geschäftliche, wirtschaftliche, wettbewerbsbezogene, politische und soziale Unsicherheiten, ungewisse und volatile Aktien- und Kapitalmärkte, Mangel an verfügbarem Kapital, tatsächliche Ergebnisse von Explorationsaktivitäten, Umweltrisiken, zukünftige Preise für Basis- und andere Metalle, Betriebsrisiken, Unfälle, Arbeitsprobleme, Verzögerungen bei der Erlangung behördlicher Genehmigungen und Zulassungen sowie andere Risiken in der Bergbauindustrie.\n\nDas Unternehmen befindet sich derzeit in der Explorationsphase. Die Exploration ist von Natur aus hochspekulativ, mit vielen Risiken verbunden, erfordert erhebliche Ausgaben und führt möglicherweise nicht zur Entdeckung von Minerallagerstätten, die rentabel abgebaut werden können. Darüber hinaus verfügt das Unternehmen derzeit über keine Reserven auf seinen Konzessionsgebieten. Daher kann nicht garantiert werden, dass sich solche zukunftsgerichteten Aussagen als zutreffend erweisen, und die tatsächlichen Ergebnisse und zukünftigen Ereignisse können erheblich von den in solchen Aussagen erwarteten abweichen.\n\nHinweis/Disclaimer zur Übersetzung (inkl. KI-Unterstützung): Die Originalmeldung in der Ausgangssprache (in der Regel Englisch) ist die einzige maßgebliche, autorisierte und rechtsverbindliche Fassung. Diese deutschsprachige Übersetzung/Zusammenfassung dient ausschließlich der leichteren Verständlichkeit und kann gekürzt oder redaktionell verdichtet sein. Die Übersetzung kann ganz oder teilweise mithilfe maschineller Übersetzung bzw. generativer KI (Large Language Models) erfolgt sein und wurde redaktionell geprüft; trotzdem können Fehler, Auslassungen oder Sinnverschiebungen auftreten. Es wird keine Gewähr für Richtigkeit, Vollständigkeit, Aktualität oder Angemessenheit übernommen; Haftungsansprüche sind ausgeschlossen (auch bei Fahrlässigkeit), maßgeblich ist stets die Originalfassung. Diese Mitteilung stellt weder eine Kauf- noch eine Verkaufsempfehlung dar und ersetzt keine rechtliche, steuerliche oder finanzielle Beratung. Bitte beachten Sie die englische Originalmeldung bzw. die offiziellen Unterlagen auf www.sedarplus.ca, www.sec.gov, www.asx.com.au oder auf der Website des Emittenten; bei Abweichungen gilt ausschließlich das Original.\n\nDie englische Originalmeldung finden Sie unter folgendem Link:\n\nhttps://www.irw-press.at/press_html.aspx?messageID=83798\n\nDie übersetzte Meldung finden Sie unter folgendem Link:\n\nhttps://www.irw-press.at/press_html.aspx?messageID=83798&tr=1\n\nNEWSLETTER REGISTRIERUNG:

\n\nAktuelle Pressemeldungen dieses Unternehmens direkt in Ihr Postfach:\n\nhttp://www.irw-press.com/alert_subscription.php?lang=de&isin=CA34638F1053\n\nMitteilung übermittelt durch IRW-Press.com. Für den Inhalt ist der Aussender verantwortlich.\n\nKostenloser Abdruck mit Quellenangabe erlaubt.\n\nFüllen Sie das untere Feld aus und senden Sie ein Nachricht an Ihre Freunde, Familie oder Kollegen! E-Mails Ihre E-Mail:\n\nDie E-Mail des Freundes:\n\nDie fett-markierten Felder sind obligatorisch. Die u nterstrichenen Buchstaben sind Zugangsschlüssel.\n\n\n\n"} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-16/Full_text/full_text_macro_central_banks.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-16/Full_text/full_text_macro_central_banks.jsonl new file mode 100644 index 0000000..f6656e4 --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-16/Full_text/full_text_macro_central_banks.jsonl @@ -0,0 +1,9 @@ +{"url": "https://edition.cnn.com/2026/04/16/economy/powell-fed-trump-interest-rates", "title": "Trump own actions against Powell and the Fed are working against him", "publish_date": "2026-04-16T12:28:19Z", "full_text": "Washington —\n\nPresident Donald Trump just can’t get what he wants from the Federal Reserve.\n\nTrump has long pounded the table for rate cuts and has wanted Fed Chair Jerome Powell out for years. But Trump’s own actions over the past year have made those two outcomes far less likely.\n\nTrump…\n\nintroduced a slew of massive tariffs, pushing up inflation.\n\nwent to war with Iran, spiking energy prices worldwide.\n\npublicly backed a criminal probe into Powell that a federal judge has described as “pretextual.”\n\nthreatened to fire Powell next month if he doesn’t step aside when his stint as Fed chair ends.\n\nis trying to fire Fed Governor Lisa Cook over unsubstantiated allegations.\n\nA livestream shows Powell speaking on the floor of the New York Stock Exchange on March 18, 2026. Angela Weiss/AFP/Getty Images\n\nNow, there’s a growing chance that the US central bank may not just delay a rate cut but may hike rates instead, particularly if the price spikes stemming from the US-Israeli war with Iran prove to be long lasting.\n\nTrump’s efforts throughout his second term have only prompted central bankers to take pause and put any rate cuts on the back burner as they wait for things to play out — an approach that even Treasury Secretary Scott Bessent recently said he agrees with.\n\nThe president’s attacks and threats on Fed policymakers themselves are also backfiring.\n\nHolding off on rate cuts\n\nFor Fed officials to lower interest rates, they must be confident that inflation is slowing and is on track to their 2% goal. That had been the case right before Trump’s second term began last January.\n\nThen Trump rolled out a confusing patchwork of tariffs last year that jacked up inflation on various goods (and he still isn’t done with his tariff spree, promising to raise duties across the board to get back to the effective tariff rate from before the Supreme Court’s ruling that struck down certain tariffs). That prompted Fed officials to adopt a wait-and-see posture, holding off on any rate moves until they delivered three consecutive cuts at the end of last year.\n\nPeople shop at a local supermarket in New York City on April 9, 2026. Charly Triballeau/AFP/Getty Images\n\nA customer puts fuel in his vehicle at a gas station on April 6, 2026, in Miami, Florida. Joe Raedle/Getty Images\n\nFed officials are now more worried about the war that began with joint US-Israeli attacks on Iran in late February. The conflict has led to a weekslong closure of the Strait of Hormuz, a key global trade passage. About 20% of the world’s oil supply, along with other key commodities, passes through the critical waterway.\n\nThe war with Iran drove up monthly US inflation threefold in March, according to the latest Consumer Price Index report.\n\nAt the Fed’s March meeting, Powell had said the war’s effects would likely be temporary. Now, less than a month later, the world’s cargo ships still aren’t flowing freely through the strait and Fed officials aren’t considering interest rate cuts anytime soon.\n\n“My baseline is that we’re going to remain on hold for a good while,” Cleveland Fed President Beth Hammack, one of the four regional Fed presidents with voting power this year, said Wednesday in an interview with CNBC.\n\nTrump’s attempts to push out Fed officials are failing\n\nSo far, Trump’s efforts to push out Fed officials haven’t been successful, and ironically, they may keep Powell in place for longer.\n\nPowell has resisted engaging with Trump over the president’s repeated threats to fire him, limiting his response to reminders that such a move would be illegal.\n\nFiring Powell could have two serious consequences for Trump: doing so would not sit well with financial markets and the decision may get held up for a long time in the courts. Powell last month said the law dictates that the current Fed head remains in the role as chair “pro tempore” if the Senate hasn’t confirmed a successor by the end of his term.\n\nPowell in Washington, DC, on January 13, 2026. The Fed chair has resisted engaging with Trump's repeated threats to fire him, limiting his response to reminders that such a move would be illegal. Chip Somodevilla/Getty Images\n\n“President Trump’s threats of firing Chair Powell are hardly surprising but are simply not consistent with what the law provides,” Skanda Amarnath, executive director at Employ America and a former economist at the Federal Reserve Bank of New York, said in a statement on Wednesday.\n\nLast year, Trump and his allies seized on the Fed’s renovation to its headquarters in Washington, DC, to put pressure on Powell, claiming the cost overruns were evidence of mismanagement. The Fed explained that some of the higher costs were due to unforeseen issues, such as asbestos and a high water table.\n\nBut that didn’t stop DC US Attorney Jeanine Pirro from serving Powell a pair of subpoenas to investigate testimony he gave to Congress last over on the renovation. Powell revealed the investigation in an extraordinary video rebuke, calling it out as a “pretext” to pressure the Fed.\n\nThe Federal Reserve renovation site on January 14, 2026, in Washington, DC. Trump and his allies had seized on the renovation last year, claiming the cost overruns were evidence of mismanagement. Alex Wong/Getty Images\n\nThe courts have been siding with Powell. A federal judge last month quashed a pair of subpoenas served to Powell by Pirro’s office, later reaffirming that ruling after Pirro requested the judge reconsider. In a statement to CNN, Pirro signaled she has no intention of abandoning the investigation. Her office also confirmed to CNN that her deputies were denied access to the Fed’s headquarters earlier this week, after showing up unannounced in order to view the renovation project.\n\nPirro has said she plans to appeal to the DC Circuit of Appeals, but her insistence with continuing the probe is precisely what is stalling Trump’s nomination of Warsh: Sen. Thom Tillis of North Carolina, a senior Republican on the Senate Banking Committee, reiterated this week that he won’t vote to confirm Warsh unless the probe into Powell is dropped.\n\nIt also appears likely that the president will lose his Supreme Court case against Fed Governor Lisa Cook, whom he tried to fire in August over allegations that she committed mortgage fraud. The Justice Department has been investigating the allegations but still hasn’t announced any charges against Cook.\n\n“The President already appears to be losing in court in his attempt to fire Governor Lisa Cook and he will likely lose again if he tries to fire Chair Powell,” Amarnath said.\n\nIn the end, Trump’s war on the Fed may end up costing him the very result he is demanding."} +{"url": "https://www.finanznachrichten.de/nachrichten-2026-04/68216751-eur-jpy-gibt-leicht-nach-da-die-hoehere-inflation-in-der-eurozone-den-fokus-auf-ezb-signale-verlagert-545.htm", "title": "EUR / JPY gibt leicht nach , da die höhere Inflation in der Eurozone den Fokus auf EZB - Signale verlagert", "publish_date": "2026-04-16T12:28:19Z", "full_text": "Die Eskalation im Iran-Konflikt hat die Energiepreise mit voller Wucht nach oben getrieben. Was zunächst nach einer kurzfristigen Reaktion aussah, entwickelt sich zunehmend zu einem strukturellen Problem: Die Straße von Hormus ist blockiert, wichtige LNG- und Ölanlagen stehen still oder werden gezielt angegriffen. Eine schnelle Entspannung ist nicht in Sicht – im Gegenteil, die Lage spitzt sich weiter zu.\n\n\n\nFür die Weltwirtschaft bedeutet dies wachsende Risiken. Steigende Energiepreise erhöhen den Inflationsdruck, gefährden Zinssenkungen und bringen die ohnehin hoch bewerteten Aktienmärkte ins Wanken. Doch wo Risiken entstehen, ergeben sich auch Chancen.\n\n\n\nDenn von einem dauerhaft höheren Energiepreisniveau profitieren nicht nur Öl- und Gasunternehmen. Auch Versorger, erneuerbare Energien sowie ausgewählte Rohstoff- und Agrarwerte rücken in den Fokus. In diesem Umfeld könnten gezielt ausgewählte Unternehmen überdurchschnittlich profitieren – unabhängig davon, ob die Krise anhält oder nicht.\n\n\n\nIn unserem aktuellen Spezialreport stellen wir drei Aktien vor, die genau dieses Profil erfüllen: Krisenprofiteure mit solidem Geschäftsmodell, attraktiver Bewertung und langfristigem Potenzial.\n\n\n\nJetzt den kostenlosen Report sichern – und Ihr Depot auf den Energiepreisschock vorbereiten!"} +{"url": "https://dantri.com.vn/kinh-doanh/chu-tich-chung-khoan-rong-viet-noi-ve-moi-quan-he-voi-kido-foods-20260416175340107.htm", "title": "Chủ tịch Chứng khoán Rồng Việt nói về mối quan hệ với KIDO Foods", "publish_date": "2026-04-16T12:28:19Z", "full_text": "Chiều ngày 16/4, Công ty cổ phần Chứng khoán Rồng Việt (VDSC, mã chứng khoán: VDS) đã tổ chức kỳ họp cổ đông 2026, thông qua kế hoạch kinh doanh cũng như chia sẻ với cổ đông về các vấn đề liên quan cổ đông lớn KIDO Foods, việc vay vốn trong bối cảnh lãi suất tăng cao…\n\nCổ đông mới KIDO Foods đang nắm giữ 26 triệu cổ phiếu, tương đương tỷ lệ sở hữu 9,56% vốn tại Chứng khoán Rồng Việt. Trong thời gian chứng khoán biến động từ đầu năm, công ty này đã liên tục mua vào cổ phiếu VDS để tăng sở hữu.\n\nÔng Nguyễn Miên Tuấn - Chủ tịch HĐQT Công ty cổ phần Chứng khoán Rồng Việt (Ảnh: BTC).\n\nChia sẻ về nhóm cổ đông này, Chủ tịch Hội đồng quản trị (HĐQT) Chứng khoán Rồng Việt Nguyễn Miên Tuấn khẳng định KIDO Foods là cổ đông lâu năm, đồng thời có định hướng gắn bó lâu dài với công ty. Bên cạnh việc nắm giữ cổ phần, nhóm này cũng hỗ trợ công ty về nguồn lực tài chính, góp phần củng cố nền tảng vốn và hoạt động kinh doanh.\n\nKIDO Foods trước kia là công ty thực phẩm thuộc Tập đoàn KIDO nhưng phía tập đoàn đã chuyển nhượng 51% vốn cho Nutifood từ năm 2024. Cuối năm 2025, KIDO thông báo sẽ chuyển nhượng tiếp 49% vốn còn lại tại công ty này cho Nutifood.\n\nCái khó của Chứng khoán Rồng Việt\n\nLiên quan đến tình hình lãi suất, lãnh đạo công ty cho biết mặt bằng lãi suất đang được điều chỉnh giảm sau thời gian tăng trưởng nóng là tín hiệu đáng mừng.\n\nKhác với những công ty chứng khoán khác, Rồng Việt không có ngân hàng hậu thuẫn phía sau.\n\n“Đây là một trong những cái khó khăn của chúng tôi. Do đó, công ty luôn chú trọng kiểm soát tài chính và sử dụng vốn hiệu quả. Trong năm nay, công ty tiếp tục đặt mục tiêu nâng dư nợ cho vay ký quỹ để đóng góp vào doanh thu. Để làm được điều này, công ty kỳ vọng gia tăng hoạt động cho vay theo các thương vụ (deal)”, ông Tuấn nói.\n\nVị này kể, 5 năm qua công ty đã tăng cường năng lực tài chính và cải thiện hiệu quả hoạt động, với chỉ số ROE được nâng lên. Nhờ đó, số lượng cổ đông cũng gia tăng, đạt khoảng 12.000 cổ đông vào cuối năm 2025. Công ty kỳ vọng sẽ tiếp tục thu hút thêm đối tác trong thời gian tới để củng cố nguồn lực tài chính. Lãnh đạo công ty còn kỳ vọng việc nâng hạng giúp Việt Nam thu hút thêm nhà đầu tư nước ngoài, qua đó tạo động lực cho thị trường.\n\nQuý I lỗ 30 tỷ đồng, chủ yếu do tự doanh\n\nCổ đông chất vấn lãnh đạo tại đại hội (Ảnh: BTC).\n\nVề kinh doanh, năm 2026 doanh nghiệp đề ra mục tiêu doanh thu khoảng 1.318 tỷ đồng và lợi nhuận sau thuế khoảng 408 tỷ đồng, tương ứng tăng trưởng lần lượt khoảng 20% và 45% so với năm trước.\n\nBên cạnh đó, công ty trình cổ đông phương án tăng vốn điều lệ từ 2.720 tỷ đồng lên 4.500 tỷ đồng thông qua phát hành tối đa 178 triệu cổ phiếu, dự kiến huy động khoảng 1.444 tỷ đồng. Nguồn vốn này chủ yếu được sử dụng cho hoạt động cho vay ký quỹ, bên cạnh đầu tư tự doanh và các mảng kinh doanh khác.\n\nTrong quý I, công ty ước tính doanh thu đạt khoảng 200 tỷ đồng. Tuy nhiên, lợi nhuận thu về âm khoảng 30 tỷ đồng.\n\nNguyên nhân chính khiến công ty thua lỗ đến từ việc phải tăng trích lập dự phòng cho danh mục tự doanh trong bối cảnh thị trường chứng khoán diễn biến kém tích cực giai đoạn đầu năm. Cùng với đó, các yếu tố bên ngoài như biến động địa chính trị, xung đột Trung Đông cùng tâm lý thận trọng của nhà đầu tư đã ảnh hưởng đáng kể đến hiệu quả đầu tư.\n\nBan lãnh đạo cho biết thêm, thị trường năm nay dự kiến đối mặt với nhiều áp lực, trong đó có mặt bằng lãi suất gia tăng. Dù vậy, Rồng Việt đánh giá vẫn còn dư địa tăng trưởng nhờ các yếu tố như mục tiêu tăng trưởng GDP, dòng vốn ngoại và triển vọng lợi nhuận của doanh nghiệp."} +{"url": "https://www.thehindubusinessline.com/markets/gold/gold-silver-prices-rise-on-weak-dollar-geopolitical-cues-analysts-see-near-term-volatility/article70868399.ece", "title": "Why gold , silver are rising on weak dollar & geopolitical tensions ? ", "publish_date": "2026-04-16T12:28:19Z", "full_text": "Gold and silver prices moved higher in Thursday’s trade, ahead of Akshaya Tritiya, supported by a weaker US dollar, geopolitical uncertainty and shifting expectations around global interest rates. The uptick comes even as global equity markets remained firm, reflecting a mix of risk-on sentiment and safe-haven demand.\n\nGold gained as the dollar softened and crude oil prices slipped below $100 per barrel amid optimism around potential peace talks between the US and Iran. The easing in oil prices tempered inflation concerns, influencing interest rate outlook and supporting bullion. Silver and other metals also tracked the upward momentum during the session.\n\nGaurav Garg, research analyst at Lemonn Markets Desk, echoed that gold and silver prices witnessed a notable rise driven by currency weakness and geopolitical tensions linked to the Iran conflict, which has raised concerns over potential supply disruptions. Internationally, gold traded at $4,857.90 per ounce, up 1.21 per cent, while domestic prices stood near ₹1,45,697 per 10 grams. Silver climbed 1.70 per cent to $80.84 per ounce globally, with domestic prices around ₹2,42,454 per kg. Crude oil remained relatively stable, with WTI trading at $91.65 per barrel.\n\nPonmudi R, CEO of Enrich Money, noted that MCX gold is trading in the ₹1,54,500–₹1,55,000 range with emerging buying interest at lower levels. He added that a sustained move above ₹1,55,000 could push prices towards ₹1,57,000–₹1,58,000, while a break below ₹1,54,000 may trigger a correction toward ₹1,52,000–₹1,48,000. The overall bias remains cautiously positive, supported by macro factors, though stronger momentum needs confirmation.\n\nOn silver, he said prices are hovering above ₹2,54,000, supported by safe-haven demand and strength in industrial metals despite elevated volatility. Resistance is seen in the ₹2,60,000–₹2,63,000 zone, with potential upside toward ₹2,68,000–₹2,70,000. On the downside, a break below ₹2,50,000 could lead to a correction toward ₹2,44,000–₹2,40,000.\n\nAnalysts expect gold and silver to remain volatile in the near term (ahead of Akshaya Tritiya), as markets continue to track geopolitical developments, currency movements and trends in crude oil prices.\n\nPublished on April 16, 2026"} +{"url": "https://www.marketpulse.com/markets/chart-alert-audusd-360-pips-rally-at-risk-of-a-minor-mean-reversion-decline-below-07200-before-new-upleg/", "title": "Chart alert : AUD / USD 360 pips rally at risk of a minor mean reversion decline below 0 . 7200 before new upleg", "publish_date": "2026-04-16T12:28:19Z", "full_text": "The Australian dollar has benefited significantly since last Wednesday, 8 April, when the US and Iran agreed to a ceasefire due to its higher beta factor, as the AUD has mirrored the movement of risk assets such as equities since the start of the US-Iran war on 28 February 2026, exhibiting similar risk-off movements, ignoring the hawkish monetary policy guidance advocated by the RBA.\n\nThe AUD/USD has jumped by 230 pips (+3.3%) from the 8 April 2026 low to print an intraday high of 0.7198 on Thursday, 16 April 2026 at this time of writing, just a whisker above its prior 11 March 2026 high of 0.7188.\n\nWhen measured from its current minor uptrend low of 0.6833 printed on 30 March 2026, it has rallied by almost 360 pips (+5.3%), making the Australian dollar the second-best-performing major currency against the US dollar based on a one-month rolling performance; USD/AUD (-2.47%), just behind the euro where the USD/EUR slid -3.04% (see Fig. 1)."} +{"url": "http://www.irishsun.com/news/278987031/cbuae-highlights-uae-proactive-approach-to-financial-resilience-in-washington", "title": "CBUAE highlights UAE proactive approach to financial resilience in Washington", "publish_date": "2026-04-16T12:28:19Z", "full_text": "WASHINGTON, 16th April, 2026 (WAM) -- The Central Bank of the UAE (CBUAE) continued its participation in the 2026 Spring Meetings of the International Monetary Fund (IMF) and the World Bank Group, as well as the meetings of the G20, G24 and BRICS, held in Washington, DC, from 13th April till 18th April 2026.\n\nThe meetings were attended by central bank governors, finance ministers and representatives of international financial institutions.\n\nKhaled Mohamed Balama, Governor of the CBUAE, led the Bank's delegation in a number of ministerial meetings and high-level dialogue sessions. The delegation included Ebrahim Obaid Al Zaabi, Assistant Governor for Monetary Policy and Financial Stability; Ahmed Saeed Al Qamzi, Assistant Governor for Banking and Insurance Supervision; and Mohamed Al Marzooqi, Head of International Relations, in addition to a number of senior officials.\n\nBalama delivered the UAE's keynote address at the high-level meeting of the Middle East, North Africa and Pakistan (MENAP) region with the IMF, attended by Kristalina Georgieva, Managing Director of the IMF.\n\nThe address focused on developments in the global economy, geopolitical challenges and their implications for both the regional and global economy. He highlighted the UAE's proactive and leading role in safeguarding the resilience of vital sectors.\n\nHe also reaffirmed the UAE's continued efforts to develop proactive frameworks aimed at enhancing the efficiency of the financial sector, including the Proactive Financial Institution Resilience Package launched by the CBUAE in March, in a first-of-its-kind step by a central bank in the region, which contributed to reinforcing the sector's resilience and sustainability.\n\nHe also led the delegation in the meetings of the Intergovernmental Group of Twenty-Four on International Monetary Affairs and Development (G-24).\n\nOn the sidelines of the meetings, the Governor and the accompanying delegation held a series of bilateral meetings with a number of central bank governors and senior officials from international financial institutions. These included separate meetings with Madis Mller, Governor of Eesti Pank, and Natia Turnava, Governor of the National Bank of Georgia, during which they discussed ways to strengthen monetary and financial cooperation, exchanged views on priorities for the next phase, and explored opportunities to further develop financial infrastructure for both sides.\n\nThis regular participation reflects the CBUAE's role in contributing to international dialogue on the future of the global economy and financial stability, underscoring the UAE's position as an active partner in supporting efforts aimed at promoting economic and financial stability at both regional and international levels."} +{"url": "https://www.dailykos.com/stories/2026/4/16/800020794/community/this/", "title": "Say What You Mean", "publish_date": "2026-04-16T12:28:19Z", "full_text": "In a recent interview with NBC News, Senator Thom Tillis vowed to continue his hold on the nomination of Kevin Warsh to replace Jerome Powell as head of the Federal Reserve. This is a principled political act well within the power of any US Senator based on the Trump Department of Justice’s clearly bogus investigation of Powell on clearly ridiculous corruption charges.\n\nTillis, a retiring Republican Senator from North Carolina who has a moderate reputation, has said he will hold the nomination for as long as necessary. He wants the Trump DOJ to drop the investigation into Powell or provide some actual evidence that Powell is corrupt. Tillis has said that he does not believe Powell was particularly good at being Fed Chairman and that Warsh is a great choice.\n\nBut that is where the principled part of this ends.\n\nDuring the interview with NBC, Tillis said he has “lost” his filter regarding criticizing President Trump because he is not running for reelection. This has become pretty common on the right, with multiple examples of former supporters of Trump suddenly becoming more critical once there is no political price to pay. But in Tillis’s case. This is more nuanced and more hypocritical.\n\nTillis has pointedly not criticized Trump directly, preferring to either directly attack Trump staffers, such as Deputy Chief of Staff for Policy Stephen Miller, and others, for giving Trump bad advice. This was the same sort of soft criticism people used during the Reagan Administration, although with them, it was because people genuinely loved Ronald Reagan. That is not the case here; it is because people genuinely fear Donald Trump.\n\nIn the case of Powell and the DOJ investigation into the FED’s $2.5 Billion renovation of an asbestos-laden 1937 era facility, Powell “takes the president at his word,” that he did not ask for an investigation into Powell. And this is where the lack of courage comes in. Trump either instructed the DOJ to go after Powell, or he made it clear by his public attacks that he would look favorably on anyone who did go after Powell.\n\nIn the movie Casino, the character Andy Stone, a mob associate, says to another mobster, “The old may said, ‘maybe your friend should give in.’ And when the old man says ‘maybe’ that’s like a papal bull.” Trump knows this, and Tillis has been around politics long enough to know this as well, he just chooses to ignore it.\n\nWhat Tillis is saying is that Trump is being manipulated by his staff about all sorts of things. We know that may be true in some ways, but not in the way Senator Tillis means it. If Tillis were being truly courageous, he would say it straight out: Trump is not being manipulated by his staff; he is manipulating those around him to do his bidding while appearing to be ignorant of the actual details.\n\nTillis holding up Warsh’s nomination is a good thing. Tillis not stating the real reason, that Trump is the problem, is not."} +{"url": "https://www.vedomosti.ru/economics/news/2026/04/16/1190832-inflyatsionnie-ozhidaniya", "title": "Инфляционные ожидания россиян в апреле сократились до 12 , 9 % ", "publish_date": "2026-04-16T12:28:19Z", "full_text": "Ожидаемая инфляция среди граждан, у которых есть сбережения, в апреле составила 11,4% по сравнению с 12,3% в марте. Ожидаемая инфляция среди тех, у кого нет сбережений, уменьшилась за месяц с 14,4% до 14,3%."} +{"url": "https://www.brasil247.com:443/economia/governo-projeta-crescimento-de-2-56-do-pib-e-inflacao-de-3-04-em-2027-u72b8zti", "title": "Governo projeta crescimento de 2 , 56 % do PIB e inflao de 3 , 04 % em 2027", "publish_date": "2026-04-16T12:28:19Z", "full_text": "247 – O governo federal projeta que a economia brasileira crescerá 2,56% em 2027, segundo o Projeto de Lei de Diretrizes Orçamentárias (PLDO) do próximo ano, divulgado pelos ministérios da Fazenda e do Planejamento e Orçamento e noticiado pelo jornal Valor Econômico. O texto será encaminhado ao Congresso Nacional e apresenta as estimativas oficiais para os principais indicadores macroeconômicos do país até 2030.\n\nDe acordo com os números apresentados, a inflação medida pelo Índice de Preços ao Consumidor Amplo (IPCA) deve ficar em 3,04% em 2027. Para os anos seguintes, a projeção do governo aponta estabilidade em 3% ao ano entre 2028 e 2030, sinalizando uma expectativa de controle inflacionário dentro de uma trajetória considerada administrável pela equipe econômica.\n\nAs projeções para o Produto Interno Bruto também indicam continuidade do crescimento nos anos posteriores. Para 2028, a estimativa é novamente de expansão de 2,56%. Em 2029, o avanço previsto é de 2,59%, enquanto em 2030 o crescimento deve alcançar 2,66%. A leitura do governo é de que a economia brasileira seguirá em trajetória positiva, ainda que em ritmo moderado.\n\nNo campo dos índices de preços, o governo também projetou variações para outros indicadores relevantes. O Índice Nacional de Preços ao Consumidor (INPC) deve registrar alta de 3,06% em 2027. Para 2028, 2029 e 2030, a estimativa é de 3% em cada ano. Já o Índice Geral de Preços - Disponibilidade Interna (IGP-DI), calculado pela Fundação Getulio Vargas (FGV), tem previsão de 4% em 2027 e de 3,8% entre 2028 e 2030.\n\nOutro dado destacado no PLDO é a previsão para a massa salarial. Segundo o texto, a alta esperada é de 11,19% em 2027. Para 2028, a estimativa recua levemente para 11,08%. Em 2029, o avanço projetado é de 11,06%, enquanto em 2030 a previsão volta a subir marginalmente, para 11,12%. O indicador é observado como um termômetro importante do comportamento da renda e do dinamismo do mercado de trabalho.\n\nNo cenário traçado pelo governo, a taxa básica de juros também deve seguir uma trajetória de redução gradual nos próximos anos. A Selic média projetada para 2027 é de 10,55%. Em 2028, o percentual cairia para 9,27%, recuando depois para 8,27% em 2029 e 7,27% em 2030. A estimativa reforça a perspectiva de um ambiente monetário menos restritivo ao longo do período.\n\nEm relação ao câmbio, o governo trabalha com uma taxa média de R$ 5,47 por dólar em 2027. Para 2028, a projeção é de R$ 5,45. Em 2029, o valor médio subiria para R$ 5,50, chegando a R$ 5,53 em 2030. A oscilação prevista é pequena, mas mostra a expectativa de manutenção de um dólar em patamar ainda elevado nos próximos anos.\n\nO PLDO também traz estimativas para o mercado internacional de petróleo. Segundo os cálculos do governo, o preço médio do barril deve ficar em US$ 67,69 em 2027. Para 2028, a previsão é de US$ 66,60. Em 2029, o valor subiria para US$ 66,92, alcançando US$ 67,44 em 2030. O comportamento dessa variável é relevante por seus impactos sobre inflação, custos de produção e contas externas.\n\nAo consolidar essas projeções, o governo apresenta ao Congresso um cenário de crescimento contínuo, inflação relativamente estável, redução progressiva dos juros e manutenção de variáveis estratégicas em níveis considerados compatíveis com a condução da política econômica. O PLDO funciona como uma peça central do planejamento fiscal e orçamentário, servindo de base para a formulação do Orçamento e para a definição de metas do setor público.\n\nAs estimativas, no entanto, também serão acompanhadas de perto por agentes econômicos, parlamentares e pelo mercado, já que o comportamento efetivo da economia dependerá de fatores internos e externos, como o ritmo da atividade global, a dinâmica cambial, os preços das commodities e as decisões de política monetária ao longo dos próximos anos."} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-16/Full_text/full_text_macro_geopolitics_risk.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-16/Full_text/full_text_macro_geopolitics_risk.jsonl new file mode 100644 index 0000000..de70a35 --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-16/Full_text/full_text_macro_geopolitics_risk.jsonl @@ -0,0 +1,5 @@ +{"url": "https://www.design-reuse.com/news/202530378-three-misconceptions-about-the-402b-semiconductor-foundry-industry/", "title": "Three Misconceptions About the $402B Semiconductor Foundry Industry", "publish_date": "2026-04-16T12:30:54Z", "full_text": "By Pierre Cambou, Yole Développement\n\nEE Times\n\nThe global semiconductor foundry industry has reached an estimated $402 billion in 2026, reflecting both the scale and the structural complexity of modern semiconductor manufacturing, according to Yole Group’s latest report, “Status of the Semiconductor Foundry Industry 2026.” Foundries now sit at the crossroads of geopolitics and the AI capex boom, but do we really understand what they are about?\n\nAdvanced nodes or leading edge: Why it matters\n\nIt is widely cited that TSMC holds about 72% share of the global semiconductor foundry market and more than 90% of advanced chips. Such statements and figures only partially reflect TSMC’s true position. Its dominance at the leading edge is often understated due to inconsistent definitions of “advanced.”\n\nClick here to read more ..."} +{"url": "https://www.redlandsdailyfacts.com/2026/04/16/us-iran-war-israel/", "title": "Pakistani army chief visits Tehran in hopes of renewed US - Iran talks", "publish_date": "2026-04-16T12:30:54Z", "full_text": "By SAMY MAGDY, MELANIE LIDMAN and KAREEM CHEYAHEB\n\nCAIRO (AP) — Pakistan’s army chief is set to meet with Iranian officials in Tehran on Thursday in a bid to extend the ceasefire which paused almost seven weeks of war between Israel, the U.S. and Iran that have killed thousands of people and upended global markets by disrupting the flow of oil. Uncertainty remains whether the frantic diplomacy can lead to a deal as the ceasefire passes the half-way mark in the original two-week agreement.\n\nThe meeting comes as President Donald Trump announced the leaders of Israel and Lebanon will speak later on Thursday about halting the fighting between them. If it takes place, the conversation would be the first time the leaders of the two countries have spoken directly in more than 30 years. Both Israeli and Lebanese governments refused to confirm a conversation. Meanwhile, the Lebanese militant group Hezbollah and Israel’s military continued cross-border attacks on Thursday.\n\nThe White House said any further talks would likely take place in the Pakistani capital of Islamabad, though no decision had been made on whether to resume negotiations. The fragile ceasefire, which halted the fighting in the Middle East a week ago, is holding despite a U.S. naval blockade of Iranian ports and Iranian counter-threats to target regional ports across the Red Sea.\n\nPakistan has emerged as a key mediator after it hosted direct talks between the U.S. and Iran in Islamabad that authorities said helped narrow differences between the two sides. Mediators are seeking a new round before the ceasefire expires next week.\n\nThe war has jolted markets and rattled the global economy as shipping has been cut off and airstrikes have torn through military and civilian infrastructure across the region. Oil prices have fallen amid hopes for an end to fighting, and U.S. stocks on Wednesday surpassed records set in January.\n\nUncertainty over Israel, Lebanon talks as strikes continue\n\nTrump said that Israel and Lebanon are expected to speak later on Thursday about a possible ceasefire, but did not elaborate which leaders would speak.\n\nOfficials from Netanyahu’s office and the Lebanese government refused to confirm the possible conversation.\n\nAn Israeli minister said Netanyahu will speak with Lebanese President Joseph Aoun on Thursday. “Today the prime minister will speak for the first time with the president of Lebanon, after so many years of a complete disconnection in the dialogue between the two countries,” Gila Gamliel, Israel’s Minister of Science and Technology, told Army Radio Thursday morning.\n\nGamliel, who was at a cabinet meeting late Wednesday night about negotiations with Lebanon, is part of Israel’s security cabinet. She said the talks “will hopefully ultimately lead to prosperity and flourishing” between the two countries. Lebanon and Israel held their first direct diplomatic talks in decades on Tuesday in Washington following more than a month of war between Israel and Iran-backed Hezbollah.\n\nBut the two countries continued exchanging fire across the border on Thursday, with Hezbollah targeting towns in northern Israel with rockets and drones. Israeli fire against southern Lebanon intensified, especially around the cities of Tyre, Nabatieh, and the strategic town of Bint Jbeil near the border with Israel.\n\nIsrael and Lebanon have technically been at war since Israel was established in 1948, and Lebanon remains deeply divided over diplomatic engagement with Israel.\n\nOfficials say US and Iran are making progress\n\nEven as the U.S. blockade on Iranian ports and renewed Iranian threats strained the ceasefire agreement, regional officials reported progress, telling The Associated Press the United States and Iran had an “in-principle agreement” to extend it to allow for more diplomacy. They spoke on condition of anonymity to discuss sensitive negotiations.\n\nBut while mediators worked for peace, tensions simmered.\n\nThe commander of Iran’s joint military command, Ali Abdollahi, threatened to halt trade in the region if the U.S. does not lift its naval blockade, and a newly appointed military adviser to Iranian Supreme Leader Mojtaba Khamenei said he doesn’t support extending the ceasefire.\n\nIn this photo released by the Iranian Foreign Ministry, Iranian Foreign Minister Abbas Araghchi, right, meets with Pakistan’s Army Chief Field Marshal Gen. Asim Munir in Tehran, Wednesday, April 15, 2026. (Iranian Foreign Ministry via AP)\n\nParamedics attach a portrait over the grave of Ghadir Baalbaki, 19, who was killed on Tuesday in an Israeli airstrike, at a temporary mass grave in the southern port city of Tyre, Lebanon, Wednesday, April 15, 2026. (AP Photo/Hussein Malla)\n\nRelatives of Ghadir Baalbaki, 19, who was killed on Tuesday in an Israeli airstrike, mourn during her funeral in the southern port city of Tyre, Lebanon, Wednesday, April 15, 2026. (AP Photo/Hussein Malla)\n\nIn this photo released by the Iranian Foreign Ministry, Pakistan’s Army Chief Field Marshal Gen. Asim Munir, left, is welcomed by Iranian Foreign Minister Abbas Araghchi upon his arrival in Tehran, Wednesday, April 15, 2026. (Iranian Foreign Ministry via AP) Show Caption 1 of 4 In this photo released by the Iranian Foreign Ministry, Iranian Foreign Minister Abbas Araghchi, right, meets with Pakistan’s Army Chief Field Marshal Gen. Asim Munir in Tehran, Wednesday, April 15, 2026. (Iranian Foreign Ministry via AP) Expand\n\nMediators seek compromise on sticking points\n\nMediators are pushing for a compromise on three main sticking points that derailed direct talks last weekend — Iran’s nuclear program, the Strait of Hormuz and compensation for wartime damages, according to a regional official involved in the mediation efforts.\n\nIranian Foreign Ministry spokesman Esmail Baghaei said Iran is open to discussing the type and level of its uranium enrichment, but his country “based on its needs, must be able to continue enrichment,” Iranian state media reported.\n\nThe fighting has killed at least 3,000 people in Iran, more than 2,100 in Lebanon, 23 in Israel and more than a dozen in Gulf Arab states. Thirteen U.S. service members have also been killed.\n\nU.S. Treasury Secretary Scott Bessent said the Trump administration would ramp up economic pain on Iran with new economic sanctions on countries doing business with it, calling the move the “financial equivalent” of a bombing campaign.\n\nPakistan’s Prime Minister Shehbaz Sharif arrived in Qatar on Thursday as part of a regional visit aimed at discussions on the ongoing U.S.-Iran peace process and efforts to promote stability in the Middle East amid continuing tensions, his office said.\n\nChina calls for Strait of Hormuz to reopen\n\nChinese Foreign Minister Wang Yi said the window of peace was opening during a phone call with his Iranian counterpart, who briefed him on the latest developments in Iran-U.S. negotiations and Tehran’s considerations on the next step, according to a statement from China’s foreign ministry late Wednesday.\n\nWang told Araghchi that the situation has reached a critical juncture between war and peace, and said Iran’s sovereignty, security, and legitimate rights should be respected as a littoral state of the Strait of Hormuz, while freedom of navigation and safety through the strait should be ensured.\n\nSince the war began, Iran has curtailed maritime traffic through the Strait of Hormuz, which a fifth of global oil transited through in peacetime. Tehran’s effective closure of the strait sent oil prices skyrocketing, raising the cost of fuel, food and other basic goods far beyond the Middle East, and the U.S. has responded with a blockade on Iranian shipping.\n\nU.S. Central Command said Wednesday that no ships had made it past the blockade since it was imposed two days earlier, while 10 merchant vessels complied with direction from U.S. forces to turn around and reenter Iranian waters.\n\nThe blockade is intended to pressure Iran, which has exported millions of barrels of oil, mostly to Asia, since the war began Feb. 28. Much of it has likely been carried by so-called dark transits that evade sanctions and oversight, providing cash that’s been vital to keeping Iran running.\n\nLidman reported from Tel Aviv, Israel and Cheyaheb reported from Beirut. Associated Press reporter Munir Ahmed reported from Islamabad."} +{"url": "https://www.laprovincia.es/economia/2026/04/16/inflacion-eurozona-repunta-2-6-marzo-encarecimiento-energia-guerra-iran-129169885.html", "title": "La inflación de la eurozona repunta al 2 , 6 % en marzo por el encarecimiento de la energía tras la guerra en Irán", "publish_date": "2026-04-16T12:30:54Z", "full_text": "La tasa de inflación interanual de la zona euro se situó en marzo en el 2,6%, siete décimas por encima del 1,9% registrado en febrero y una más de lo anticipado inicialmente, según la segunda lectura publicada por Eurostat. Se trata del mayor repunte del coste de la vida en la región desde julio de 2024, impulsado por el encarecimiento de la energía tras el estallido del conflicto en Oriente Próximo.\n\nEl aumento de siete décimas en marzo, primer mes de la guerra tras los ataques de Estados Unidos e Israel sobre Irán, iguala el salto observado en octubre de 2022, cuando la invasión rusa de Ucrania disparó el precio de los hidrocarburos.\n\nEn el conjunto de la Unión Europea, la inflación interanual alcanzó el 2,8% en marzo, frente al 2,1% de febrero, lo que representa la mayor subida de precios entre los Veintisiete desde enero de 2025.\n\nSegún Eurostat, la aceleración de la inflación en la eurozona refleja de forma inmediata el impacto de la guerra en Oriente Próximo y del bloqueo del estrecho de Ormuz sobre los combustibles. En marzo, el precio de la energía subió un 5,1% interanual, frente a la caída del 3,1% registrada en febrero. Por el contrario, los alimentos frescos moderaron su avance hasta el 4,2%, cuatro décimas menos que el mes anterior.\n\nPor su parte, los bienes industriales no energéticos elevaron su precio un 0,5% interanual, dos décimas menos que en febrero, mientras que los servicios se encarecieron un 3,2%, frente al 3,4% del mes precedente.\n\nSi se excluye el impacto de la energía, la inflación de la zona euro se situó en marzo en el 2,3%, una décima menos que en febrero. La inflación subyacente, que deja fuera también los alimentos, el alcohol y el tabaco, se moderó igualmente una décima, hasta el 2,3%.\n\nEn España, la tasa de inflación armonizada repuntó en marzo hasta el 3,4% interanual, lo que deja un diferencial desfavorable de ocho décimas respecto a la media de la eurozona.\n\nNoticias relacionadas\n\nEntre los países de la UE, las menores tasas de inflación se registraron en Dinamarca, con un 1%, y en República Checa, Chipre y Suecia, todos ellos con un 1,5%. En el lado contrario, los mayores incrementos de precios correspondieron a Rumanía, con un 9%, Croacia, con un 4,6%, y Lituania, con un 4,4%."} +{"url": "https://www.stcatharinesstandard.ca/news/world/united-states/killing-of-iranian-activist-in-canada-exposes-increasingly-bitter-divisions-within-the-diaspora/article_823736e8-ea08-5c6e-a647-04a9d4ebea58.html", "title": "Killing of Iranian activist in Canada exposes increasingly bitter divisions within the diaspora", "publish_date": "2026-04-16T12:30:54Z", "full_text": "Country\n\nUnited States of America US Virgin Islands United States Minor Outlying Islands Canada Mexico, United Mexican States Bahamas, Commonwealth of the Cuba, Republic of Dominican Republic Haiti, Republic of Jamaica Afghanistan Albania, People's Socialist Republic of Algeria, People's Democratic Republic of American Samoa Andorra, Principality of Angola, Republic of Anguilla Antarctica (the territory South of 60 deg S) Antigua and Barbuda Argentina, Argentine Republic Armenia Aruba Australia, Commonwealth of Austria, Republic of Azerbaijan, Republic of Bahrain, Kingdom of Bangladesh, People's Republic of Barbados Belarus Belgium, Kingdom of Belize Benin, People's Republic of Bermuda Bhutan, Kingdom of Bolivia, Republic of Bosnia and Herzegovina Botswana, Republic of Bouvet Island (Bouvetoya) Brazil, Federative Republic of British Indian Ocean Territory (Chagos Archipelago) British Virgin Islands Brunei Darussalam Bulgaria, People's Republic of Burkina Faso Burundi, Republic of Cambodia, Kingdom of Cameroon, United Republic of Cape Verde, Republic of Cayman Islands Central African Republic Chad, Republic of Chile, Republic of China, People's Republic of Christmas Island Cocos (Keeling) Islands Colombia, Republic of Comoros, Union of the Congo, Democratic Republic of Congo, People's Republic of Cook Islands Costa Rica, Republic of Cote D'Ivoire, Ivory Coast, Republic of the Cyprus, Republic of Czech Republic Denmark, Kingdom of Djibouti, Republic of Dominica, Commonwealth of Ecuador, Republic of Egypt, Arab Republic of El Salvador, Republic of Equatorial Guinea, Republic of Eritrea Estonia Ethiopia Faeroe Islands Falkland Islands (Malvinas) Fiji, Republic of the Fiji Islands Finland, Republic of France, French Republic French Guiana French Polynesia French Southern Territories Gabon, Gabonese Republic Gambia, Republic of the Georgia Germany Ghana, Republic of Gibraltar Greece, Hellenic Republic Greenland Grenada Guadaloupe Guam Guatemala, Republic of Guinea, Revolutionary People's Rep'c of Guinea-Bissau, Republic of Guyana, Republic of Heard and McDonald Islands Holy See (Vatican City State) Honduras, Republic of Hong Kong, Special Administrative Region of China Hrvatska (Croatia) Hungary, Hungarian People's Republic Iceland, Republic of India, Republic of Indonesia, Republic of Iran, Islamic Republic of Iraq, Republic of Ireland Israel, State of Italy, Italian Republic Japan Jordan, Hashemite Kingdom of Kazakhstan, Republic of Kenya, Republic of Kiribati, Republic of Korea, Democratic People's Republic of Korea, Republic of Kuwait, State of Kyrgyz Republic Lao People's Democratic Republic Latvia Lebanon, Lebanese Republic Lesotho, Kingdom of Liberia, Republic of Libyan Arab Jamahiriya Liechtenstein, Principality of Lithuania Luxembourg, Grand Duchy of Macao, Special Administrative Region of China Macedonia, the former Yugoslav Republic of Madagascar, Republic of Malawi, Republic of Malaysia Maldives, Republic of Mali, Republic of Malta, Republic of Marshall Islands Martinique Mauritania, Islamic Republic of Mauritius Mayotte Micronesia, Federated States of Moldova, Republic of Monaco, Principality of Mongolia, Mongolian People's Republic Montserrat Morocco, Kingdom of Mozambique, People's Republic of Myanmar Namibia Nauru, Republic of Nepal, Kingdom of Netherlands Antilles Netherlands, Kingdom of the New Caledonia New Zealand Nicaragua, Republic of Niger, Republic of the Nigeria, Federal Republic of Niue, Republic of Norfolk Island Northern Mariana Islands Norway, Kingdom of Oman, Sultanate of Pakistan, Islamic Republic of Palau Palestinian Territory, Occupied Panama, Republic of Papua New Guinea Paraguay, Republic of Peru, Republic of Philippines, Republic of the Pitcairn Island Poland, Polish People's Republic Portugal, Portuguese Republic Puerto Rico Qatar, State of Reunion Romania, Socialist Republic of Russian Federation Rwanda, Rwandese Republic Samoa, Independent State of San Marino, Republic of Sao Tome and Principe, Democratic Republic of Saudi Arabia, Kingdom of Senegal, Republic of Serbia and Montenegro Seychelles, Republic of Sierra Leone, Republic of Singapore, Republic of Slovakia (Slovak Republic) Slovenia Solomon Islands Somalia, Somali Republic South Africa, Republic of South Georgia and the South Sandwich Islands Spain, Spanish State Sri Lanka, Democratic Socialist Republic of St. Helena St. Kitts and Nevis St. Lucia St. Pierre and Miquelon St. Vincent and the Grenadines Sudan, Democratic Republic of the Suriname, Republic of Svalbard & Jan Mayen Islands Swaziland, Kingdom of Sweden, Kingdom of Switzerland, Swiss Confederation Syrian Arab Republic Taiwan, Province of China Tajikistan Tanzania, United Republic of Thailand, Kingdom of Timor-Leste, Democratic Republic of Togo, Togolese Republic Tokelau (Tokelau Islands) Tonga, Kingdom of Trinidad and Tobago, Republic of Tunisia, Republic of Turkey, Republic of Turkmenistan Turks and Caicos Islands Tuvalu Uganda, Republic of Ukraine United Arab Emirates United Kingdom of Great Britain & N. Ireland Uruguay, Eastern Republic of Uzbekistan Vanuatu Venezuela, Bolivarian Republic of Viet Nam, Socialist Republic of Wallis and Futuna Islands Western Sahara Yemen Zambia, Republic of Zimbabwe"} +{"url": "https://multiplayer.it/notizie/tsmc-alza-previsioni-2026-ricavi-aumenteranno-ia.html", "title": "TSMC alza le previsioni : nel 2026 i ricavi aumenteranno ancora grazie allIA", "publish_date": "2026-04-16T12:30:54Z", "full_text": "L'azienda prevede ora un incremento dei ricavi superiore al 30% su base annua , superando la precedente stima che si fermava poco sotto questa soglia. Parallelamente, è stato confermato un aumento della spesa in conto capitale, che dovrebbe collocarsi nella fascia alta della guidance compresa tra 52 e 56 miliardi di dollari (circa 48-52 miliardi di euro).\n\nI dati TSMC\n\nNel primo trimestre del 2026, TSMC ha registrato un utile netto record pari a 572 miliardi e mezzo di dollari taiwanesi, equivalenti a circa 16 miliardi e 900 milioni di euro, con una crescita del 58% rispetto allo stesso periodo dell'anno precedente. Si tratta dell'ottavo trimestre consecutivo con incremento a doppia cifra, sostenuto in larga parte dalla domanda di chip avanzati destinati a sistemi di IA.\n\nIl CEO di TSMC, C.C. Wei\n\nIl CEO C.C. Wei ha sottolineato come la richiesta legata all'intelligenza artificiale rimanga estremamente elevata, nonostante le incertezze macroeconomiche legate alle tensioni geopolitiche in Medio Oriente. L'azienda ha comunque adottato un approccio prudente nella pianificazione, considerando i possibili impatti sulla catena di approvvigionamento.\n\nUno dei principali ambiti di espansione riguarda la produzione a 3 nanometri, tecnologia chiave per i chip di nuova generazione. TSMC sta ampliando la capacità produttiva in Taiwan, Stati Uniti e Giappone, con l'obiettivo di aumentare i volumi tra il 2027 e il 2028. In particolare, negli Stati Uniti è previsto un investimento complessivo di 165 miliardi di dollari, pari a circa 153 miliardi di euro, destinato allo sviluppo di impianti produttivi in Arizona.\n\nNel trimestre, i chip a 3 nanometri hanno rappresentato circa il 25% dei ricavi complessivi, in forte crescita rispetto al 6% registrato nel terzo trimestre del 2023. Le previsioni per il trimestre in corso indicano vendite comprese tra 36 e 37 miliardi di euro, in netto aumento rispetto ai 28 miliardi dello stesso periodo del 2025.\n\nL'onda dell'IA spinge i giganti dei semiconduttori nel primo trimestre del 2026: mentre TSMC registra profitti record, Samsung guida la crescita con un impressionante +81% (Fonte immagine: Reuters)\n\nLa crescente domanda di chip ad alte prestazioni ha contribuito anche alla crescita del valore di mercato dell'azienda, che ha raggiunto circa 1.580 miliardi di euro, consolidando il vantaggio rispetto ai principali concorrenti asiatici. Le azioni quotate a Taipei hanno registrato un incremento significativo dall'inizio dell'anno.\n\nNonostante il contesto internazionale complesso, TSMC ha dichiarato di disporre di scorte di sicurezza per materiali critici come elio e idrogeno, oltre a una rete diversificata di fornitori. Questo dovrebbe limitare eventuali interruzioni produttive nel breve periodo."} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-16/Full_text/full_text_macro_yields_dollar.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-16/Full_text/full_text_macro_yields_dollar.jsonl new file mode 100644 index 0000000..66d1e57 --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-16/Full_text/full_text_macro_yields_dollar.jsonl @@ -0,0 +1,8 @@ +{"url": "https://www.thehindubusinessline.com/markets/stock-markets-close-lower-on-profit-taking-in-financial-shares/article70868922.ece", "title": "Sensex , Nifty pare gains to end marginally lower , Adani Enterprises , Hindalco lead gainers", "publish_date": "2026-04-16T12:30:02Z", "full_text": "Benchmark indices ended marginally lower on Thursday after a volatile session, as profit-booking at higher levels and lingering uncertainty around US–Iran talks weighed on sentiment.\n\nVinod Nair, Head of Research at Geojit Investments, said the market ended with marginal losses on weekly expiry amid volatility and profit-booking. He noted that investors remain cautious ahead of further clarity on US–Iran negotiations, while a higher-than-expected WPI inflation print weighed on auto and consumption stocks.\n\nThe BSE Sensex declined 122.56 points or 0.16 per cent to close at 77,988.68 after hitting an intraday high of 78,730.32, while the NSE Nifty 50 slipped 34.55 points or 0.14 per cent to settle at 24,196.75. after touching 24,400.95.\n\nAlso read\n\nVolatility index remained stable around 18.\n\nMarkets opened on a positive note, supported by easing geopolitical concerns, firm global cues and optimism around potential progress in US–Iran negotiations. However, indices failed to hold gains and slipped into negative territory amid profit-booking following the recent rally and rising oil prices, which reflected scepticism over the likelihood of a lasting peace deal. Ponmudi R, CEO of Enrich Money, emphasised that volatility is likely to persist, with the market direction closely tied to developments in West Asia.\n\nThe broader market continued to outperform the benchmarks, with the Nifty midcap 100 and Nifty smallcap 100 indices gaining 0.63 per cent and 0.89 per cent, respectively.\n\nGiven the current technical structure, midcaps and smallcaps are likely to continue their outperformance over the short term, Sudeep Shah, Head - Technical and Derivatives Research at SBI Securities, said.\n\nSectorally, metals emerged as the top performers, supported by firm global commodity prices and a softer dollar.\n\nIT stocks also showed resilience, aided by improving visibility on AI-led demand. Investors also eyed Wipro Q4 results. In contrast, banking, auto and consumption stocks came under pressure, while heavyweight stocks capped overall market gains. Bank Nifty has underperformed the frontline indices for the second consecutive trading session.\n\nAdani Enterprises & Hindalco lead Nifty 50 pack\n\nAmong Nifty 50 constituents, Adani Enterprises, Hindalco, Trent, Eternal and Adani Ports emerged as top gainers, while HDFC Bank, ONGC, Titan, M&M and Bharti Airtel were major laggards.\n\nMarket experts added that market breadth remained strong as 331 stocks in the Nifty 500 universe ended higher, indicating sustained participation beyond large caps.\n\nAlso read\n\nOf all the 4,494 stocks that were traded on the BSE, 2,808 advanced, 1,549 declined and 147 remained unchanged. About 163 stocks scaled to a 52-week high, while 22 fell to a 52-week low. In addition, 4 scrips hit the upper circuit and 9 hit the lower circuit.\n\nMetal stocks witnessed strong buying interest\n\nGMDC, Hindustan Copper, NALCO, Hindalco Industries and Vedanta witnessed strong buying interest, aiding the sectoral rally, according to Hariprasad K, SEBI-registered research analyst and founder of Livelong Wealth. However, selling in heavyweights such as HDFC Bank, Reliance Industries and ONGC limited upside.\n\nMidcap & smallcap movers\n\nIn the midcap segment, BHEL, PB Fintech, Radico Khaitan, Container Corporation of India and Swiggy advanced up to 6 per cent, whereas Supreme Industries, Astral, GMR Airports, Hero MotoCorp and Groww declined 2–4 per cent.\n\nAmong smallcap stocks, GMDC, Firstsource Solutions, Aptus Value Housing Finance, Swan Energy and Crompton Greaves Consumer Electricals surged 5–20 per cent, while Poonawalla Fincorp, Piramal Finance, JSW Cement, Meesho and Angel One slipped 1–2 per cent.\n\nAlso read\n\nAsian markets ended significantly higher.\n\nBrent crude oil prices remained elevated at around $96 per barrel. Precious metals such as gold and silver also posted significant gains. On the currency front, the rupee appreciated 0.2 per cent to 93.2 against the US dollar, supported by optimism around easing geopolitical tensions and softer crude oil prices.\n\nIn the previous trading session, Sensex settled 1,263.67 points or 1.64 per cent higher at 78,111.24, and Nifty 50 climbed 388.65 points or 1.63 per cent to 24,231.30. US markets edged higher on Wednesday.\n\nFIIs bought equities worth ₹666.15 crore, as per the exchange data.\n\nPublished on April 16, 2026"} +{"url": "https://www.marketpulse.com/markets/cable-eyes-13696-after-reclaiming-key-moving-averages-bulls-defend-13500/", "title": "Cable eyes 1 . 3696 after reclaiming key moving averages , bulls defend 1 . 3500", "publish_date": "2026-04-16T12:30:02Z", "full_text": "The daily timeframe provides the most compelling evidence of a medium-term trend shift. After months of being capped by a persistent descending trendline (dark navy), GBP/USD staged a clean breakout in early April.\n\nCrucially, the pair has successfully reclaimed its 100-day MA (blue) at 1.3444 and its 200-day MA (black) at 1.3413. This \"double reclaim\" of the major moving averages suggests that the macro bias has shifted from \"sell the rallies\" to \"buy the dips.\" Currently, the pair is eyeing the next major structural hurdle at 1.3696, which represents a significant historical resistance zone.\n\nThe Daily RSI is at 62.7, indicating healthy bullish momentum with plenty of runway before hitting the overbought 70.0 threshold.\n\nGBP/USD Daily Chart, April 16, 2026"} +{"url": "https://www.fool.com/investing/2026/04/16/3-absurdly-cheap-stocks-to-buy-with-1000-while-the/?source=iedfolrf0000001", "title": "3 Absurdly Cheap Stocks to Buy With $1 , 000 While the Market Is This Nervous", "publish_date": "2026-04-16T12:30:02Z", "full_text": "Many investors feel nervous about the current investing environment, and the hesitation is understandable. Oil prices have spiked, and supply chains have broken down amid conflict in the Middle East. Also, the Shiller P/E ratio has risen to 40, a level near historical highs.\n\nFortunately, if the market is good at delivering one thing, it is opportunity, and that applies even under difficult conditions. That might motivate investors to seek stocks that can succeed in any environment, and these three names likely fit the bill.\n\n1. Domino's Pizza\n\nDomino's Pizza (DPZ 0.30%) has emerged as an unexpected winner among consumer discretionary stocks. Investors may recall that it was one of the few stocks to rise during the COVID-19 pandemic, as the pizza chain's order and delivery model was well-suited for ordering out.\n\nMuch of that growth pulled back as lockdowns ended. However, Domino's has differentiated itself in more ways than just delivery. It utilizes \"fortressing,\" opening up a large number of stores in nearby areas. Although most companies would call that practice cannibalizing, Domino's has built a competitive advantage by shortening delivery times.\n\nAdditionally, it capitalizes on technology, and not just through its app and websites. Instead, customers can order on platforms varying from car dashboards to Apple Watches, taking advantage of impulse shoppers.\n\nAdmittedly, this is more of a safety play, as revenue increased by 5% in 2025, a time when net income grew by only 3% amid rising expenses.\n\nNonetheless, its $7.96 per share annual dividend increased by 15% last year, a testament to its success. Also, the yield of 2.2% is well above the 1.1% average for the S&P 500 (^GSPC +0.80%).\n\nExpand NASDAQ : DPZ Domino's Pizza Today's Change ( -0.30 %) $ -1.10 Current Price $ 368.07 Key Data Points Market Cap $12B Day's Range $ 365.45 - $ 370.00 52wk Range $ 346.31 - $ 499.08 Volume 198 Avg Vol 966K Gross Margin 39.95 % Dividend Yield 1.96 %\n\nFinally, Domino's P/E ratio of 21 is at multiyear lows, and considering that $369 buys one share, investors can buy a starter position cheaply.\n\n2. Clorox\n\nClorox (CLX 1.46%) is a consumer staples conglomerate consisting of its flagship bleach product along with Hidden Valley salad dressing, Kingsford charcoal, Burt's Bees personal care products, and other brands.\n\nLike Domino's, it benefited from the pandemic as the population became obsessed with cleanliness. That impulse faded as pandemic-related fear receded, causing the stock price to fall.\n\nUnfortunately, issues such as a major cyberattack in 2023 and a change in customer relationship management (CRM) systems led to a significant sales decline. That long-term drop means that Clorox stock now sells at a discount of more than 55% from its all-time high in 2021.\n\nExpand NYSE : CLX Clorox Today's Change ( -1.46 %) $ -1.52 Current Price $ 102.92 Key Data Points Market Cap $12B Day's Range $ 102.39 - $ 104.59 52wk Range $ 96.66 - $ 143.96 Volume 556 Avg Vol 2.2M Gross Margin 44.04 % Dividend Yield 4.80 %\n\nIndeed, the fact that net sales declined by 10% yearly in the first half of fiscal 2026 (ended Dec. 31, 2025) shows that the struggles continue. Still, analysts expect that sales decline to come in at 6% for the fiscal year before net sales rebound by 13% in fiscal 2027.\n\nMoreover, even though profits fell 19% annually to $237 million in the first half of fiscal 2026, the situation is likely not that bleak.\n\nAll this makes Clorox a relatively safe, undervalued dividend stock. The payout, which has risen annually for decades, is now $4.96 per share, a yield of 4.7%. When also considering the 17 P/E ratio, investors could have a lucrative growth and income stock by buying three shares for $312.\n\n3. Target\n\nTarget's (TGT +2.79%) struggles may outweigh absurd cheapness in the minds of some investors. Net sales have declined for years, and challenges such as chronically high inventories, messy stores, and controversial political decisions alienated many shoppers.\n\nHowever, former COO Michael Fiddelke took over as CEO in February and has set out to revive the brand. He pledged to invest $5 billion in improving stores and supply chains and incorporating more technology.\n\nTarget's turnaround has a high chance of succeeding. More than 75% of Americans live within 10 miles of a Target store, making it well-positioned for omnichannel selling. It could also benefit by restoring its reputation as an upscale discounter that built its brand.\n\nAdmittedly, this comeback remains somewhat speculative. Target's net sales fell 2% in 2025, and profits fell 9% to $3.7 billion amid rising depreciation costs.\n\nNonetheless, the company forecasts a 2% net sales increase in 2026, a sign that conditions may have begun to improve. Also, its troubles have not stopped it from maintaining a 54-year streak of payout hikes, making it a Dividend King. That dividend, which is now $4.56 per share yearly, yields 3.8%.\n\nExpand NYSE : TGT Target Today's Change ( 2.79 %) $ 3.34 Current Price $ 122.87 Key Data Points Market Cap $56B Day's Range $ 118.79 - $ 123.30 52wk Range $ 83.44 - $ 126.00 Volume 3.1K Avg Vol 6.1M Gross Margin 25.44 % Dividend Yield 3.69 %\n\nFinally, investors can buy this stock for 15 times earnings, meaning a purchase of 2.7 shares for $320 could deliver market-beating returns as conditions improve."} +{"url": "http://www.kreiszeitung.de/politik/trump-koennte-mit-genialer-strategie-den-krieg-im-iran-gewinnen-zr-94264746.html", "title": "Trump blockiert Straße von Hormus : Mullah - Regime igeht das Geld aus", "publish_date": "2026-04-16T12:30:02Z", "full_text": "Trump blockiert Straße von Hormus: Mullah-Regime geht das Geld für den Iran-Krieg aus\n\nDrucken Teilen\n\nUns auf Google folgen\n\nDie Blockade der Straße von Hormus durch den Präsidenten stellt Teherans Strategie, dem Westen wirtschaftliche Schmerzen zuzufügen, völlig auf den Kopf.\n\nWir wissen, dass Donald Trump unberechenbar ist. Wenn er jedoch bei seinem Kurs bleibt und bereit ist, das damit verbundene Risiko zu akzeptieren, könnte es sich erweisen, dass die Schließung der Straße von Hormus für den mit Iran verbundenen Seeverkehr ein entscheidender Schlag ist, der Teheran zwingt, sich seinem Willen zu beugen. Es scheint klar, dass die USA und Israel nicht erwartet haben, dass das iranische Regime ein derartiges Maß an Widerstandskraft zeigen würde.\n\nDer Persische Golf und die Straße von Hormus. © -/The Visible Earth/NASA/dpa\n\nSie haben außerdem Irans Fähigkeit unterschätzt, die Straße zu schließen, durch die 20 Prozent des weltweiten Öls sowie ein großer Teil des verflüssigten Erdgases transportiert werden. Während die Straße an ihrer schmalsten Stelle fast 30 Seemeilen breit ist, besteht der schiffbare Teil aus zwei jeweils zwei Meilen breiten Fahrspuren, getrennt durch eine Pufferzone von derselben Breite. Die USA blockieren die Straße von Hormus nun für Schiffe, die iranische Häfen ansteuern oder von dort kommen.\n\nÖlblockade als politisches Druckmittel im Iran-Krieg\n\nEin Dutzend US-Kriegsschiffe erzwingt die Blockade, unterstützt von mehreren Dutzend Kampfflugzeugen und Aufklärungsflugzeugen, so das US-Zentralkommando (Centcom). Die beabsichtigte Wirkung wird darin bestehen, Irans Wirtschaft auszutrocknen. Öl ist die Lebensader des Regimes. Es hat militärische Zerstörung aus der Luft überlebt, doch kann es auch das Unvermögen überleben, seine Soldaten zu bezahlen?\n\nDas ist klug, weil es zeigt, dass die USA über reine militärische Macht hinausdenken. In den vergangenen 25 Jahren war Washington sehr effektiv darin, durch den Einsatz von Gewalt einem Feind Schaden zuzufügen, doch es erwies sich als weniger gut darin, diese militärische Aktion mit politischen Ergebnissen in Einklang zu bringen, und das politische Ergebnis ist es, das die endgültige Lösung bringt. Rund 80 Prozent der iranischen Ölexporte passieren die Straße von Hormus.\n\nIsrael und USA attackieren Mullah-Regime – Bilder aus dem Iran-Krieg Fotostrecke ansehen\n\nDieser Handel dürfte über Nacht zum Erliegen gekommen sein, während auch Nicht-Öl-Exporte – Mineralien und Metalle – betroffen sein werden. Einer Schätzung zufolge kostet dies Iran täglich 435 Millionen US-Dollar, darunter 276 Millionen US-Dollar an entgangenen Exporten. Da die Ölexporte einen so großen Anteil an Irans Deviseneinnahmen ausmachen, dürfte dem Regime schnell das Geld ausgehen, um Importgüter zu bezahlen, was möglicherweise eine finanzielle und inflationäre Krise innerhalb Irans auslöst.\n\nAngriffe von außen auf eine Nation neigen dazu, eine Bevölkerung zu einen. Wenn das Regime jedoch jene, die es für seine Drecksarbeit braucht – Soldaten und paramilitärische Schläger –, nicht mehr bezahlen kann, könnten diese sich zurückziehen und sich darauf konzentrieren, ihre Familien zu schützen, statt Herrscher zu unterstützen, die sie nicht mehr unterstützen können. Zumindest wird es Gläubige von Mitläufern trennen. Kommt Irans Wirtschaft tatsächlich unter massiven Druck, werden Massenproteste wieder möglich, vielleicht mit weniger Menschen, die bereit sind, das Regime zu verteidigen.\n\nDie Logik der Straße von Hormus kehrt sich um\n\nDe facto hätte Trump dann die Logik von Irans eigener Schließung der Straße von Hormus auf den Kopf gestellt. Statt dass der Westen den Großteil der wirtschaftlichen Schmerzen durch höhere Ölpreise erleidet, wird Iran die bei Weitem akutesten Kosten tragen. Die Ajatollahs stehen damit vor einer noch schärferen Wahl: Sie verhandeln ein Abkommen, mit dem die USA und Israel leben können – keine Atomwaffen und möglicherweise keine Langstreckenraketen – oder sie sehen sich mit einem Zusammenbruch konfrontiert.\n\nDas würde den Weg weisen von einem schwachen „Zombie“-Regime, das an der Macht kleben kann, weil keine größere Kraft existiert, die es stürzen könnte, hin zu einem Regime, das ernsthaft in Gefahr schwebt, dass Massenproteste auf den Straßen zu einem allgemeinen Zusammenbruch der Autorität führen. Es gibt natürlich Risiken für die USA, China ist eines davon. China bezieht einen Großteil seines Öls aus Iran, und Peking hat die US-Maßnahmen bereits als „unverantwortlich und gefährlich“ bezeichnet.\n\nDie Blockade von Schiffen, die von Iran nach China fahren, könnte eine breitere Krise auslösen. Im schlimmsten Fall könnte dies zu einer direkten Konfrontation führen. Wahrscheinlicher ist, dass Präsident Xi sich selbst und China zunehmend als stabile Alternative zu einer unzuverlässigen US-Macht darstellen wird. Zweitens könnten Golf-Verbündete, die selbst unter der Einschränkung des Golf-Seeverkehrs leiden, Trumps unberechenbaren Verhaltens müde werden und aus dem US-Orbit in die Arme Chinas gedrängt werden.\n\nRisiken für Trump und die Verbündeten\n\nAuch das amerikanische Volk, das Trump teilweise wegen seiner Ablehnung ewiger Kriege unterstützte, wird nur begrenzte Geduld mit einem neuen Abnutzungskrieg haben. Es ist bemerkenswert, dass die US-amerikanische öffentliche Unterstützung für Israel seit 2022 erheblich gesunken ist. Trump wird sicherstellen müssen, dass andere Ölquellen hochgefahren werden. Iran hat in den vergangenen Monaten im Durchschnitt täglich 1,8 Millionen Barrel Rohöl exportiert.\n\nWenn der Fluss iranischen Öls zu einem Rinnsal wird, müssen andere Staaten bereit und in der Lage sein, die Lücke zu schließen, sonst wird die Auswirkung auf die Weltwirtschaft noch gravierender. Schließlich könnte Iran beschließen, sich zu rächen und damit den Waffenstillstand zu brechen. Saudi-Arabien befürchtet, dass Teheran seine Stellvertreter, die jemenitischen Huthis, anweisen wird, die Meerenge Bab al-Mandab zu schließen, die am Eingang zum Roten Meer auf der anderen Seite der Arabischen Halbinsel liegt.\n\nÜber vier Millionen Barrel pro Tag passieren diesen Engpass, ebenso wie Schiffe, die den Suezkanal durchqueren. Dessen Schließung wird den Welthandel und die Ölversorgung erheblich beeinträchtigen. Es ist bisweilen schwierig, sich ein wirkliches Bild der Ereignisse im Iran zu machen, unter anderem, weil die BBC und ein Großteil der britischen Medien zu reflexhaftem Anti-Amerikanismus neigen, den Trumps Verhalten manchmal leider noch verstärkt.\n\nSchwächung von Irans Raketen- und Atomprogramm\n\nDie Realität ist jedoch, dass die USA und Israel sowohl in dieser Runde des Konflikts als auch im 12-tägigen Krieg im vergangenen Juni den Atomprogrammen des Landes einen erheblichen Schlag versetzt haben. Auch das iranische Raketenprogramm ist geschwächt worden. Angesichts der Tatsache, dass diese Raketen eines Tages in der Lage gewesen wären, das Vereinigte Königreich zu treffen, möglicherweise mit nuklearen Sprengköpfen, sollten wir diese Entmachtung eines Feindes feiern.\n\nNun bedroht Trump die wirtschaftliche Lebensader des Regimes. Für Iran sind die Einsätze gerade deutlich gestiegen. Dr Bob Seely MBE ist der Autor von „The New Total War“ (Dieser Artikel von Bob Seely entstand in Kooperation mit telegraph.co.uk)"} +{"url": "https://www.thehindubusinessline.com/markets/gold/gold-silver-prices-rise-on-weak-dollar-geopolitical-cues-analysts-see-near-term-volatility/article70868399.ece", "title": "Why gold , silver are rising on weak dollar & geopolitical tensions ? ", "publish_date": "2026-04-16T12:30:02Z", "full_text": "Gold and silver prices moved higher in Thursday’s trade, ahead of Akshaya Tritiya, supported by a weaker US dollar, geopolitical uncertainty and shifting expectations around global interest rates. The uptick comes even as global equity markets remained firm, reflecting a mix of risk-on sentiment and safe-haven demand.\n\nGold gained as the dollar softened and crude oil prices slipped below $100 per barrel amid optimism around potential peace talks between the US and Iran. The easing in oil prices tempered inflation concerns, influencing interest rate outlook and supporting bullion. Silver and other metals also tracked the upward momentum during the session.\n\nGaurav Garg, research analyst at Lemonn Markets Desk, echoed that gold and silver prices witnessed a notable rise driven by currency weakness and geopolitical tensions linked to the Iran conflict, which has raised concerns over potential supply disruptions. Internationally, gold traded at $4,857.90 per ounce, up 1.21 per cent, while domestic prices stood near ₹1,45,697 per 10 grams. Silver climbed 1.70 per cent to $80.84 per ounce globally, with domestic prices around ₹2,42,454 per kg. Crude oil remained relatively stable, with WTI trading at $91.65 per barrel.\n\nPonmudi R, CEO of Enrich Money, noted that MCX gold is trading in the ₹1,54,500–₹1,55,000 range with emerging buying interest at lower levels. He added that a sustained move above ₹1,55,000 could push prices towards ₹1,57,000–₹1,58,000, while a break below ₹1,54,000 may trigger a correction toward ₹1,52,000–₹1,48,000. The overall bias remains cautiously positive, supported by macro factors, though stronger momentum needs confirmation.\n\nOn silver, he said prices are hovering above ₹2,54,000, supported by safe-haven demand and strength in industrial metals despite elevated volatility. Resistance is seen in the ₹2,60,000–₹2,63,000 zone, with potential upside toward ₹2,68,000–₹2,70,000. On the downside, a break below ₹2,50,000 could lead to a correction toward ₹2,44,000–₹2,40,000.\n\nAnalysts expect gold and silver to remain volatile in the near term (ahead of Akshaya Tritiya), as markets continue to track geopolitical developments, currency movements and trends in crude oil prices.\n\nPublished on April 16, 2026"} +{"url": "https://www.capital.gr/agores/3985670/xrimatistirio-epilektikes-kiniseis-kai-auximeni-metablitotita/", "title": "Χρηματιστήριο : Επιλεκτικές κινήσεις και αυξημένη μεταβλητότητα", "publish_date": "2026-04-16T12:30:02Z", "full_text": "ΤΕΛΕΥΤΑΙΑ ΕΝΗΜΕΡΩΣΗ 14:10\n\nτου Μάνου Χαχλαδάκη\n\nΣυντηρείται το θετικό κλίμα στην αγορά της Αθήνας που δείχνει διάθεση να κινηθεί για τρίτη ημέρα ανοδικά, αν και με χαμηλούς ρυθμούς εν μέσω της αυξημένης μεταβλητότητας που χαρακτηρίζει τις συναλλαγές.\n\nΕιδικότερα, ο Γενικός Δείκτης βρέθηκε έως και τις 2.311 μονάδες (+0,96%) αλλά πλέον διαπραγματεύεται στις 2.294 μονάδες με μικρά κέρδη 0,2% και τον τζίρο στα 145 εκατ. ευρώ, ενώ έχουν διακινηθεί 23 εκατ. τεμάχια.\n\nΟ τραπεζικός δείκτης βρέθηκε να ενισχύεται έως και κατά 1,3% (2.707 μον.) αλλά πλέον έχει γυρίσει ελαφρώς αρνητικός στις 2.668 μονάδες, ο FTSE της υψηλής κεφαλαιοποίησης σημειώνει άνοδο κατά 0,2% στις 5.840 μον. και ο FTSEM της μεσαίας στις 2.822 μον. με +0,4%\n\nΟυσιαστικά η συνεδρίαση δείχνει να εξελίσσεται σε διελκυστίνδα μεταξύ ορισμένων blue chips που διαφοροποιούνται έντονα θετικά, πρωτίστως της Metlen αλλά και των ΓΕΚ ΤΕΡΝΑ, Λάμδα και Aegean και από την άλλη πλευρά των τραπεζών, που έχασαν το αρχικό τους μομέντουμ και σταδιακά περνάνε σε αρνητικό έδαφος - πιθανώς και από το βάρος του profit taking που προκαλεί το ράλι 5,6% της Τρίτης.\n\nΚατά τα άλλα, η συνεδρίαση ξεκίνησε με κεκτημένη ταχύτητα από χθες (FTSEM +1,5%) για τα mid caps αλλά στην πορεία επήλθε επίσης κάποια εξισορρόπηση, με εμφανές και εδώ το χαρακτήρα stock picking στις τοποθετήσεις.\n\nΓενικότερα πάντως, το θετικό κλίμα διατηρείται στις αγορές διεθνώς καθώς οι επενδυτές δείχνουν να προεξοφλούν θετική έκβαση στις διαπραγματεύσεις ΗΠΑ - Ιράν.\n\nΕνδεικτικό είναι ότι στην Wall Street, αφότου μάζεψαν όλες τις απώλειες του πολέμου, οι S&P 500 και Nasdaq κατέγραψαν χθες νέα ιστορικά υψηλά (+0,8% και +1,6% αντίστοιχα), με τον πρόεδρο Τραμπ να επαναλαμβάνει ότι \"ο πόλεμος είναι πολύ κοντά στο να τελειώσει\" και αξιωματούχους του Λευκού Οίκου να αναφέρουν ότι σχεδιάζεται ένας νέος, δεύτερος, γύρος διαπραγματεύσεων.\n\nΣτην Ευρώπη οι κινήσεις είναι μάλλον πιο συγκρατημένες, αν και οι δείκτες σήμερα δείχνουν διάθεση να επιστρέψουν σε θετικό έδαφος μετά την ήπια οπισθοχώρηση χθες, κυρίως υπό το βάρος της πτώσης του κλάδου πολυτελείας που δέχθηκε σημαντικό πλήγμα από τον πόλεμο.\n\nΟι κινήσεις στο ταμπλό\n\nΗ Metlen επιχειρεί σταθερά από το άνοιγμα να δώσει ώθηση στον ΓΔ με εντολές έως τα 36,9 ευρώ (+4,1%).\n\nΙσχυρή άνοδο 2,4% καταγράφουν επίσης η ΓΕΚ ΤΕΡΝΑ που ανακτά τα 40 ευρώ και η Λάμδα στα 6,3 με την Aegean να ακολουθεί από κοντά στα 13,4 με +2%.\n\nΣτις τράπεζες είναι εξαιρετικά έντονη η κινητικότητα στην Πειραιώς που έχει κάνει τζίρο ήδη άνω των 42 εκατ. μόνη της (το 1/4 της συνεδρίασης) αλλά με αισθητή μεταβλητότητα - από τα 8,63 ευρώ (+1,4%) έως τα 8,48 (-0,4%) - ενώ επί του παρόντος βρίσκεται πέριξ του αμετάβλητου.\n\nΗ Alpha κινείται σταθερά ανοδικά με +0,5%, ενώ η ΕΤΕ και η Eurobank υποχωρούν ελαφρώς κατά 0,3%.\n\nΣημειώνεται ότι οι συστημικές έλαβαν ακόμα μία ψήφο εμπιστοσύνης, από την Euroxx που ανέβασε τις τιμές - στόχους κάνοντας λόγο για ευκαιρία για αγορά ενός σημαντικού story ανάπτυξης.\n\nΕκτός ΔΤΡ, η Credia κινείται δυναμικά στις παρυφές του 1,20 με +1,9%.\n\nΟι επιλογές των πωλητών στον 25άρη εστιάζουν κυρίως στις ΔΕΗ και Coca Cola αμφότερες περί του -0,9%.\n\nΣτα mid caps ξεχωρίζει πλέον το ράλι 4% του ΟΛΘ με ιδιαίτερα υψηλό τζίρο άνω των 640 χιλ. ευρώ όλα στο ταμπλό, αφότου ανακοίνωσε νέο ιστορικό υψηλό σε έσοδα και κερδοφορία το 2025.\n\nΗ Alter Ego ενισχύεται επίσης κατά 3% και η Qualco κατά 2%.\n\nΣτον αντίποδα, η Intralot έχει περάσει σε αρνητικό έδαφος στα 1,03 με -0,7%.\n\nΣτο σύνολο το ταμπλό 75 τίτλοι κινούνται ανοδικά, έναντι 50 πτωτικών.\n\nΗ εικόνα διεθνώς\n\nΠεριορισμένες είναι οι διακυμάνσεις των τιμών του πετρελαίου που πλέον κινούνται χαμηλότερα των 100 δολαρίων το βαρέλι. Το Brent στα 95,7 δολ. με +0,8% σήμερα και το αμερικανικό WTI στα 91,7 δολ. με +0,4%.\n\nΣταθεροποιητικές τάσεις δείχνει και το ευρωπαϊκό φυσικό αέριο που κινείται στα 41,7 ευρώ η μεγαβατώρα με +0,7%.\n\nΣτις μετοχές, τα συμβόλαια των δεικτών της Wall Street κινούνται ελαφρώς ανοδικά με την τεχνολογία να διατηρεί προβάδισμα, μετά τα ρεκόρ χθες (S&P 500, Nasdaq).\n\nΤα futures του Dow Jones στο +0,1%, του S&P 500 στο +0,1% και του Nasdaq στο +0,2%.\n\nΉπια ανοδική είναι η τάση και στην Ευρώπη. Ο γερμανικός DAX στο +0,5%, ο γαλλικός CAC 40 στο +0,5%, ο βρετανικός FTSE 100 στο +0,6%, ο ιταλικός FTSE MIB στο +0,35%, ο ισπανικός IBEX 35 στο +0,2% και η πανευρωπαϊκή υψηλή κεφαλαιοποίηση του Stoxx 50 στο +0,4%.\n\nΟι αγοραστές έχουν προβάδισμα και στην αγορά ομολόγων, με τις αποδόσεις να υποχωρούν ως εκ τούτου. Του δεκαετούς ΗΠΑ στο 4,27%, του γερμανικού τίτλου στο 3,01% και του γαλλικού στο 3,65%, με τον ελληνικό στο 3,75%.\n\nΤέλος, ελαφρώς ανοδική είναι η τάση και στα μέταλλα, ο χρυσός στα 4.848 δολάρια η ουγγιά με +0,5% και το ασήμι στα 80,4 δολ. με +1%."} +{"url": "https://www.marketpulse.com/markets/chart-alert-audusd-360-pips-rally-at-risk-of-a-minor-mean-reversion-decline-below-07200-before-new-upleg/", "title": "Chart alert : AUD / USD 360 pips rally at risk of a minor mean reversion decline below 0 . 7200 before new upleg", "publish_date": "2026-04-16T12:30:02Z", "full_text": "The Australian dollar has benefited significantly since last Wednesday, 8 April, when the US and Iran agreed to a ceasefire due to its higher beta factor, as the AUD has mirrored the movement of risk assets such as equities since the start of the US-Iran war on 28 February 2026, exhibiting similar risk-off movements, ignoring the hawkish monetary policy guidance advocated by the RBA.\n\nThe AUD/USD has jumped by 230 pips (+3.3%) from the 8 April 2026 low to print an intraday high of 0.7198 on Thursday, 16 April 2026 at this time of writing, just a whisker above its prior 11 March 2026 high of 0.7188.\n\nWhen measured from its current minor uptrend low of 0.6833 printed on 30 March 2026, it has rallied by almost 360 pips (+5.3%), making the Australian dollar the second-best-performing major currency against the US dollar based on a one-month rolling performance; USD/AUD (-2.47%), just behind the euro where the USD/EUR slid -3.04% (see Fig. 1)."} +{"url": "https://www.israelnetz.com/2026/04/16/", "title": "16 . 04 . 2026 - Israelnetz", "publish_date": "2026-04-16T12:30:02Z", "full_text": "Tag: 16. April 2026\n\nBritisches Vermächtnis: Okzident trifft Orient Die Architektur in Jerusalem ist stark geprägt von der britischen Mandatszeit. Nach der Übernahme der Verwaltung setzte ein Bauboom ein.\n\nStarker Schekel Mit 3,05 Schekel zu 1 US-Dollar hat die israelische Währung den stärksten Stand seit 30 Jahren erreicht. Als Gründe führt das Wirtschaftsmagazin „Globes“ unter anderem die Waffenruhe mit dem Iran und Gespräche mit dem Libanon an. Bereits seit Monaten ist der Schekel die weltweit stärkste Währung gegenüber dem US-Dollar. Ein starker Schekel dämpft die Inflation, […]\n\nDeutschland unterstützte Israel mit Waffen Wegen angeblicher „Beihilfe zum Völkermord in Gaza“ haben Anwälte in Berlin Strafanzeige gegen Bundeskanzler Friedrich Merz und andere Verantwortliche erstattet. Deutschland soll demnach Waffen im Wert von mehr als 485 Millionen Euro nach Israel xportiert haben. Unterstützt wird die Anzeige von der Initiative europäischer Juristen „Europäisches Zentrum zur Rechtsunterstützung“ (ELSC), dem „Palästina-Institut für Öffentliche Diplomatie“ […]\n\n„Apple TV“ veröffentlicht Trailer von israelischer Thriller-Serie „Unconditioned“ Der Streamingdienst „Apple TV“ hat den Trailer zur israelischen Serie „Unconditional“ veröffentlicht. Sie handelt von einer 23-jährigen Israelin (Talia Lynne Ronn), die auf einer Urlaubsreise in Moskau wegen Drogenbesitzes festgenommen wird. Ihre Mutter (Liras Chamami) kämpft dann um die Freilassung. Produzenten sind Adam Bizanski und Dana Idisis. Der achtteilige Thriller soll Ende April in Israel […]\n\n„Time“ zählt Netanjahu zu den 100 einflussreichsten Persönlichkeiten Das amerikanische Magazin „Time“ zählt den israelischen Premier Benjamin Netanjahu zu den einflussreichsten Persönlichkeiten dieses Jahres. Ihm sei nach dem Terrormassaker vom 7. Oktober dank der militärischen Erfolge ein politisches Comeback gelungen, schreibt „Time“-Kolumnist Ian Bremmer in der am Donnerstag veröffentlichten Liste. Gleichzeitig verliere Israel wegen militärischer Operationen wie im Libanon oder Gaza gerade bei […]"} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-16/Raw/raw_gdelt_asset_metals_derivatives.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-16/Raw/raw_gdelt_asset_metals_derivatives.jsonl new file mode 100644 index 0000000..718c31b --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-16/Raw/raw_gdelt_asset_metals_derivatives.jsonl @@ -0,0 +1,8 @@ +{"url": "https://www.eastbaytimes.com/2026/04/15/oral-b-water-flosser-vs-burst-water-flosser/", "url_mobile": "https://www.eastbaytimes.com/2026/04/15/oral-b-water-flosser-vs-burst-water-flosser/amp/", "title": "Oral - B water flosser vs . Burst water flosser", "seendate": "20260416T120000Z", "socialimage": "https://www.eastbaytimes.com/wp-content/uploads/2026/04/oral-b-water-flosser-vs-burst-water-flosser-326244-09b180.jpg", "domain": "eastbaytimes.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://www.finanznachrichten.de/nachrichten-2026-04/68216726-formation-metals-durchteuft-1-8-g-t-au-auf-21-9-m-oestlich-von-1-75-g-t-au-auf-30-4-m-auf-fortgeschrittenem-goldprojekt-n2-bohrungen-bestaetigen-bestae-248.htm", "url_mobile": "", "title": "Formation Metals durchteuft 1 , 8 g / t Au auf 21 , 9 m , östlich von 1 , 75 g / t Au auf 30 , 4 m auf fortgeschrittenem Goldprojekt N2 : Bohrungen bestätigen Beständigkeit von 300 m innerhalb von 5 km entlang von mineralisiertem Streichen", "seendate": "20260416T120000Z", "socialimage": "https://www.finanznachrichten.de/chart-formation-metals-inc-aktie-intraday-tradegate.png", "domain": "finanznachrichten.de", "language": "German", "sourcecountry": "Germany"} +{"url": "https://www.hellenicshippingnews.com/the-commodities-feed-oil-trades-lower-on-de-escalation-hopes/", "url_mobile": "", "title": "The Commodities Feed : Oil trades lower on de - escalation hopes | Hellenic Shipping News Worldwide", "seendate": "20260416T120000Z", "socialimage": "", "domain": "hellenicshippingnews.com", "language": "English", "sourcecountry": "China"} +{"url": "https://sudanile.com/%D8%A7%D9%84%D8%A7%D9%82%D8%AA%D8%B5%D8%A7%D8%AF-%D8%A7%D9%84%D8%B3%D9%88%D8%AF%D8%A7%D9%86%D9%8A-%D9%81%D9%8A-%D8%B8%D9%84-%D8%AD%D8%B1%D8%A8%D9%8A%D9%86/", "url_mobile": "", "title": "الاقتصاد السوداني في ظل حربين", "seendate": "20260416T120000Z", "socialimage": "https://sudanile.com/wp-content/uploads/2026/01/omersidahmed.jpg", "domain": "sudanile.com", "language": "Arabic", "sourcecountry": "Sudan"} +{"url": "https://finance.eastmoney.com/a/202604163707626246.html", "url_mobile": "", "title": "4月16日晚间沪深上市公司重大事项公告最新快递 _ 东方财富网", "seendate": "20260416T120000Z", "socialimage": "", "domain": "finance.eastmoney.com", "language": "Chinese", "sourcecountry": "China"} +{"url": "https://www.capital.gr/agores/3985670/xrimatistirio-epilektikes-kiniseis-kai-auximeni-metablitotita/", "url_mobile": "https://www.capital.gr/agores/3985670/xrimatistirio-epilektikes-kiniseis-kai-auximeni-metablitotita/?amp=true", "title": "Χρηματιστήριο : Επιλεκτικές κινήσεις και αυξημένη μεταβλητότητα", "seendate": "20260416T120000Z", "socialimage": "https://www.capital.gr/Content/ImagesDatabase/fb/1000x523/crop/both/1c/1c7dc27ec6bb415283b6d5247933b503.jpg", "domain": "capital.gr", "language": "Greek", "sourcecountry": "Greece"} +{"url": "https://www.1in.am/3705445.html", "url_mobile": "", "title": "Նավթի գներ – 15 / 04 / 26", "seendate": "20260416T120000Z", "socialimage": "https://www.1in.am/assets/uploads/2026/04/6000-849-540x360.jpg", "domain": "1in.am", "language": "Armenian", "sourcecountry": "Armenia"} +{"url": "https://www.newratings.de/du/main/company_headline.m?nid=19666857", "url_mobile": "", "title": "newratings . de", "seendate": "20260416T120000Z", "socialimage": "", "domain": "newratings.de", "language": "German", "sourcecountry": "Germany"} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-16/Raw/raw_gdelt_macro_central_banks.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-16/Raw/raw_gdelt_macro_central_banks.jsonl new file mode 100644 index 0000000..14f5d22 --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-16/Raw/raw_gdelt_macro_central_banks.jsonl @@ -0,0 +1,10 @@ +{"url": "https://edition.cnn.com/2026/04/16/economy/powell-fed-trump-interest-rates", "url_mobile": "", "title": "Trump own actions against Powell and the Fed are working against him", "seendate": "20260416T120000Z", "socialimage": "https://media.cnn.com/api/v1/images/stellar/prod/2025-07-24t211944z-216166992-rc28tfa1flx3-rtrmadp-3-usa-trump-fed-20260415201241131.JPG?c=16x9&q=w_800,c_fill", "domain": "edition.cnn.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://uzmanpara.milliyet.com.tr/kap-haberi/pay-disinda-sermaye-piyasasi-araci-islemlerine-iliskin-bildirim-faiz-iceren/69e0c5d267ad3132ebe299f1/", "url_mobile": "", "title": "Pay Dışında Sermaye Piyasası Aracı İşlemlerine İlişkin Bildirim ( Faiz İçeren ) ", "seendate": "20260416T120000Z", "socialimage": "https://imgfinans.milliyet.com.tr/i/uzmanpara.png", "domain": "uzmanpara.milliyet.com.tr", "language": "Turkish", "sourcecountry": "Turkey"} +{"url": "https://www.finanznachrichten.de/nachrichten-2026-04/68216751-eur-jpy-gibt-leicht-nach-da-die-hoehere-inflation-in-der-eurozone-den-fokus-auf-ezb-signale-verlagert-545.htm", "url_mobile": "", "title": "EUR / JPY gibt leicht nach , da die höhere Inflation in der Eurozone den Fokus auf EZB - Signale verlagert", "seendate": "20260416T120000Z", "socialimage": "https://www.finanznachrichten.de/nicht-boersennotiert-chart.png", "domain": "finanznachrichten.de", "language": "German", "sourcecountry": "Germany"} +{"url": "https://dantri.com.vn/kinh-doanh/chu-tich-chung-khoan-rong-viet-noi-ve-moi-quan-he-voi-kido-foods-20260416175340107.htm", "url_mobile": "", "title": "Chủ tịch Chứng khoán Rồng Việt nói về mối quan hệ với KIDO Foods", "seendate": "20260416T120000Z", "socialimage": "https://cdnphoto.dantri.com.vn/M-Lm8acIY0RrjxcThm0TJyWRgKk=/zoom/1200_630/2026/04/16/mien-tuan-vds-cropped-1776336752527.jpg", "domain": "dantri.com.vn", "language": "Vietnamese", "sourcecountry": "Vietnam"} +{"url": "https://www.thehindubusinessline.com/markets/gold/gold-silver-prices-rise-on-weak-dollar-geopolitical-cues-analysts-see-near-term-volatility/article70868399.ece", "url_mobile": "https://www.thehindubusinessline.com/markets/gold/gold-silver-prices-rise-on-weak-dollar-geopolitical-cues-analysts-see-near-term-volatility/article70868399.ece/amp/", "title": "Why gold , silver are rising on weak dollar & geopolitical tensions ? ", "seendate": "20260416T120000Z", "socialimage": "https://bl-i.thgim.com/public/incoming/ylh7fy/article70868566.ece/alternates/LANDSCAPE_1200/2026-01-28T135228Z_1432587036_RC2CAJA9GI69_RTRMADP_3_GLOBAL-PRECIOUS-GERMANY-GOLD.JPG", "domain": "thehindubusinessline.com", "language": "English", "sourcecountry": "India"} +{"url": "https://www.marketpulse.com/markets/chart-alert-audusd-360-pips-rally-at-risk-of-a-minor-mean-reversion-decline-below-07200-before-new-upleg/", "url_mobile": "", "title": "Chart alert : AUD / USD 360 pips rally at risk of a minor mean reversion decline below 0 . 7200 before new upleg", "seendate": "20260416T120000Z", "socialimage": "https://storage.googleapis.com/web-content.oanda.com/images/AUD_1920x1080-1.original.jpg", "domain": "marketpulse.com", "language": "English", "sourcecountry": "United States"} +{"url": "http://www.irishsun.com/news/278987031/cbuae-highlights-uae-proactive-approach-to-financial-resilience-in-washington", "url_mobile": "", "title": "CBUAE highlights UAE proactive approach to financial resilience in Washington", "seendate": "20260416T120000Z", "socialimage": "https://image.chitra.live/api/v1/wps/3141291/96e30e2c-037d-4fa9-9b2f-e4e957f751e1/0/ZDhiMTA2ZjItMzk-600x315.jpg", "domain": "irishsun.com", "language": "English", "sourcecountry": "Ireland"} +{"url": "https://www.dailykos.com/stories/2026/4/16/800020794/community/this/", "url_mobile": "", "title": "Say What You Mean", "seendate": "20260416T120000Z", "socialimage": "https://www.dailykos.com/wp-content/uploads/sites/2/2026/04/20260416TillisNot.png", "domain": "dailykos.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://www.vedomosti.ru/economics/news/2026/04/16/1190832-inflyatsionnie-ozhidaniya", "url_mobile": "", "title": "Инфляционные ожидания россиян в апреле сократились до 12 , 9 % ", "seendate": "20260416T114500Z", "socialimage": "https://sharing.vedomosti.ru/1776338218/vedomosti.ru/economics/news/2026/04/16/1190832-inflyatsionnie-ozhidaniya.jpg", "domain": "vedomosti.ru", "language": "Russian", "sourcecountry": "Russia"} +{"url": "https://www.brasil247.com:443/economia/governo-projeta-crescimento-de-2-56-do-pib-e-inflacao-de-3-04-em-2027-u72b8zti", "url_mobile": "", "title": "Governo projeta crescimento de 2 , 56 % do PIB e inflao de 3 , 04 % em 2027", "seendate": "20260416T114500Z", "socialimage": "https://cdn.brasil247.com/pb-b247gcp/swp/jtjeq9/media/20260415140444_37b5a25db4233fa94ee0623756c1a361ea0ae654e9afa9ded573a95baa186ee9.jpg", "domain": "brasil247.com", "language": "Portuguese", "sourcecountry": "Brazil"} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-16/Raw/raw_gdelt_macro_geopolitics_risk.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-16/Raw/raw_gdelt_macro_geopolitics_risk.jsonl new file mode 100644 index 0000000..36dbfea --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-16/Raw/raw_gdelt_macro_geopolitics_risk.jsonl @@ -0,0 +1,9 @@ +{"url": "https://www.unian.ua/economics/other/ne-vistachaye-stazhu-dlya-pensiji-ukrajincyam-poyasnili-yak-dokupiti-roki-i-skilki-ce-koshtuye-13351200.html", "url_mobile": "https://www.unian.ua/economics/other/ne-vistachaye-stazhu-dlya-pensiji-ukrajincyam-poyasnili-yak-dokupiti-roki-i-skilki-ce-koshtuye-ostanni-novini-amp-13351200.html", "title": "Що робити , якщо не вистачає стажу для пенсії - в ПФУ пояснили , як купити роки", "seendate": "20260416T120000Z", "socialimage": "https://images.unian.net/photos/2025_07/thumb_files/620_324_1753794916-1797.jpg?1", "domain": "unian.ua", "language": "Ukrainian", "sourcecountry": "Ukraine"} +{"url": "https://finance.eastmoney.com/a/202604163707548732.html", "url_mobile": "", "title": " AI需求极其强劲 ! 台积电法说会实录 : 供不应求将持续至至少2027年 _ 东方财富网", "seendate": "20260416T120000Z", "socialimage": "", "domain": "finance.eastmoney.com", "language": "Chinese", "sourcecountry": "China"} +{"url": "https://www.volynnews.com/news/all/u-lutskomu-rayoni-dvoye-brativ-iaki-perebuvaiut-v-rozshuku-pobylysia-z-hrupoiu-opovishchennia/", "url_mobile": "", "title": "У Луцькому районі двоє братів , які перебувають в розшуку , побилися з групою оповіщення", "seendate": "20260416T120000Z", "socialimage": "https://www.volynnews.com/files/news/2026/04-16/422588/1.jpg", "domain": "volynnews.com", "language": "Ukrainian", "sourcecountry": "Ukraine"} +{"url": "https://www.design-reuse.com/news/202530378-three-misconceptions-about-the-402b-semiconductor-foundry-industry/", "url_mobile": "", "title": "Three Misconceptions About the $402B Semiconductor Foundry Industry", "seendate": "20260416T120000Z", "socialimage": "", "domain": "design-reuse.com", "language": "English", "sourcecountry": "China"} +{"url": "https://www.redlandsdailyfacts.com/2026/04/16/us-iran-war-israel/", "url_mobile": "", "title": "Pakistani army chief visits Tehran in hopes of renewed US - Iran talks", "seendate": "20260416T120000Z", "socialimage": "https://www.redlandsdailyfacts.com/wp-content/uploads/2026/04/APTOPIX_Iran_War_97981-1.jpg", "domain": "redlandsdailyfacts.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://www.laprovincia.es/economia/2026/04/16/inflacion-eurozona-repunta-2-6-marzo-encarecimiento-energia-guerra-iran-129169885.html", "url_mobile": "https://www.laprovincia.es/economia/2026/04/16/inflacion-eurozona-repunta-2-6-marzo-encarecimiento-energia-guerra-iran-129169885.amp.html", "title": "La inflación de la eurozona repunta al 2 , 6 % en marzo por el encarecimiento de la energía tras la guerra en Irán", "seendate": "20260416T120000Z", "socialimage": "https://estaticos-cdn.prensaiberica.es/clip/de35dce5-458f-4b9e-905c-c4510e213079_16-9-discover-aspect-ratio_default_0.jpg", "domain": "laprovincia.es", "language": "Spanish", "sourcecountry": "Spain"} +{"url": "https://stars.glavred.info/ne-yunaya-i-s-probegom-tinu-karol-zhestko-podkololi-na-muzykalnoy-premii-10757126.html", "url_mobile": "https://stars.glavred.info/amp-ne-yunaya-i-s-probegom-tinu-karol-zhestko-podkololi-na-muzykalnoy-premii-10757126.html", "title": "Тина Кароль скандал - Тину Кароль подкололи на премии YUNA", "seendate": "20260416T120000Z", "socialimage": "https://images.glavred.info/2026_04/thumb_files/600x420/1776335136-1651.jpg", "domain": "stars.glavred.info", "language": "Russian", "sourcecountry": "Ukraine"} +{"url": "https://www.stcatharinesstandard.ca/news/world/united-states/killing-of-iranian-activist-in-canada-exposes-increasingly-bitter-divisions-within-the-diaspora/article_823736e8-ea08-5c6e-a647-04a9d4ebea58.html", "url_mobile": "", "title": "Killing of Iranian activist in Canada exposes increasingly bitter divisions within the diaspora", "seendate": "20260416T120000Z", "socialimage": "https://bloximages.chicago2.vip.townnews.com/stcatharinesstandard.ca/content/tncms/assets/v3/editorial/f/97/f9745984-3fc8-5ebf-a096-f17c596b40c4/69e0b8054e6de.image.jpg?crop=1620%2C851%2C0%2C114", "domain": "stcatharinesstandard.ca", "language": "English", "sourcecountry": "Canada"} +{"url": "https://multiplayer.it/notizie/tsmc-alza-previsioni-2026-ricavi-aumenteranno-ia.html", "url_mobile": "", "title": "TSMC alza le previsioni : nel 2026 i ricavi aumenteranno ancora grazie allIA", "seendate": "20260416T120000Z", "socialimage": "", "domain": "multiplayer.it", "language": "Italian", "sourcecountry": "Italy"} diff --git a/Data/1_Bronze_Raw/News_Scrapes/2026-04-16/Raw/raw_gdelt_macro_yields_dollar.jsonl b/Data/1_Bronze_Raw/News_Scrapes/2026-04-16/Raw/raw_gdelt_macro_yields_dollar.jsonl new file mode 100644 index 0000000..9c5d8a5 --- /dev/null +++ b/Data/1_Bronze_Raw/News_Scrapes/2026-04-16/Raw/raw_gdelt_macro_yields_dollar.jsonl @@ -0,0 +1,10 @@ +{"url": "https://www.thehindubusinessline.com/markets/stock-markets-close-lower-on-profit-taking-in-financial-shares/article70868922.ece", "url_mobile": "https://www.thehindubusinessline.com/markets/stock-markets-close-lower-on-profit-taking-in-financial-shares/article70868922.ece/amp/", "title": "Sensex , Nifty pare gains to end marginally lower , Adani Enterprises , Hindalco lead gainers", "seendate": "20260416T120000Z", "socialimage": "https://bl-i.thgim.com/public/incoming/vlfloy/article70867902.ece/alternates/LANDSCAPE_1200/PO_Candle_chart.jpg", "domain": "thehindubusinessline.com", "language": "English", "sourcecountry": "India"} +{"url": "https://www.handelsblatt.com/unternehmen/industrie/autozulieferer-bosch-ueberrascht-nach-roten-zahlen-mit-positivem-ausblick/100215955.html", "url_mobile": "", "title": "Autozulieferer : Bosch überrascht nach roten Zahlen mit positivem Ausblick", "seendate": "20260416T120000Z", "socialimage": "https://images.handelsblatt.com/Kf-15HB-2xTB/cover/2048/1152/0/0/93/72/0.5/0.5/bosch.jpg", "domain": "handelsblatt.com", "language": "German", "sourcecountry": "Germany"} +{"url": "https://www.marketpulse.com/markets/cable-eyes-13696-after-reclaiming-key-moving-averages-bulls-defend-13500/", "url_mobile": "", "title": "Cable eyes 1 . 3696 after reclaiming key moving averages , bulls defend 1 . 3500", "seendate": "20260416T120000Z", "socialimage": "https://storage.googleapis.com/web-content.oanda.com/images/GBP_1920x1080-1.original.jpg", "domain": "marketpulse.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://www.fool.com/investing/2026/04/16/3-absurdly-cheap-stocks-to-buy-with-1000-while-the/?source=iedfolrf0000001", "url_mobile": "", "title": "3 Absurdly Cheap Stocks to Buy With $1 , 000 While the Market Is This Nervous", "seendate": "20260416T120000Z", "socialimage": "https://g.foolcdn.com/editorial/images/864973/holding-up-a-fan-of-5-dollar-bills.jpg", "domain": "fool.com", "language": "English", "sourcecountry": "United States"} +{"url": "http://www.kreiszeitung.de/politik/trump-koennte-mit-genialer-strategie-den-krieg-im-iran-gewinnen-zr-94264746.html", "url_mobile": "", "title": "Trump blockiert Straße von Hormus : Mullah - Regime igeht das Geld aus", "seendate": "20260416T120000Z", "socialimage": "", "domain": "kreiszeitung.de", "language": "German", "sourcecountry": "Germany"} +{"url": "https://www.thehindubusinessline.com/markets/gold/gold-silver-prices-rise-on-weak-dollar-geopolitical-cues-analysts-see-near-term-volatility/article70868399.ece", "url_mobile": "https://www.thehindubusinessline.com/markets/gold/gold-silver-prices-rise-on-weak-dollar-geopolitical-cues-analysts-see-near-term-volatility/article70868399.ece/amp/", "title": "Why gold , silver are rising on weak dollar & geopolitical tensions ? ", "seendate": "20260416T120000Z", "socialimage": "https://bl-i.thgim.com/public/incoming/ylh7fy/article70868566.ece/alternates/LANDSCAPE_1200/2026-01-28T135228Z_1432587036_RC2CAJA9GI69_RTRMADP_3_GLOBAL-PRECIOUS-GERMANY-GOLD.JPG", "domain": "thehindubusinessline.com", "language": "English", "sourcecountry": "India"} +{"url": "https://www.capital.gr/agores/3985670/xrimatistirio-epilektikes-kiniseis-kai-auximeni-metablitotita/", "url_mobile": "https://www.capital.gr/agores/3985670/xrimatistirio-epilektikes-kiniseis-kai-auximeni-metablitotita/?amp=true", "title": "Χρηματιστήριο : Επιλεκτικές κινήσεις και αυξημένη μεταβλητότητα", "seendate": "20260416T120000Z", "socialimage": "https://www.capital.gr/Content/ImagesDatabase/fb/1000x523/crop/both/1c/1c7dc27ec6bb415283b6d5247933b503.jpg", "domain": "capital.gr", "language": "Greek", "sourcecountry": "Greece"} +{"url": "http://news.fjsen.com/2026-04/16/content_32170251.htm", "url_mobile": "", "title": "老工业基地在绿色转型中焕发新气象 来自草原钢城一线的调查报告", "seendate": "20260416T120000Z", "socialimage": "", "domain": "news.fjsen.com", "language": "Chinese", "sourcecountry": "China"} +{"url": "https://www.marketpulse.com/markets/chart-alert-audusd-360-pips-rally-at-risk-of-a-minor-mean-reversion-decline-below-07200-before-new-upleg/", "url_mobile": "", "title": "Chart alert : AUD / USD 360 pips rally at risk of a minor mean reversion decline below 0 . 7200 before new upleg", "seendate": "20260416T120000Z", "socialimage": "https://storage.googleapis.com/web-content.oanda.com/images/AUD_1920x1080-1.original.jpg", "domain": "marketpulse.com", "language": "English", "sourcecountry": "United States"} +{"url": "https://www.israelnetz.com/2026/04/16/", "url_mobile": "", "title": "16 . 04 . 2026 - Israelnetz", "seendate": "20260416T120000Z", "socialimage": "", "domain": "israelnetz.com", "language": "German", "sourcecountry": "Israel"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/AAPL_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/AAPL_2026-04-04.jsonl new file mode 100644 index 0000000..a169476 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/AAPL_2026-04-04.jsonl @@ -0,0 +1,3 @@ +{"metadata": {"ticker": "AAPL", "form_type": "4", "filed_at": "2026-04-03T18:30:45-04:00", "accession_no": "0001140361-26-013192", "url": "https://www.sec.gov/Archives/edgar/data/320193/000114036126013192/xslF345X06/form4.xml", "ingested_at": "2026-04-04T22:49:03.052799"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "O'BRIEN DEIRDRE", "role": "Senior Vice President", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 64317.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 201127.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 34315.0, "price": 255.63, "total_value": 8771943.45, "post_transaction_shares": 166812.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 20338.0, "price": 255.12, "total_value": 5188630.5600000005, "post_transaction_shares": 146474.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 9664.0, "price": 255.82, "total_value": 2472244.48, "post_transaction_shares": 136810.0, "is_10b5_1_planned": true}]}} +{"metadata": {"ticker": "AAPL", "form_type": "4", "filed_at": "2026-04-03T18:30:43-04:00", "accession_no": "0001140361-26-013191", "url": "https://www.sec.gov/Archives/edgar/data/320193/000114036126013191/xslF345X06/form4.xml", "ingested_at": "2026-04-04T22:49:03.628698"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Khan Sabih", "role": "COO", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 64317.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 1107212.0, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 33317.0, "price": 255.63, "total_value": 8516824.709999999, "post_transaction_shares": 1073895.0, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "AAPL", "form_type": "4", "filed_at": "2026-04-03T18:30:41-04:00", "accession_no": "0001140361-26-013190", "url": "https://www.sec.gov/Archives/edgar/data/320193/000114036126013190/xslF345X06/form4.xml", "ingested_at": "2026-04-04T22:49:04.205425"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "COOK TIMOTHY D", "role": "Chief Executive Officer", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 131576.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 3411994.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 66627.0, "price": 255.63, "total_value": 17031860.009999998, "post_transaction_shares": 3345367.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 5087.0, "price": 251.25, "total_value": 1278108.75, "post_transaction_shares": 3340280.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 9147.0, "price": 252.11, "total_value": 2306050.17, "post_transaction_shares": 3331133.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1878.0, "price": 253.13, "total_value": 475378.14, "post_transaction_shares": 3329255.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 16083.0, "price": 254.37, "total_value": 4091032.71, "post_transaction_shares": 3313172.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 28188.0, "price": 255.17, "total_value": 7192731.96, "post_transaction_shares": 3284984.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 4566.0, "price": 256.0, "total_value": 1168896.0, "post_transaction_shares": 3280418.0, "is_10b5_1_planned": true}]}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/AMAT_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/AMAT_2026-04-04.jsonl new file mode 100644 index 0000000..e26acbf --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/AMAT_2026-04-04.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "AMAT", "form_type": "4", "filed_at": "2026-04-02T18:44:21-04:00", "accession_no": "0001628280-26-023379", "url": "https://www.sec.gov/Archives/edgar/data/6951/000162828026023379/xslF345X06/wk-form4_1775169858.xml", "ingested_at": "2026-04-04T22:54:48.024214"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Sanders Adam", "role": "Corp. Controller & CAO", "transactions": [{"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 125.0, "price": 353.8, "total_value": 44225.0, "post_transaction_shares": 4548.0, "is_10b5_1_planned": false}]}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/AMZN_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/AMZN_2026-04-04.jsonl new file mode 100644 index 0000000..9b4bfab --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/AMZN_2026-04-04.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "AMZN", "form_type": "4", "filed_at": "2026-04-03T16:41:29-04:00", "accession_no": "0001018724-26-000010", "url": "https://www.sec.gov/Archives/edgar/data/1018724/000101872426000010/xslF345X06/wk-form4_1775248886.xml", "ingested_at": "2026-04-04T22:54:20.480654"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Herrington Douglas J", "role": "CEO Worldwide Amazon Stores", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1000.0, "price": 210.5, "total_value": 210500.0, "post_transaction_shares": 520361.0, "is_10b5_1_planned": true}]}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/AVGO_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/AVGO_2026-04-04.jsonl new file mode 100644 index 0000000..b035647 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/AVGO_2026-04-04.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "AVGO", "form_type": "8-K", "filed_at": "2026-04-02T17:25:00-04:00", "accession_no": "0001193125-26-140574", "url": "https://www.sec.gov/Archives/edgar/data/1730168/000119312526140574/d109450d8k.htm", "ingested_at": "2026-04-04T22:54:26.159841"}, "raw_text": "8-K false 0001730168 0001730168 2026-03-30 2026-03-30 UNITED STATES SECURITIES AND EXCHANGE COMMISSION Washington, D.C. 20549 FORM 8-K CURRENT REPORT PURSUANT TO SECTION 13 OR 15(d) OF THE SECURITIES EXCHANGE ACT OF 1934 Date of Report (Date of earliest event reported): March 30, 2026 Broadcom Inc. (Exact Name of Registrant as Specified in Charter) Delaware 001-38449 35-2617337 (State or other jurisdiction of incorporation) (Commission File Number) (I.R.S. Employer Identification No.) 3421 Hillview Avenue Palo Alto , California 94304 (Address of principal executive offices including zip code) (650) 427-6000 (Registrant’s telephone number, including area code) Check the appropriate box below if the Form 8-K filing is intended to simultaneously satisfy the filing obligation of the registrant under any of the following provisions: ☐ Written communications pursuant to Rule 425 under the Securities Act (17 CFR 230.425) ☐ Soliciting material pursuant to Rule 14a-12 under the Exchange Act (17 CFR 240.14a-12) ☐ Pre-commencement communications pursuant to Rule 14d-2(b) under the Exchange Act (17 CFR 240.14d-2(b)) ☐ Pre-commencement communications pursuant to Rule 13e-4(c) under the Exchange Act (17 CFR 240.13e-4(c)) Securities registered pursuant to Section 12(b) of the Act: Title of Each Class Trading Symbol(s) Name of Each Exchange on Which Registered Common Stock, $0.001 par value AVGO The NASDAQ Global Select Market Indicate by check mark whether the registrant is an emerging growth company as defined in Rule 405 of the Securities Act of 1933 (§230.405 of this chapter) or Rule 12b-2 of the Securities Exchange Act of 1934 (§240.12b-2 of this chapter). Emerging growth company ☐ If an emerging growth company, indicate by check mark if the registrant has elected not to use the extended transition period for complying with any new or revised financial accounting standards provided pursuant to Section 13(a) of the Exchange Act. ☐ Item 5.02 Departure of Directors or Certain Officers; Election of Directors; Appointment of Certain Officers; Compensatory Arrangements of Certain Officers. Chief Financial Officer Transition On March 30, 2026, Kirsten M. Spears notified Broadcom Inc. (the “Company”) of her retirement and resigned from her position as Chief Financial Officer and Chief Accounting Officer of the Company, effective as of June 12, 2026. On March 30, 2026, the Board of Directors of the Company (the “Board”) appointed Amie Thuener to succeed Ms. Spears as the Chief Financial Officer of the Company, effective as of June 12, 2026. The employment of Ms. Thuener with the Company is expected to commence on May 4, 2026 and she will assume the role of Chief Financial Officer following the retirement of Ms. Spears on June 12, 2026. Ms. Thuener, age 51, has served as Vice President, Corporate Controller and Chief Accounting Officer of Alphabet Inc. since 2018. Ms. Thuener held several senior finance positions at Alphabet from 2013 to 2018, including as Vice President and Chief Accountant. Prior to joining Alphabet, Ms. Thuener was at PricewaterhouseCoopers LLP from 1996 to 2012 and held several senior management positions, including as Managing Director, Transaction Services. Ms. Thuener is a Certified Public Accountant and a Chartered Global Management Accountant. There are no family relationships between Ms. Thuener and any director or executive officer of the Company as defined in Item 401(d) of Regulation S-K, and Ms. Thuener has no direct or indirect material interest in any transaction or proposed transaction required to be disclosed pursuant to Item 404(a) of Regulation S-K. Kirsten M. Spears Transition and Consulting Agreement In connection with the retirement of Ms. Spears, the Company entered into a transition and consulting agreement with Ms. Spears, dated as of April 1, 2026 (the “Transition Agreement”). The Transition Agreement provides that, following the conclusion of Ms. Spears’ employment with the Company on June 12, 2026, she will provide consulting services to the Company, as reasonably requested by the Chief Executive Officer of the Company, until March 15, 2027, unless the consulting period terminates earlier in accordance with the terms of the Transition Agreement. During the consulting period, Ms. Spears’ outstanding equity awards will continue to vest in accordance with their terms (provided that the performance-based equity awards will in no event vest at a level exceeding target). Ms. Spears will not receive any other compensation during the consulting period. The Transition Agreement includes a general release of claims in favor of the Company. Amie Thuener Offer Letter and Equity Awards In connection with her employment with the Company and appointment as Chief Financial Officer of the Company, effective as of June 12, 2026, the Company entered into an offer letter with Ms. Thuener, dated as of March 30, 2026, which sets forth the material terms of her employment and compensation (the “Offer Letter”). Pursuant to the Offer Letter, Ms. Thuener will receive an annual base salary of $700,000 and will be eligible to participate in the Company’s annual performance bonus plan with a target bonus opportunity of 100% of her base salary. Ms. Thuener will also receive a $1,000,000 sign-on cash bonus, payable within 30 days following the commencement of her employment. The Offer Letter further provides that, subject to the approval of the Compensation Committee of the Board and Ms. Thuener’s continued employment through the applicable grant date, Ms. Thuener will be granted equity awards under the Company’s 2012 Stock Incentive Plan consisting of (i) 50,000 restricted stock units (“RSUs”) and (ii) 50,000 performance stock units (“PSUs”) at target. The equity awards are expected to be granted on June 15, 2026. The RSUs will vest in equal quarterly installments over a four-year period following the grant date, subject to Ms. Thuener’s continued employment through each applicable vesting date. The PSUs will vest annually over a four-year period across four overlapping performance periods (March 2, 2026 through March 1, 2027, March 2, 2026 through March 1, 2028, March 2, 2026 through March 1, 2029 and March 2, 2026 through March 1, 2030) based on the Company’s total stockholder return relative to the S&P 500 and the Company’s absolute total stockholder return for the applicable performance period, in each case subject to Ms. Thuener’s continued employment through the anniversary of the grant date immediately following the end of each applicable performance period. The maximum vesting for the PSUs is 200% of the total target number of shares. The equity awards will be subject to the other terms and conditions set forth in the Company’s 2012 Stock Incentive Plan and the applicable award agreements. In addition, Ms. Thuener is expected to enter into the Company’s standard form of indemnification and advancement agreement and a severance benefit agreement on terms and conditions materially consistent with those applicable to Ms. Spears pursuant to her severance benefit agreement, as described in the Company’s definitive proxy statement filed with the U.S. Securities and Exchange Commission on March 2, 2026. SIGNATURE Pursuant to the requirements of the Securities Exchange Act of 1934, the registrant has duly caused this report to be signed on its behalf by the undersigned hereunto duly authorized. Date: April 2, 2026 Broadcom Inc. By: /s/ Hock E. Tan Hock E. Tan President and Chief Executive Officer", "parsed_data": {}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/BKNG_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/BKNG_2026-04-04.jsonl new file mode 100644 index 0000000..160c798 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/BKNG_2026-04-04.jsonl @@ -0,0 +1,3 @@ +{"metadata": {"ticker": "BKNG", "form_type": "8-K", "filed_at": "2026-04-02T16:34:43-04:00", "accession_no": "0000950157-26-000465", "url": "https://www.sec.gov/Archives/edgar/data/1075531/000095015726000465/form8-k.htm", "ingested_at": "2026-04-04T22:54:56.421512"}, "raw_text": "false 12-31 0001075531 BKNG31 BKNG37 BKNG35 BKNG38 BKNG44 BKNG36 BKNG31A BKNG33 BKNG30 BKNG45 BKNG46 BKNG26 BKNG28A BKNG28 BKNG34 BKNG32A BKNG27 BKNG29 BKNG32 BKNG29A 0001075531 2026-04-02 2026-04-02 0001075531 bkng:Three750SeniorNotesDue2037Member 2026-04-02 2026-04-02 0001075531 bkng:Four125SeniorNotesDue2038Member 2026-04-02 2026-04-02 0001075531 bkng:Four250SeniorNotesDue2029Member 2026-04-02 2026-04-02 0001075531 bkng:One800SeniorNotesDue2027Member 2026-04-02 2026-04-02 0001075531 bkng:Three500SeniorNotesDue2029Member 2026-04-02 2026-04-02 0001075531 bkng:Three625SeniorNotesDue2028Member 2026-04-02 2026-04-02 0001075531 bkng:Four500SeniorNotesDue2046Member 2026-04-02 2026-04-02 0001075531 bkng:Zero500SeniorNotesDue2028Member 2026-04-02 2026-04-02 0001075531 bkng:Three125SeniorNotesDue2031Member 2026-04-02 2026-04-02 0001075531 bkng:Four750SeniorNotesDue2034Member 2026-04-02 2026-04-02 0001075531 bkng:Three625SeniorNotesDue2035Member 2026-04-02 2026-04-02 0001075531 bkng:Three875SeniorNotesDue2045Member 2026-04-02 2026-04-02 0001075531 bkng:Three750SeniorNotesDue2036Member 2026-04-02 2026-04-02 0001075531 bkng:Three000SeniorNotesDue2030Member 2026-04-02 2026-04-02 0001075531 bkng:Four000SeniorNotesDue2044Member 2026-04-02 2026-04-02 0001075531 bkng:Four500SeniorNotesDue2031Member 2026-04-02 2026-04-02 0001075531 bkng:Four000SeniorNotesDue2026Member 2026-04-02 2026-04-02 0001075531 bkng:Four125SeniorNotesDue2033Member 2026-04-02 2026-04-02 0001075531 bkng:Three250SeniorNotesDue2032Member 2026-04-02 2026-04-02 0001075531 bkng:Three625SeniorNotesDue2032Member 2026-04-02 2026-04-02 UNITED STATES SECURITIES AND EXCHANGE COMMISSION Washington, D.C. 20549 FORM 8-K CURRENT REPORT Pursuant to Section 13 or 15(d) of the Securities Exchange Act of 1934 Date of Report (Date of earliest event reported) April 2, 2026 Booking Holdings Inc. (Exact name of registrant as specified in its charter) Delaware 1-36691 06-1528493 (State or other Jurisdiction of Incorporation) (Commission File Number) (IRS Employer Identification No.) 800 Connecticut Avenue Norwalk Connecticut 06854 (Address of principal executive offices) (zip code) Registrant's telephone number, including area code: ( 203 ) 299-8000 N/A (Former name or former address, if changed since last report) Check the appropriate box below if the Form 8-K filing is intended to simultaneously satisfy the filing obligation of the registrant under any of the following\n provisions: ☐ Written communications pursuant to Rule 425 under the Securities Act (17 CFR 230.425) ☐ Soliciting material pursuant to Rule 14a-12 under the Exchange Act (17 CFR 240.14a-12) ☐ Pre-commencement communications pursuant to Rule 14d-2(b) under the Exchange Act (17 CFR 240.14d-2(b)) ☐ Pre-commencement communications pursuant to Rule 13e-4(c) under the Exchange Act (17 CFR 240.13e-4(c)) Securities Registered Pursuant to Section 12(b) of the Act: Title of Each Class: Trading Symbol Name of Each Exchange on which Registered: Common Stock par value $0.008 per share BKNG The NASDAQ Global Select Market 4.000% Senior Notes Due 2026 BKNG 26 The NASDAQ Stock Market LLC 1.800% Senior Notes Due 2027 BKNG 27 The NASDAQ Stock Market LLC 0.500% Senior Notes Due 2028 BKNG 28 The NASDAQ Stock Market LLC 3.625% Senior Notes Due 2028 BKNG 28A The NASDAQ Stock Market LLC 3.500% Senior Notes Due 2029 BKN 29A The NASDAQ Stock Market LLC 4.250% Senior Notes Due 2029 BKN 29 The NASDAQ Stock Market LLC 3.000% Senior Notes Due 2030 BKNG 30 The NASDAQ Stock Market LLC 3.125% Senior Notes Due 2031 BKNG 31A The NASDAQ Stock Market LLC 4.500% Senior Notes Due 2031 BKNG 31 The NASDAQ Stock Market LLC 3.625% Senior Notes Due 2032 BKNG 32 The NASDAQ Stock Market LLC 3.250% Senior Notes Due 2032 BKNG 32A The NASDAQ Stock Market LLC 4.125% Senior Notes Due 2033 BKNG 33 The NASDAQ Stock Market LLC 4.750% Senior Notes Due 2034 BKNG 34 The NASDAQ Stock Market LLC 3.625% Senior Notes Due 2035 BKNG 35 The NASDAQ Stock Market LLC 3.750% Senior Notes Due 2036 BKNG 36 The NASDAQ Stock Market LLC 3.750% Senior Notes Due 2037 BKNG 37 The NASDAQ Stock Market LLC 4.125% Senior Notes Due 2038 BKNG 38 The NASDAQ Stock Market LLC 4.000% Senior Notes Due 2044 BKNG 44 The NASDAQ Stock Market LLC 3.875% Senior Notes Due 2045 BKNG 45 The NASDAQ Stock Market LLC 4.500% Senior Notes Due 2046 BKNG 46 The NASDAQ Stock Market LLC Indicate by check mark whether the registrant is an emerging growth company as defined in Rule 405 of the Securities Act of 1933 (§230.405 of this chapter) or Rule 12b-2\n of the Securities Exchange Act of 1934 (§240.12b-2 of this chapter). Emerging growth company ☐ If an emerging growth company, indicate by check mark if the registrant has elected not to use the extended transition period for complying with any new or revised\n financial accounting standards provided pursuant to Section 13(a) of the Exchange Act. ☐ Item 5.03. Amendments to Articles of incorporation or Bylaws; Change in Fiscal Year. On April 2, 2026, Booking Holdings Inc. (the “Company”) filed an amendment to its Restated Certificate of Incorporation with the Delaware Secretary of State to effect the\n previously announced twenty-five-for-one forward stock split of the Company’s common stock and to proportionately increase the number of shares of the Company’s authorized common stock from 1,000,000,000 to 25,000,000,000. The amendment, which became\n effective at 4:01 p.m. Eastern Time on April 2, 2026, is filed as Exhibit 3.1 to this Current Report on Form 8-K. Trading is expected to commence on a split-adjusted basis at market open on Monday, April 6, 2026. Item 9.01. Financial Statements and Exhibits . (d) Exhibits Exhibit Number Description 3.1 Amendment to Restated Certificate of Incorporation of Booking\n Holdings Inc., dated April 2, 2026. 104 Cover Page Interactive Data File - the cover page interactive data file does not appear in the Interactive Data File because its XBRL tags are embedded within the\n Inline XBRL document. SIGNATURES Pursuant to the requirements of the Securities Exchange Act of 1934, the Registrant has duly caused this report to be signed on its behalf by the\n undersigned hereunto duly authorized. BOOKING HOLDINGS INC. By: /s/ Peter J. Millones Name: Peter J. Millones Title: Executive Vice President and General Counsel Date: April 2, 2026", "parsed_data": {}} +{"metadata": {"ticker": "BKNG", "form_type": "8-K", "filed_at": "2026-04-02T16:12:50-04:00", "accession_no": "0001075531-26-000014", "url": "https://www.sec.gov/Archives/edgar/data/1075531/000107553126000014/bkng-20260402.htm", "ingested_at": "2026-04-04T22:54:57.020686"}, "raw_text": "bkng-20260402 false 0001075531 0001075531 2026-04-02 2026-04-02 0001075531 us-gaap:CommonStockMember 2026-04-02 2026-04-02 0001075531 bkng:A4000SeniorNotesDue2026Member 2026-04-02 2026-04-02 0001075531 bkng:A1.8SeniorNotesDueMarch2027Member 2026-04-02 2026-04-02 0001075531 bkng:A05SeniorNotesDueMarch2028Member 2026-04-02 2026-04-02 0001075531 bkng:A3625SeniorNotesDue2028Member 2026-04-02 2026-04-02 0001075531 bkng:A3.500SeniorNotesDueMarch2029Member 2026-04-02 2026-04-02 0001075531 bkng:A4250SeniorNotesDue2029Member 2026-04-02 2026-04-02 0001075531 bkng:A3.0SeniorNotesDueNovember2030Member 2026-04-02 2026-04-02 0001075531 bkng:A3.125SeniorNotesDueMay2031Member 2026-04-02 2026-04-02 0001075531 bkng:A450SeniorNotesDue2031Member 2026-04-02 2026-04-02 0001075531 bkng:A3.625SeniorNotesDueMarch2032Member 2026-04-02 2026-04-02 0001075531 bkng:A3.250SeniorNotesDueNovember2032Member 2026-04-02 2026-04-02 0001075531 bkng:A4125SeniorNotesDue2033Member 2026-04-02 2026-04-02 0001075531 bkng:A4750SeniorNotesDue2034Member 2026-04-02 2026-04-02 0001075531 bkng:A3.625SeniorNotesDueNovember2035Member 2026-04-02 2026-04-02 0001075531 bkng:A3.750SeniorNotesDueMarch2036Member 2026-04-02 2026-04-02 0001075531 bkng:A3.750SeniorNotesDueNovember2037Member 2026-04-02 2026-04-02 0001075531 bkng:A4.125SeniorNotesDueMay2038Member 2026-04-02 2026-04-02 0001075531 bkng:A4.000SeniorNotesDueMarch2044Member 2026-04-02 2026-04-02 0001075531 bkng:A3.875SeniorNotesDueMarch2045Member 2026-04-02 2026-04-02 0001075531 bkng:A4.500SeniorNotesDueMay2046Member 2026-04-02 2026-04-02 UNITED STATES SECURITIES AND EXCHANGE COMMISSION Washington, D.C. 20549 FORM 8-K CURRENT REPORT Pursuant to Section 13 or 15(d) of the Securities Exchange Act of 1934 Date of Report (Date of earliest event reported) April 2, 2026 Booking Holdings Inc. (Exact name of registrant as specified in its charter) Delaware 1-36691 06-1528493 (State or other Jurisdiction of Incorporation) (Commission File Number) (IRS Employer Identification No.) 800 Connecticut Avenue Norwalk Connecticut 06854 (Address of principal executive offices) (zip code) Registrant's telephone number, including area code: ( 203 ) 299-8000 N/A (Former name or former address, if changed since last report) Check the appropriate box below if the Form 8-K filing is intended to simultaneously satisfy the filing obligation of the registrant under any of the following provisions: ☐ Written communications pursuant to Rule 425 under the Securities Act (17 CFR 230.425) ☐ Soliciting material pursuant to Rule 14a-12  under the Exchange Act (17 CFR 240.14a-12) ☐ Pre-commencement communications pursuant to Rule 14d-2(b) under the Exchange Act (17 CFR 240.14d-2(b)) ☐ Pre-commencement communications pursuant to Rule 13e-4(c) under the Exchange Act (17 CFR 240.13e-4(c)) Securities Registered Pursuant to Section 12(b) of the Act: Title of Each Class: Trading Symbol Name of Each Exchange on which Registered: Common Stock par value $0.008 per share BKNG The NASDAQ Global Select Market 4.000% Senior Notes Due 2026 BKNG 26 The NASDAQ Stock Market LLC 1.800% Senior Notes Due 2027 BKNG 27 The NASDAQ Stock Market LLC 0.500% Senior Notes Due 2028 BKNG 28 The NASDAQ Stock Market LLC 3.625% Senior Notes Due 2028 BKNG 28A The NASDAQ Stock Market LLC 3.500% Senior Notes Due 2029 BKNG 29A The NASDAQ Stock Market LLC 4.250% Senior Notes Due 2029 BKNG 29 The NASDAQ Stock Market LLC 3.000% Senior Notes Due 2030 BKNG 30 The NASDAQ Stock Market LLC 3.125% Senior Notes Due 2031 BKNG 31A The NASDAQ Stock Market LLC 4.500% Senior Notes Due 2031 BKNG 31 The NASDAQ Stock Market LLC 3.625% Senior Notes Due 2032 BKNG 32 The NASDAQ Stock Market LLC 3.250% Senior Notes Due 2032 BKNG 32A The NASDAQ Stock Market LLC 4.125% Senior Notes Due 2033 BKNG 33 The NASDAQ Stock Market LLC 4.750% Senior Notes Due 2034 BKNG 34 The NASDAQ Stock Market LLC 3.625% Senior Notes Due 2035 BKNG 35 The NASDAQ Stock Market LLC 3.750% Senior Notes Due 2036 BKNG 36 The NASDAQ Stock Market LLC 3.750% Senior Notes Due 2037 BKNG 37 The NASDAQ Stock Market LLC 4.125% Senior Notes Due 2038 BKNG 38 The NASDAQ Stock Market LLC 4.000% Senior Notes Due 2044 BKNG 44 The NASDAQ Stock Market LLC 3.875% Senior Notes Due 2045 BKNG 45 The NASDAQ Stock Market LLC 4.500% Senior Notes Due 2046 BKNG 46 The NASDAQ Stock Market LLC Indicate by check mark whether the registrant is an emerging growth company as defined in Rule 405 of the Securities Act of 1933 (§230.405 of this chapter) or Rule 12b-2 of the Securities Exchange Act of 1934 (§240.12b-2 of this chapter). Emerging growth company ☐ If an emerging growth company, indicate by check mark if the registrant has elected not to use the extended transition period for complying with any new or revised financial accounting standards provided pursuant to Section 13(a) of the Exchange Act. ☐ Item 5.02.    Departure of Directors or Certain Officers; Election of Directors; Appointment of Certain Officers; Compensatory Arrangements of Certain Officers. On April 2, 2026, Booking Holdings Inc. (the \"Company\") announced that it has appointed Caroline Sullivan as its Senior Vice President, Chief Accounting Officer, and Controller effective as of April 29, 2026. Ms. Sullivan, age 57, served as Vice President, Procurement and Real Estate of Elevance Health, a health insurance company, from June 2025 to March 2026. Prior to this, Ms. Sullivan was Senior Vice President, Chief Accounting Officer and Corporate Controller at Moody's Corporation, a global risk assessment firm, from December 2018 to March 2025. Ms. Sullivan also served as Global Banking Controller of Bank of America from 2017 to 2018. Earlier in her career, she held various finance positions with Morgan Stanley and Allied Irish Bank. Ms. Sullivan began her career at Ernst and Young and is a Certified Public Accountant. In connection with Ms. Sullivan's appointment, she and the Company entered into an employment agreement with, among others, the following terms: • an initial annual base salary of $525,000; • a target annual bonus of 75% of base salary; • a grant of restricted stock units (\"RSUs\") expected to be made in May 2026 with a grant date fair value of $1,000,000; • a grant of performance share units (\"PSUs\") expected to be made in March 2027 with a grant date fair value at target of $1,000,000; • a new hire grant of RSUs expected to be made in May 2026 with a grant date fair value of $1,000,000; • a signing bonus of $300,000; and • in the event of her termination without cause, subject to the execution of a release of claims, severance benefits including payments equal to one times her base salary and target annual bonus, a pro-rated portion of any earned bonus for the year of termination if employment is terminated after June 30 of the then current year, health benefits for a period of 12 months, and any earned bonus for a prior completed year that has not yet been paid. Ms. Sullivan's RSUs and new hire RSUs will each vest in three equal annual installments on each of the first three anniversaries of the grant date, subject to her continuous service from the date of grant until the vesting date, with pro rata vesting upon a termination without cause or due to disability, and full vesting upon a termination due to death. Ms. Sullivan's PSU award will vest subject to such service and performance-based vesting provisions generally consistent with those applicable to similarly-situated executives who receive PSU grants in 2027. The awards will be subject to the terms of the respective award agreements for awards under the Company’s 1999 Omnibus Plan. In connection with Ms. Sullivan's appointment, the Company and Ms. Sullivan have also entered into a Non-Competition and Non-Solicitation Agreement and an Employee Confidentiality and Assignment Agreement. SIGNATURES Pursuant to the requirements of the Securities Exchange Act of 1934, the Registrant has duly caused this report to be signed on its behalf by the undersigned hereunto duly authorized. BOOKING HOLDINGS INC. By: /s/ Ewout L. Steenbergen Name: Ewout L. Steenbergen Title: Executive Vice President and Chief Financial Officer Date:  April 2, 2026", "parsed_data": {}} +{"metadata": {"ticker": "BKNG", "form_type": "8-K", "filed_at": "2026-04-01T16:10:37-04:00", "accession_no": "0001075531-26-000012", "url": "https://www.sec.gov/Archives/edgar/data/1075531/000107553126000012/bkng-20260401.htm", "ingested_at": "2026-04-04T22:54:57.634231"}, "raw_text": "bkng-20260401 false 0001075531 0001075531 2026-04-01 2026-04-01 0001075531 us-gaap:CommonStockMember 2026-04-01 2026-04-01 0001075531 bkng:A4000SeniorNotesDue2026Member 2026-04-01 2026-04-01 0001075531 bkng:A1.8SeniorNotesDueMarch2027Member 2026-04-01 2026-04-01 0001075531 bkng:A05SeniorNotesDueMarch2028Member 2026-04-01 2026-04-01 0001075531 bkng:A3625SeniorNotesDue2028Member 2026-04-01 2026-04-01 0001075531 bkng:A3.500SeniorNotesDueMarch2029Member 2026-04-01 2026-04-01 0001075531 bkng:A4250SeniorNotesDue2029Member 2026-04-01 2026-04-01 0001075531 bkng:A3.0SeniorNotesDueNovember2030Member 2026-04-01 2026-04-01 0001075531 bkng:A3.125SeniorNotesDueMay2031Member 2026-04-01 2026-04-01 0001075531 bkng:A450SeniorNotesDue2031Member 2026-04-01 2026-04-01 0001075531 bkng:A3.625SeniorNotesDueMarch2032Member 2026-04-01 2026-04-01 0001075531 bkng:A3.250SeniorNotesDueNovember2032Member 2026-04-01 2026-04-01 0001075531 bkng:A4125SeniorNotesDue2033Member 2026-04-01 2026-04-01 0001075531 bkng:A4750SeniorNotesDue2034Member 2026-04-01 2026-04-01 0001075531 bkng:A3.625SeniorNotesDueNovember2035Member 2026-04-01 2026-04-01 0001075531 bkng:A3.750SeniorNotesDueMarch2036Member 2026-04-01 2026-04-01 0001075531 bkng:A3.750SeniorNotesDueNovember2037Member 2026-04-01 2026-04-01 0001075531 bkng:A4.125SeniorNotesDueMay2038Member 2026-04-01 2026-04-01 0001075531 bkng:A4.000SeniorNotesDueMarch2044Member 2026-04-01 2026-04-01 0001075531 bkng:A3.875SeniorNotesDueMarch2045Member 2026-04-01 2026-04-01 0001075531 bkng:A4.500SeniorNotesDueMay2046Member 2026-04-01 2026-04-01 UNITED STATES SECURITIES AND EXCHANGE COMMISSION Washington, D.C. 20549 FORM 8-K CURRENT REPORT Pursuant to Section 13 or 15(d) of the Securities Exchange Act of 1934 Date of Report (Date of earliest event reported) April 1, 2026 Booking Holdings Inc. (Exact name of registrant as specified in its charter) Delaware 1-36691 06-1528493 (State or other Jurisdiction of Incorporation) (Commission File Number) (IRS Employer Identification No.) 800 Connecticut Avenue Norwalk Connecticut 06854 (Address of principal executive offices) (zip code) Registrant's telephone number, including area code: ( 203 ) 299-8000 N/A (Former name or former address, if changed since last report) Check the appropriate box below if the Form 8-K filing is intended to simultaneously satisfy the filing obligation of the registrant under any of the following provisions: ☐ Written communications pursuant to Rule 425 under the Securities Act (17 CFR 230.425) ☐ Soliciting material pursuant to Rule 14a-12  under the Exchange Act (17 CFR 240.14a-12) ☐ Pre-commencement communications pursuant to Rule 14d-2(b) under the Exchange Act (17 CFR 240.14d-2(b)) ☐ Pre-commencement communications pursuant to Rule 13e-4(c) under the Exchange Act (17 CFR 240.13e-4(c)) Securities Registered Pursuant to Section 12(b) of the Act: Title of Each Class: Trading Symbol Name of Each Exchange on which Registered: Common Stock par value $0.008 per share BKNG The NASDAQ Global Select Market 4.000% Senior Notes Due 2026 BKNG 26 The NASDAQ Stock Market LLC 1.800% Senior Notes Due 2027 BKNG 27 The NASDAQ Stock Market LLC 0.500% Senior Notes Due 2028 BKNG 28 The NASDAQ Stock Market LLC 3.625% Senior Notes Due 2028 BKNG 28A The NASDAQ Stock Market LLC 3.500% Senior Notes Due 2029 BKNG 29A The NASDAQ Stock Market LLC 4.250% Senior Notes Due 2029 BKNG 29 The NASDAQ Stock Market LLC 3.000% Senior Notes Due 2030 BKNG 30 The NASDAQ Stock Market LLC 3.125% Senior Notes Due 2031 BKNG 31A The NASDAQ Stock Market LLC 4.500% Senior Notes Due 2031 BKNG 31 The NASDAQ Stock Market LLC 3.625% Senior Notes Due 2032 BKNG 32 The NASDAQ Stock Market LLC 3.250% Senior Notes Due 2032 BKNG 32A The NASDAQ Stock Market LLC 4.125% Senior Notes Due 2033 BKNG 33 The NASDAQ Stock Market LLC 4.750% Senior Notes Due 2034 BKNG 34 The NASDAQ Stock Market LLC 3.625% Senior Notes Due 2035 BKNG 35 The NASDAQ Stock Market LLC 3.750% Senior Notes Due 2036 BKNG 36 The NASDAQ Stock Market LLC 3.750% Senior Notes Due 2037 BKNG 37 The NASDAQ Stock Market LLC 4.125% Senior Notes Due 2038 BKNG 38 The NASDAQ Stock Market LLC 4.000% Senior Notes Due 2044 BKNG 44 The NASDAQ Stock Market LLC 3.875% Senior Notes Due 2045 BKNG 45 The NASDAQ Stock Market LLC 4.500% Senior Notes Due 2046 BKNG 46 The NASDAQ Stock Market LLC Indicate by check mark whether the registrant is an emerging growth company as defined in Rule 405 of the Securities Act of 1933 (§230.405 of this chapter) or Rule 12b-2 of the Securities Exchange Act of 1934 (§240.12b-2 of this chapter). Emerging growth company ☐ If an emerging growth company, indicate by check mark if the registrant has elected not to use the extended transition period for complying with any new or revised financial accounting standards provided pursuant to Section 13(a) of the Exchange Act. ☐ Item 5.02.    Departure of Directors or Certain Officers; Election of Directors; Appointment of Certain Officers; Compensatory Arrangements of Certain Officers. Appointment of Director On April 1, 2026, Mr. Kurt Sievers was appointed to the Board of Directors (the \"Board\") of Booking Holdings Inc. (the \"Company\") and will be joining the Board's Corporate Governance Committee. Mr. Sievers served as President and Chief Executive Officer of NXP Semiconductors N.V., a Netherlands-based semiconductor company (\"NXP\"), from 2020 until his retirement in 2025. He previously served as President beginning in 2018 and joined NXP’s Executive Management Team in 2009. Mr. Sievers currently serves on the board of directors of Capgemini SE, a multinational information technology services and consulting company, and is a member of its Strategy & CSR and Compensation Committees. He also serves on the supervisory board of Daimler Truck Holding AG, a commercial vehicle manufacturer. In consideration of his services as a member of the Company's Board and any Board committees, Mr. Sievers will be compensated in accordance with the Company's non-employee director compensation program as in effect from time to time. Retirement of Director Ms. Lynn Radakovich has informed the Company that she has decided to retire from the Board, effective at the Company's Annual Meeting in June 2026 (the \"Annual Meeting\"), and therefore is not standing for re-election at the Annual Meeting. The Company and the Board express their appreciation to Ms. Radakovich for her dedicated service. Item 7.01    Regulation FD Disclosure. A copy of the press release announcing Mr. Sievers's appointment and Ms. Radakovich's retirement is furnished with this Current Report as Exhibit 99.1. The information furnished herewith pursuant to this Item 7.01 of this Current Report shall not be deemed to be \"filed\" for purposes of Section 18 of the Securities Exchange Act of 1934, as amended (the \"Exchange Act\"), or otherwise subject to the liabilities of that section, and shall not be incorporated by reference into any registration statement or other document under the Securities Act of 1933, as amended, or the Exchange Act, except as shall be expressly set forth by specific reference in such filing. Item 9.01.           Financial Statements and Exhibits. (d)    Exhibits Exhibit Number Description 99.1 Press Release, dated April 1, 2026. 104 Cover Page Interactive Data File - the cover page interactive data file does not appear in the Interactive Data File because its XBRL tags are embedded within the Inline XBRL document. SIGNATURES Pursuant to the requirements of the Securities Exchange Act of 1934, the Registrant has duly caused this report to be signed on its behalf by the undersigned hereunto duly authorized. BOOKING HOLDINGS INC. By: /s/ Peter J. Millones Name: Peter J. Millones Title: Executive Vice President and General Counsel Date:  April 1, 2026", "parsed_data": {}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/CMCSA_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/CMCSA_2026-04-04.jsonl new file mode 100644 index 0000000..e601d52 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/CMCSA_2026-04-04.jsonl @@ -0,0 +1,6 @@ +{"metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-03T13:33:09-04:00", "accession_no": "0001225208-26-004342", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004342/xslF345X06/doc4.xml", "ingested_at": "2026-04-04T22:54:43.613356"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Murdock Daniel C.", "role": "EVP & Chief Accounting Officer", "transactions": [{"date": "2026-04-03", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 5268.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 64435.0497, "is_10b5_1_planned": false}, {"date": "2026-04-03", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 2073.0, "price": 27.93, "total_value": 57898.89, "post_transaction_shares": 62362.0497, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-02T16:27:31-04:00", "accession_no": "0001225208-26-004203", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004203/xslF345X06/doc4.xml", "ingested_at": "2026-04-04T22:54:44.188539"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Smith Gordon", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 1176.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 9045.0, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-02T16:26:30-04:00", "accession_no": "0001225208-26-004202", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004202/xslF345X06/doc4.xml", "ingested_at": "2026-04-04T22:54:44.751062"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Honickman Jeffrey A", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 1524.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 262583.021, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-02T16:25:30-04:00", "accession_no": "0001225208-26-004201", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004201/xslF345X06/doc4.xml", "ingested_at": "2026-04-04T22:54:45.317020"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "BREEN EDWARD D", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 697.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 56522.277, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-02T16:24:25-04:00", "accession_no": "0001225208-26-004200", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004200/xslF345X06/doc4.xml", "ingested_at": "2026-04-04T22:54:45.888239"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Brady Louise F.", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 1176.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 32682.89, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-02T16:23:19-04:00", "accession_no": "0001225208-26-004199", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004199/xslF345X06/doc4.xml", "ingested_at": "2026-04-04T22:54:46.458338"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Baltimore Thomas J Jr", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 1176.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 39043.493, "is_10b5_1_planned": false}]}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/COST_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/COST_2026-04-04.jsonl new file mode 100644 index 0000000..d576741 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/COST_2026-04-04.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "COST", "form_type": "4", "filed_at": "2026-04-01T18:13:26-04:00", "accession_no": "0000909832-26-000039", "url": "https://www.sec.gov/Archives/edgar/data/909832/000090983226000039/xslF345X06/form4.xml", "ingested_at": "2026-04-04T22:54:26.825658"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Frates Caton", "role": "Executive Vice President", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 700.0, "price": 993.0, "total_value": 695100.0, "post_transaction_shares": 5815.001, "is_10b5_1_planned": false}]}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/GOOG_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/GOOG_2026-04-04.jsonl new file mode 100644 index 0000000..17c75dd --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/GOOG_2026-04-04.jsonl @@ -0,0 +1,4 @@ +{"metadata": {"ticker": "GOOG", "form_type": "4", "filed_at": "2026-04-03T17:31:35-04:00", "accession_no": "0001193125-26-142372", "url": "https://www.sec.gov/Archives/edgar/data/1652044/000119312526142372/xslF345X06/ownership.xml", "ingested_at": "2026-04-04T22:54:21.748568"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "O'Toole Amie Thuener", "role": "VP, Chief Accounting Officer", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 617.0, "price": 289.63, "total_value": 178701.71, "post_transaction_shares": 10093.0, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "GOOG", "form_type": "8-K", "filed_at": "2026-04-02T16:18:28-04:00", "accession_no": "0001652044-26-000031", "url": "https://www.sec.gov/Archives/edgar/data/1652044/000165204426000031/goog-20260330.htm", "ingested_at": "2026-04-04T22:54:22.331849"}, "raw_text": "goog-20260330 FALSE 0001652044 0001652044 2026-03-30 2026-03-30 0001652044 us-gaap:CommonClassAMember 2026-03-30 2026-03-30 0001652044 goog:CapitalClassCMember 2026-03-30 2026-03-30 0001652044 goog:A2.375SeniorNotesDue2028Member 2026-03-30 2026-03-30 0001652044 goog:A2.500SeniorNotesDue2029Member 2026-03-30 2026-03-30 0001652044 goog:A4.125SeniorNotesDue2029Member 2026-03-30 2026-03-30 0001652044 goog:A2.875SeniorNotesDue2031Member 2026-03-30 2026-03-30 0001652044 goog:A4.625SeniorNotesDue2032Member 2026-03-30 2026-03-30 0001652044 goog:A3.000SeniorNotesDue2033Member 2026-03-30 2026-03-30 0001652044 goog:A3.125SeniorNotesDue2034Member 2026-03-30 2026-03-30 0001652044 goog:A3.375SeniorNotesDue2037Member 2026-03-30 2026-03-30 0001652044 goog:A3.500SeniorNotesDue2038Member 2026-03-30 2026-03-30 0001652044 goog:A5.500SeniorNotesDue2041Member 2026-03-30 2026-03-30 0001652044 goog:A4.000SeniorNotesDue2044Member 2026-03-30 2026-03-30 0001652044 goog:A3.875SeniorNotesDue2045Member 2026-03-30 2026-03-30 0001652044 goog:A4.000SeniorNotesDue2054Member 2026-03-30 2026-03-30 0001652044 goog:A5.875SeniorNotesDue2058Member 2026-03-30 2026-03-30 0001652044 goog:A4.375SeniorNotesDue2064Member 2026-03-30 2026-03-30 0001652044 goog:A6.125SeniorNotesDue2126Member 2026-03-30 2026-03-30 UNITED STATES SECURITIES AND EXCHANGE COMMISSION Washington, D.C. 20549 _________________________________________________ FORM 8-K _____________________________________________________________ CURRENT REPORT Pursuant to Section 13 or 15(d) of The Securities Exchange Act of 1934 Date of Report (Date of earliest event reported) March 30, 2026 ____________________________________________________________ ALPHABET INC. (Exact name of registrant as specified in its charter) _______________________________________________________________ Delaware 001-37580 61-1767919 (State or other jurisdiction of incorporation) (Commission File Number) (IRS Employer Identification No.) 1600 Amphitheatre Parkway Mountain View , CA 94043 (Address of principal executive offices, including zip code) ( 650 ) 253-0000 (Registrant’s telephone number, including area code) Not Applicable (Former name or former address, if changed since last report) ______________________________________________________________ Check the appropriate box below if the Form 8-K filing is intended to simultaneously satisfy the filing obligation of the registrant under any of the following provisions (see General Instruction A.2. below): ☐ Written communications pursuant to Rule 425 under the Securities Act (17 CFR 230.425) ☐ Soliciting material pursuant to Rule 14a-12 under the Exchange Act (17 CFR 240.14a-12) ☐ Pre-commencement communications pursuant to Rule 14d-2(b) under the Exchange Act (17 CFR 240.14d-2(b)) ☐ Pre-commencement communications pursuant to Rule 13e-4(c) under the Exchange Act (17 CFR 240.13e-4(c)) Securities registered pursuant to Section 12(b) of the Act: Title of each class Trading Symbol(s) Name of each exchange on which registered Class A Common Stock, $0.001 par value GOOGL Nasdaq Stock Market LLC (Nasdaq Global Select Market) Class C Capital Stock, $0.001 par value GOOG Nasdaq Stock Market LLC (Nasdaq Global Select Market) 2.375% Senior Notes due 2028 — Nasdaq Stock Market LLC 2.500% Senior Notes due 2029 — Nasdaq Stock Market LLC 4.125% Senior Notes due 2029 — Nasdaq Stock Market LLC 2.875% Senior Notes due 2031 — Nasdaq Stock Market LLC 4.625% Senior Notes due 2032 — Nasdaq Stock Market LLC 3.000% Senior Notes due 2033 — Nasdaq Stock Market LLC 3.125% Senior Notes due 2034 — Nasdaq Stock Market LLC 3.375% Senior Notes due 2037 — Nasdaq Stock Market LLC 3.500% Senior Notes due 2038 — Nasdaq Stock Market LLC 5.500% Senior Notes due 2041 — Nasdaq Stock Market LLC 4.000% Senior Notes due 2044 — Nasdaq Stock Market LLC 3.875% Senior Notes due 2045 — Nasdaq Stock Market LLC 4.000% Senior Notes due 2054 — Nasdaq Stock Market LLC 5.875% Senior Notes due 2058 — Nasdaq Stock Market LLC 4.375% Senior Notes due 2064 — Nasdaq Stock Market LLC 6.125% Senior Notes due 2126 — Nasdaq Stock Market LLC Indicate by check mark whether the registrant is an emerging growth company as defined in Rule 405 of the Securities Act of 1933 (§230.405 of this chapter) or Rule 12b-2 of the Securities Exchange Act of 1934 (§240.12b-2 of this chapter). Emerging growth company ☐ If an emerging growth company, indicate by check mark if the registrant has elected not to use the extended transition period for complying with any new or revised financial accounting standards provided pursuant to Section 13(a) of the Exchange Act. ☐ Item 5.02 Departure of Directors or Certain Officers; Election of Directors; Appointment of Certain Officers; Compensatory Arrangements of Certain Officers. On March 30, 2026, Amie Thuener O'Toole notified Alphabet Inc. (the “Company”) of her resignation as Vice President, Corporate Controller and Principal Accounting Officer of the Company, effective April 9, 2026, to pursue another professional opportunity. Ms. O'Toole’s decision to resign did not result from any disagreement with the Company on any matter relating to the Company’s operations, policies, or practices. SIGNATURE Pursuant to the requirements of the Securities Exchange Act of 1934, the registrant has duly caused this report to be signed on its behalf by the undersigned hereunto duly authorized. ALPHABET INC. Date: April 2, 2026 /s/ KATHRYN W. HALL Kathryn W. Hall Assistant Secretary", "parsed_data": {}} +{"metadata": {"ticker": "GOOG", "form_type": "4", "filed_at": "2026-03-31T21:43:02-04:00", "accession_no": "0001193125-26-135334", "url": "https://www.sec.gov/Archives/edgar/data/1238734/000119312526135334/xslF345X06/ownership.xml", "ingested_at": "2026-04-04T22:54:22.903382"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "WALKER JOHN KENT", "role": "President, Global Affairs, CLO", "transactions": [{"date": "2026-03-27", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 2677.0, "price": 273.91, "total_value": 733257.0700000001, "post_transaction_shares": 58124.0, "is_10b5_1_planned": false}, {"date": "2026-03-27", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1516.0, "price": 274.93, "total_value": 416793.88, "post_transaction_shares": 56608.0, "is_10b5_1_planned": false}, {"date": "2026-03-27", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1400.0, "price": 276.21, "total_value": 386694.0, "post_transaction_shares": 55208.0, "is_10b5_1_planned": false}, {"date": "2026-03-27", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 2100.0, "price": 277.42, "total_value": 582582.0, "post_transaction_shares": 53108.0, "is_10b5_1_planned": false}, {"date": "2026-03-27", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1300.0, "price": 278.3, "total_value": 361790.0, "post_transaction_shares": 51808.0, "is_10b5_1_planned": false}, {"date": "2026-03-31", "code": "G", "direction": "OTHER (D)", "shares": 8993.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 23508.0, "is_10b5_1_planned": false}, {"date": "2026-03-31", "code": "G", "direction": "OTHER (A)", "shares": 8993.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 60801.0, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "GOOG", "form_type": "4", "filed_at": "2026-03-31T20:39:05-04:00", "accession_no": "0001193125-26-135258", "url": "https://www.sec.gov/Archives/edgar/data/1652044/000119312526135258/xslF345X06/ownership.xml", "ingested_at": "2026-04-04T22:54:23.480449"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "ARNOLD FRANCES", "role": "Director", "transactions": [{"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 102.0, "price": 275.19, "total_value": 28069.38, "post_transaction_shares": 18316.0, "is_10b5_1_planned": false}]}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/HON_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/HON_2026-04-04.jsonl new file mode 100644 index 0000000..00baeb1 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/HON_2026-04-04.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "HON", "form_type": "4", "filed_at": "2026-04-02T17:57:33-04:00", "accession_no": "0000773840-26-000025", "url": "https://www.sec.gov/Archives/edgar/data/773840/000077384026000025/xslF345X06/wk-form4_1775167050.xml", "ingested_at": "2026-04-04T22:54:42.309982"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Flint Deborah", "role": "Other", "transactions": []}} +{"metadata": {"ticker": "HON", "form_type": "4", "filed_at": "2026-04-02T17:56:37-04:00", "accession_no": "0000773840-26-000024", "url": "https://www.sec.gov/Archives/edgar/data/773840/000077384026000024/xslF345X06/wk-form4_1775166995.xml", "ingested_at": "2026-04-04T22:54:42.895683"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "ANGOVE DUNCAN", "role": "Other", "transactions": []}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/IBM_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/IBM_2026-04-04.jsonl new file mode 100644 index 0000000..7ffbd9f --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/IBM_2026-04-04.jsonl @@ -0,0 +1,13 @@ +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01T17:11:35-04:00", "accession_no": "0001630253-26-000003", "url": "https://www.sec.gov/Archives/edgar/data/51143/000163025326000003/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-04T22:54:48.742964"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Laguarta Ramon", "role": "Director", "transactions": []}} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01T17:10:34-04:00", "accession_no": "0001804183-26-000004", "url": "https://www.sec.gov/Archives/edgar/data/51143/000180418326000004/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-04T22:54:49.319678"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Brown Marianne Catherine", "role": "Director", "transactions": []}} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01T17:09:51-04:00", "accession_no": "0001738987-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/51143/000173898726000002/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-04T22:54:49.890485"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Buberl Thomas", "role": "Director", "transactions": []}} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01T17:09:00-04:00", "accession_no": "0001183474-26-000003", "url": "https://www.sec.gov/Archives/edgar/data/51143/000118347426000003/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-04T22:54:50.474380"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "FARR DAVID N", "role": "Director", "transactions": []}} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01T17:08:11-04:00", "accession_no": "0001453149-26-000006", "url": "https://www.sec.gov/Archives/edgar/data/51143/000145314926000006/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-04T22:54:51.046789"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Gorsky Alex", "role": "Director", "transactions": []}} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01T17:05:39-04:00", "accession_no": "0001769389-26-000003", "url": "https://www.sec.gov/Archives/edgar/data/51143/000176938926000003/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-04T22:54:51.631365"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "HOWARD MICHELLE J", "role": "Director", "transactions": []}} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01T17:04:56-04:00", "accession_no": "0001269971-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/51143/000126997126000002/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-04T22:54:52.223698"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "LIVERIS ANDREW N", "role": "Director", "transactions": []}} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01T17:04:16-04:00", "accession_no": "0001731814-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/51143/000173181426000002/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-04T22:54:52.813351"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "MCNABB FREDERICK WILLIAM III", "role": "Director", "transactions": []}} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01T17:03:36-04:00", "accession_no": "0001771933-26-000005", "url": "https://www.sec.gov/Archives/edgar/data/51143/000177193326000005/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-04T22:54:53.392704"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Miebach Michael", "role": "Director", "transactions": []}} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01T17:02:53-04:00", "accession_no": "0001628797-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/51143/000162879726000002/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-04T22:54:53.968188"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "VOSER PETER R.", "role": "Director", "transactions": []}} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01T17:02:18-04:00", "accession_no": "0001223690-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/51143/000122369026000002/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-04T22:54:54.572877"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "WADDELL FREDERICK H", "role": "Director", "transactions": []}} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01T17:01:34-04:00", "accession_no": "0001196985-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/51143/000119698526000002/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-04T22:54:55.150928"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "ZOLLAR ALFRED W", "role": "Director", "transactions": []}} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01T17:00:51-04:00", "accession_no": "0001765271-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/51143/000176527126000002/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-04T22:54:55.747804"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Pollack Martha E", "role": "Director", "transactions": []}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/INTC_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/INTC_2026-04-04.jsonl new file mode 100644 index 0000000..45e0490 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/INTC_2026-04-04.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "INTC", "form_type": "8-K", "filed_at": "2026-04-03T12:50:37-04:00", "accession_no": "0000050863-26-000069", "url": "https://www.sec.gov/Archives/edgar/data/50863/000005086326000069/intc-20260330.htm", "ingested_at": "2026-04-04T22:54:47.308119"}, "raw_text": "intc-20260330 0000050863 false 0000050863 2026-03-30 2026-04-03 UNITED STATES SECURITIES AND EXCHANGE COMMISSION Washington, D.C. 20549 FORM 8-K CURRENT REPORT Pursuant to Section 13 or 15(d) of the Securities Exchange Act of 1934 Date of Report (Date of earliest event reported): March 30, 2026 INTEL CORPORATION (Exact name of registrant as specified in its charter) Delaware 000-06217 94-1672743 (State or other jurisdiction (Commission (IRS Employer of incorporation) File Number) Identification No.) 2200 Mission College Boulevard , Santa Clara , California 95054-1549 (Address of principal executive offices) (Zip Code) Registrant's telephone number, including area code: (408) 765-8080 Not Applicable (Former name or former address, if changed since last report) Check the appropriate box below if the Form 8-K filing is intended to simultaneously satisfy the filing obligation of the registrant under any of the following provisions ( see General Instruction A.2. below): ☐ Written communications pursuant to Rule 425 under the Securities Act (17 CFR 230.425) ☐ Soliciting material pursuant to Rule 14a-12 under the Exchange Act (17 CFR 240.14a-12) ☐ Pre-commencement communications pursuant to Rule 14d-2(b) under the Exchange Act (17 CFR 240.14d-2(b)) ☐ Pre-commencement communications pursuant to Rule 13e-4(c) under the Exchange Act (17 CFR 240.13e-4c)) Securities registered pursuant to Section 12(b) of the Act: Title of each class Trading Symbol(s) Name of each exchange on which registered Common stock, $0.001 par value INTC Nasdaq Global Select Market Indicate by check mark whether the registrant is an emerging growth company as defined in Rule 405 of the Securities Act of 1933 (§230.405 of this chapter) or Rule 12b-2 of the Securities Exchange Act of 1934 (§240.12b-2 of this chapter). Emerging growth company ☐ If an emerging growth company, indicate by check mark if the registrant has elected not to use the extended transition period for complying with any new or revised financial accounting standards provided pursuant to Section 13(a) of the Exchange Act. ¨ Item 5.02    Departure of Directors or Certain Officers; Election of Directors; Appointment of Certain Officers; Compensatory Arrangements of Certain Officers. On March 30,2026, Intel Corporation determined that April Miller Boise, Intel’s Executive Vice President and Chief Legal Officer, will separate from Intel effective as of June 1, 2026. Upon her departure on June 1, 2026, Ms. Miller Boise will be entitled to severance benefits in accordance with the terms and conditions of the Intel Corporation Executive Severance Plan, as previously disclosed, in exchange for a release of claims in favor of Intel. Item 9.01 Financial Statements and Exhibits. (d) Exhibits. The following exhibits are provided as part of this report: Exhibit Number Description 104 Cover Page Interactive Data File, formatted in Inline XBRL and included as Exhibit 101. SIGNATURES Pursuant to the requirements of the Securities Exchange Act of 1934, the registrant has duly caused this report to be signed on its behalf by the undersigned hereunto duly authorized. INTEL CORPORATION (Registrant) Date: April 3, 2026 By: /s/ David Zinsner David Zinsner Executive Vice President and Chief Financial Officer", "parsed_data": {}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/INTU_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/INTU_2026-04-04.jsonl new file mode 100644 index 0000000..5b4b609 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/INTU_2026-04-04.jsonl @@ -0,0 +1,6 @@ +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03T16:51:34-04:00", "accession_no": "0001628280-26-023706", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023706/xslF345X06/wk-form4_1775249487.xml", "ingested_at": "2026-04-04T22:54:38.419929"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Goodarzi Sasan K", "role": "CEO, President and Director", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 653.529, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 14264.957, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 893.612, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 15158.569, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 802.006, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 15960.575, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 863.013, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 16823.588, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 30.832, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 16854.42, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 1277.861, "price": 432.38, "total_value": 552521.5391800001, "post_transaction_shares": 15576.559, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03T16:50:20-04:00", "accession_no": "0001628280-26-023704", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023704/xslF345X06/wk-form4_1775249417.xml", "ingested_at": "2026-04-04T22:54:39.027084"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "McLean Kerry J", "role": "EVP, Gen. Counsel & Corp. Sec.", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 244.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 28657.7666, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 236.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 28893.7666, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 199.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 29092.7666, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 170.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 29262.7666, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 301.627, "price": 432.38, "total_value": 130417.48226, "post_transaction_shares": 28961.1396, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03T16:48:01-04:00", "accession_no": "0001628280-26-023701", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023701/xslF345X06/wk-form4_1775249278.xml", "ingested_at": "2026-04-04T22:54:39.614244"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Hotz Lauren D", "role": "SVP, Chief Accounting Officer", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 41.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 2055.7352, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 104.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 2159.7352, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 97.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 2256.7352, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 88.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 2344.7352, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 120.548, "price": 432.38, "total_value": 52122.54424, "post_transaction_shares": 2224.1872, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03T16:46:29-04:00", "accession_no": "0001628280-26-023698", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023698/xslF345X06/wk-form4_1775249186.xml", "ingested_at": "2026-04-04T22:54:40.203764"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Hilliard Caryl Lyn", "role": "EVP, People and Places", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 122.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 23018.008, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 110.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 23128.008, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 87.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 23215.008, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 150.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 23365.008, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 212.093, "price": 432.38, "total_value": 91704.77133999999, "post_transaction_shares": 23152.915, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03T16:45:28-04:00", "accession_no": "0001628280-26-023696", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023696/xslF345X06/wk-form4_1775249122.xml", "ingested_at": "2026-04-04T22:54:40.778129"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Hanebrink Anton", "role": "EVP, Corp Strategy and Dev", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 348.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 29953.249, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 252.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 30205.249, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 224.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 30429.249, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 418.253, "price": 432.38, "total_value": 180844.23213999998, "post_transaction_shares": 30010.996, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03T16:39:06-04:00", "accession_no": "0001628280-26-023690", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023690/xslF345X06/wk-form4_1775248743.xml", "ingested_at": "2026-04-04T22:54:41.363317"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Aujla Sandeep", "role": "EVP and CFO", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 2665.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 3239.1366, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 346.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 3585.1366, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 349.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 3934.1366, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 1725.362, "price": 432.38, "total_value": 746012.02156, "post_transaction_shares": 2208.7746, "is_10b5_1_planned": false}]}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/MDLZ_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/MDLZ_2026-04-04.jsonl new file mode 100644 index 0000000..e69de29 diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/NFLX_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/NFLX_2026-04-04.jsonl new file mode 100644 index 0000000..b5751c8 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/NFLX_2026-04-04.jsonl @@ -0,0 +1,13 @@ +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-03T16:07:32-04:00", "accession_no": "0001543133-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000154313326000002/xslF345X06/wk-form4_1775246849.xml", "ingested_at": "2026-04-04T22:54:27.690770"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Neumann Spencer Adam", "role": "Chief Financial Officer", "transactions": [{"date": "2026-04-02", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 7770.0, "price": 38.105, "total_value": 296075.85, "post_transaction_shares": 81557.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 20860.0, "price": 36.408, "total_value": 759470.88, "post_transaction_shares": 102417.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 28630.0, "price": 98.0, "total_value": 2805740.0, "post_transaction_shares": 73787.0, "is_10b5_1_planned": true}]}} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02T18:02:54-04:00", "accession_no": "0001065280-26-000136", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000136/xslF345X06/wk-form4_1775167371.xml", "ingested_at": "2026-04-04T22:54:28.265373"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "KILGORE LESLIE J", "role": "Other", "transactions": []}} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02T18:02:46-04:00", "accession_no": "0001065280-26-000135", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000135/xslF345X06/wk-form4_1775167364.xml", "ingested_at": "2026-04-04T22:54:28.839154"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Masiyiwa Strive", "role": "Other", "transactions": []}} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02T18:02:38-04:00", "accession_no": "0001065280-26-000134", "url": "https://www.sec.gov/Archives/edgar/data/1033331/000106528026000134/xslF345X06/wk-form4_1775167354.xml", "ingested_at": "2026-04-04T22:54:29.443415"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "HASTINGS REED", "role": "Other", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 420550.0, "price": 9.437, "total_value": 3968730.3499999996, "post_transaction_shares": 424490.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 152047.0, "price": 95.015, "total_value": 14446745.705, "post_transaction_shares": 272443.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 247923.0, "price": 95.6767, "total_value": 23720454.4941, "post_transaction_shares": 24520.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 20580.0, "price": 96.6601, "total_value": 1989264.858, "post_transaction_shares": 3940.0, "is_10b5_1_planned": true}]}} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02T18:02:28-04:00", "accession_no": "0001065280-26-000133", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000133/xslF345X06/wk-form4_1775167345.xml", "ingested_at": "2026-04-04T22:54:30.038969"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Sweeney Anne M", "role": "Other", "transactions": []}} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02T18:02:20-04:00", "accession_no": "0001065280-26-000132", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000132/xslF345X06/wk-form4_1775167337.xml", "ingested_at": "2026-04-04T22:54:30.617313"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "MATHER ANN", "role": "Other", "transactions": []}} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02T18:01:52-04:00", "accession_no": "0001065280-26-000131", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000131/xslF345X06/wk-form4_1775167309.xml", "ingested_at": "2026-04-04T22:54:31.210332"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Dopfner Mathias", "role": "Other", "transactions": []}} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02T18:01:44-04:00", "accession_no": "0001065280-26-000130", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000130/xslF345X06/wk-form4_1775167302.xml", "ingested_at": "2026-04-04T22:54:31.787519"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Karbowski Jeffrey William", "role": "Chief Accounting Officer", "transactions": []}} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02T18:01:36-04:00", "accession_no": "0001065280-26-000129", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000129/xslF345X06/wk-form4_1775167293.xml", "ingested_at": "2026-04-04T22:54:32.363920"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "SMITH BRADFORD L", "role": "Other", "transactions": []}} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02T18:01:30-04:00", "accession_no": "0001065280-26-000128", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000128/xslF345X06/wk-form4_1775167286.xml", "ingested_at": "2026-04-04T22:54:32.939871"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "RICE SUSAN E", "role": "Other", "transactions": []}} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02T18:01:23-04:00", "accession_no": "0001065280-26-000127", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000127/xslF345X06/wk-form4_1775167280.xml", "ingested_at": "2026-04-04T22:54:33.516613"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "BARTON RICHARD N", "role": "Other", "transactions": []}} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02T18:01:07-04:00", "accession_no": "0001065280-26-000126", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000126/xslF345X06/wk-form4_1775167264.xml", "ingested_at": "2026-04-04T22:54:34.100797"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Mertz Elinor", "role": "Other", "transactions": []}} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02T16:04:17-04:00", "accession_no": "0001082906-26-000012", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000108290626000012/xslF345X06/form4.xml", "ingested_at": "2026-04-04T22:54:34.673370"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Hoag Jay C", "role": "Other", "transactions": []}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/PANW_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/PANW_2026-04-04.jsonl new file mode 100644 index 0000000..df6ee38 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/PANW_2026-04-04.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "PANW", "form_type": "4", "filed_at": "2026-04-03T16:30:29-04:00", "accession_no": "0001882285-26-000007", "url": "https://www.sec.gov/Archives/edgar/data/1327567/000188228526000007/xslF345X06/ownership.xml", "ingested_at": "2026-04-04T22:55:01.436892"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Paul Josh D.", "role": "Chief Accounting Officer", "transactions": [{"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 947.0, "price": 160.32, "total_value": 151823.03999999998, "post_transaction_shares": 84236.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1100.0, "price": 161.4, "total_value": 177540.0, "post_transaction_shares": 83136.0, "is_10b5_1_planned": true}]}} +{"metadata": {"ticker": "PANW", "form_type": "4", "filed_at": "2026-04-03T16:30:26-04:00", "accession_no": "0001852540-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/1327567/000185254026000002/xslF345X06/ownership.xml", "ingested_at": "2026-04-04T22:55:02.015659"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Golechha Dipak", "role": "EVP, Chief Financial Officer", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 200.0, "price": 157.81, "total_value": 31562.0, "post_transaction_shares": 155050.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1300.0, "price": 160.039, "total_value": 208050.69999999998, "post_transaction_shares": 153750.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 3500.0, "price": 160.704, "total_value": 562464.0, "post_transaction_shares": 150250.0, "is_10b5_1_planned": true}]}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/QCOM_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/QCOM_2026-04-04.jsonl new file mode 100644 index 0000000..139e887 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/QCOM_2026-04-04.jsonl @@ -0,0 +1,3 @@ +{"metadata": {"ticker": "QCOM", "form_type": "4", "filed_at": "2026-04-02T17:23:11-04:00", "accession_no": "0000804328-26-000051", "url": "https://www.sec.gov/Archives/edgar/data/804328/000080432826000051/xslF345X06/edgardoc.xml", "ingested_at": "2026-04-04T22:54:36.438677"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Grech Patricia Y", "role": "SVP, Chief Accounting Officer", "transactions": [{"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 85.0, "price": 125.5, "total_value": 10667.5, "post_transaction_shares": 192.0, "is_10b5_1_planned": true}]}} +{"metadata": {"ticker": "QCOM", "form_type": "4", "filed_at": "2026-04-02T16:08:27-04:00", "accession_no": "0000804328-26-000049", "url": "https://www.sec.gov/Archives/edgar/data/804328/000080432826000049/xslF345X06/edgardoc.xml", "ingested_at": "2026-04-04T22:54:37.033688"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "MCLAUGHLIN MARK D", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 538.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 12849.8312, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "QCOM", "form_type": "4", "filed_at": "2026-04-02T16:08:15-04:00", "accession_no": "0000804328-26-000048", "url": "https://www.sec.gov/Archives/edgar/data/804328/000080432826000048/xslF345X06/edgardoc.xml", "ingested_at": "2026-04-04T22:54:37.607779"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "TRICOIRE JEAN-PASCAL", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 262.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 13481.4716, "is_10b5_1_planned": false}]}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/SBUX_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/SBUX_2026-04-04.jsonl new file mode 100644 index 0000000..093f5a6 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/SBUX_2026-04-04.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "SBUX", "form_type": "8-K", "filed_at": "2026-04-02T16:55:33-04:00", "accession_no": "0000829224-26-000064", "url": "https://www.sec.gov/Archives/edgar/data/829224/000082922426000064/sbux-20260402.htm", "ingested_at": "2026-04-04T22:55:00.161523"}, "raw_text": "sbux-20260402 false 0000829224 0000829224 2026-04-02 2026-04-02 UNITED STATES SECURITIES AND EXCHANGE COMMISSION Washington, DC 20549 FORM 8-K CURRENT REPORT Pursuant to Section 13 or 15(d) of the Securities Exchange Act of 1934 Date of Report (Date of earliest event reported): April 2, 2026 Starbucks Corporation (Exact name of registrant as specified in its charter) Washington 000-20322 91-1325671 (State or other jurisdiction of incorporation) (Commission File Number) (IRS Employer Identification No.) 2401 Utah Avenue South , Seattle , Washington 98134 (Address of principal executive offices) (Zip Code) ( 206 ) 447-1575 (Registrant's telephone number, including area code) Check the appropriate box below if the Form 8-K filing is intended to simultaneously satisfy the filing obligation of the registrant under any of the following provisions: ☐ Written communications pursuant to Rule 425 under the Securities Act (17 CFR 230.425) ☐ Soliciting material pursuant to Rule 14a-12 under the Exchange Act (17 CFR 240.14a-12) ☐ Pre-commencement communications pursuant to Rule 14d-2(b) under the Exchange Act (17 CFR 240.14d-2(b)) ☐ Pre-commencement communications pursuant to Rule 13e-4(c) under the Exchange Act (17 CFR 240.13e-4(c)) Securities registered pursuant to Section 12(b) of the Act: Title Trading Symbol Name of each exchange on which registered Common Stock, par value $0.001 per share SBUX Nasdaq Global Select Market Indicate by check mark whether the registrant is an emerging growth company as defined in Rule 405 of the Securities Act of 1933 (§230.405 of this chapter) or Rule 12b-2 of the Securities Exchange Act of 1934 (§240.12b-2 of this chapter). Emerging Growth Company ☐ If an emerging growth company, indicate by check mark if the registrant has elected not to use the extended transition period for complying with any new or revised financial accounting standards provided pursuant to Section 13(a) of the Exchange Act. o Item 7.01    Regulation FD Disclosure. As previously disclosed on November 3, 2025, Starbucks entered an agreement to form a joint venture with Boyu Capital. On April 2, 2026, Starbucks announced that, following the satisfaction of all necessary closing conditions, it completed the transaction. Pursuant to the transaction, funds managed by Boyu Capital have acquired a 60% interest in Starbucks retail operations in China. Starbucks retains a 40% interest and will serve as the owner and licensor of the Starbucks global brand. A copy of the press release issued is furnished as Exhibit 99.1 to this Form 8-K. The information contained in Item 7.01 of this report, including the information in Exhibit 99.1, is furnished pursuant to Item 7.01 of Form 8-K and shall not be deemed “filed” for the purposes of Section 18 of the Securities Exchange Act of 1934, as amended, or otherwise subject to the liabilities of that section. Furthermore, the information in Item 7.01 of this report, including the information in Exhibit 99.1 attached to this report, shall not be deemed to be incorporated by reference in the filings of Starbucks Corporation under the Securities Act of 1933, as amended. Item 9.01 Financial Statements and Exhibits. (d) Exhibits. Exhibit No. Description 99.1 Press Release, dated April 2, 2026 104 Cover Page Interactive Data File (formatted as inline XBRL) SIGNATURES Pursuant to the requirements of the Securities Exchange Act of 1934, the registrant has duly caused this report to be signed on its behalf by the undersigned hereunto duly authorized. STARBUCKS CORPORATION Dated: April 2, 2026 By: /s/ Joshua C. Gaul Joshua C. Gaul vice president, assistant general counsel and corporate secretary", "parsed_data": {}} +{"metadata": {"ticker": "SBUX", "form_type": "8-K", "filed_at": "2026-03-30T09:15:22-04:00", "accession_no": "0000829224-26-000058", "url": "https://www.sec.gov/Archives/edgar/data/829224/000082922426000058/sbux-20260325.htm", "ingested_at": "2026-04-04T22:55:00.764230"}, "raw_text": "sbux-20260325 false 0000829224 0000829224 2026-03-25 2026-03-25 UNITED STATES SECURITIES AND EXCHANGE COMMISSION Washington, D.C. 20549 FORM 8-K CURRENT REPORT Pursuant to Section 13 OR 15(d) of The Securities Exchange Act of 1934 Date of Report (Date of earliest event reported): March 25, 2026 Starbucks Corporation (Exact name of registrant as specified in its charter) Washington 000-20322 91-1325671 (State or other jurisdiction of incorporation) (Commission File Number) (IRS Employer Identification No.) 2401 Utah Avenue South , Seattle , Washington 98134 (Address of principal executive offices) (Zip Code) ( 206 ) 447-1575 ( Registrant’s telephone number, including area code) Check the appropriate box below if the Form 8-K filing is intended to simultaneously satisfy the filing obligation of the registrant under any of the following provisions: ☐ Written communications pursuant to Rule 425 under the Securities Act (17 CFR 230.425) ☐ Soliciting material pursuant to Rule 14a-12 under the Exchange Act (17 CFR 240.14a-12) ☐ Pre-commencement communications pursuant to Rule 14d-2(b) under the Exchange Act (17 CFR 240.14d-2(b)) ☐ Pre-commencement communications pursuant to Rule 13e-4(c) under the Exchange Act (17 CFR 240.13e-4(c)) Securities registered pursuant to Section 12(b) of the Act: Title Trading Symbol Name of each exchange on which registered Common Stock, par value $0.001 per share SBUX Nasdaq Global Select Market Indicate by check mark whether the registrant is an emerging growth company as defined in Rule 405 of the Securities Act of 1933 (§230.405 of this chapter) or Rule 12b-2 of the Securities Exchange Act of 1934 (§240.12b-2 of this chapter). Emerging Growth Company ☐ If an emerging growth company, indicate by check mark if the registrant has elected not to use the extended transition period for complying with any new or revised financial accounting standards provided pursuant to Selection 13(a) of the Exchange Act. ☐ Item 5.07 Submission of Matters to a Vote of Security Holders. On March 25, 2026, Starbucks Corporation (the “Company”) held its 2026 Annual Meeting of Shareholders (the “Annual Meeting”). The matters submitted to a vote at the Annual Meeting and the voting results of such matters are as follows: Proposal 1 - Election of Directors The Company’s shareholders elected each of the eleven directors nominated by the Company’s Board of Directors to serve until the 2027 Annual Meeting of Shareholders or until their successors are duly elected and qualified. The following is a breakdown of the voting results: Name of Nominee For Against Withheld Broker Non-Votes Ritch Allison 846,955,724 28,832,837 1,081,482 127,972,619 Andy Campion 764,749,951 110,976,652 1,143,440 127,972,619 Beth Ford 808,145,942 66,979,908 1,744,193 127,972,619 Jørgen Vig Knudstorp 828,586,462 46,185,327 2,098,254 127,972,619 Marissa Mayer 867,967,230 7,925,365 977,448 127,972,619 Neal Mohan 865,313,815 10,401,952 1,154,276 127,972,619 Dambisa Moyo 864,744,438 11,015,863 1,109,742 127,972,619 Brian Niccol 830,353,482 43,094,658 3,421,903 127,972,619 Daniel Servitje 841,710,171 33,992,034 1,167,838 127,972,619 Mike Sievert 863,809,451 11,894,524 1,166,068 127,972,619 Wei Zhang 855,876,306 19,854,913 1,138,824 127,972,619 Proposal 2 - Advisory Resolution on Executive Compensation At the Annual Meeting, the shareholders approved, on a nonbinding, advisory basis, the compensation paid to the Company’s named executive officers. The following is a breakdown of the voting results: For Against Abstain Broker Non-Votes 774,932,476 99,362,557 2,575,010 127,972,619 Proposal 3 - Ratification of the Selection of Deloitte & Touche LLP as the Company’s Independent Registered Public Accounting Firm for Fiscal Year 2026 At the Annual Meeting, the shareholders approved the ratification of the selection of Deloitte & Touche LLP as the Company’s independent registered public accounting firm for the fiscal year ending September 27, 2026. The following is a breakdown of the voting results: For Against Abstain Broker Non-Votes 965,325,253 38,304,225 1,213,184 —— Proposal 4 - Shareholder Proposal Requesting Supermajority Shareholder Voting Requirements be Replaced with Majority Voting Requirements At the Annual Meeting, the shareholders approved a shareholder proposal requesting supermajority shareholder voting requirements be replaced with majority voting requirements. The following is a breakdown of the voting results: For Against Abstain Broker Non-Votes 823,985,324 17,573,051 30,866,556 132,323,108 Proposal 5 - Shareholder Proposal Requesting Adoption of an Independent Board Chair Policy At the Annual Meeting, the shareholders did not approve a shareholder proposal requesting adoption of an independent board chair policy. The following is a breakdown of the voting results: For Against Abstain Broker Non-Votes 107,793,749 763,797,502 5,278,792 127,972,619 Proposal 6 - Shareholder Proposal Requesting a Report on the Company’s Apparent Exclusion of Detransitioning in its Healthcare Coverage At the Annual Meeting, the shareholders did not approve a shareholder proposal requesting a report on the Company’s apparent exclusion of detransitioning in its healthcare coverage. The following is a breakdown of the voting results: For Against Abstain Broker Non-Votes 8,169,593 861,170,343 7,530,107 127,972,619 Proposal 7 - Shareholder Proposal Requesting a Report on Median Compensation and Benefits Gaps as They Address Reproductive and Gender Dysphoria Care At the Annual Meeting, the shareholders did not approve a shareholder proposal requesting a report on median compensation and benefits gaps as they address reproductive and gender dysphoria care. The following is a breakdown of the voting results: For Against Abstain Broker Non-Votes 5,153,879 864,501,617 7,214,547 127,972,619 Proposal 8 - Shareholder Proposal Requesting a Report on the Company’s Use of Diagnostic Tools Created by Politicized Corporate Partners At the Annual Meeting, the shareholders did not approve a shareholder proposal requesting a report on the Company’s use of diagnostic tools created by politicized corporate partners. The following is a breakdown of the voting results: For Against Abstain Broker Non-Votes 6,335,450 863,459,994 7,074,599 127,972,619 Proposal 9 - Shareholder Proposal Requesting a Report on the Risks of the Company Excluding Religious Charities from its Employee-Gift Match Program At the Annual Meeting, the shareholders did not approve a shareholder proposal requesting a report on the risks of the Company excluding religious charities from its employee-gift match program. The following is a breakdown of the voting results: For Against Abstain Broker Non-Votes 5,749,240 864,268,337 6,852,466 127,972,619 The above proposals are further described in the Company’s definitive proxy statement on Schedule 14A filed with the U.S. Securities and Exchange Commission on January 26, 2026. SIGNATURES Pursuant to the requirements of the Securities Exchange Act of 1934, the registrant has duly caused this report to be signed on its behalf by the undersigned hereunto duly authorized. STARBUCKS CORPORATION Dated: March 30, 2026 By: /s/ Joshua C. Gaul Joshua C. Gaul vice president, assistant general counsel and corporate secretary", "parsed_data": {}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/TMUS_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/TMUS_2026-04-04.jsonl new file mode 100644 index 0000000..1b3c85d --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/TMUS_2026-04-04.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "TMUS", "form_type": "8-K", "filed_at": "2026-03-31T16:35:02-04:00", "accession_no": "0001193125-26-134731", "url": "https://www.sec.gov/Archives/edgar/data/1283699/000119312526134731/d136365d8k.htm", "ingested_at": "2026-04-04T22:54:35.624295"}, "raw_text": "8-K false 0001283699 0001283699 2026-03-31 2026-03-31 0001283699 tmus:CommonStockParValue0.00001PerShareMember 2026-03-31 2026-03-31 0001283699 tmus:A3.550SeniorNotesDue2029Member 2026-03-31 2026-03-31 0001283699 tmus:M3.700SeniorNotesDue20323Member 2026-03-31 2026-03-31 0001283699 tmus:M3.150SeniorNotesDue20321Member 2026-03-31 2026-03-31 0001283699 tmus:M3.200SeniorNotesDue20322Member 2026-03-31 2026-03-31 0001283699 tmus:M3.625SeniorNotesDue20357Member 2026-03-31 2026-03-31 0001283699 tmus:M3.850SeniorNotesDue20364Member 2026-03-31 2026-03-31 0001283699 tmus:M3.900SeniorNotesDue20385Member 2026-03-31 2026-03-31 0001283699 tmus:A3.500SeniorNotesDue2037Member 2026-03-31 2026-03-31 0001283699 tmus:A3.800SeniorNotesDue2045Member 2026-03-31 2026-03-31 0001283699 tmus:M6.250SeniorNotesDue20696Member 2026-03-31 2026-03-31 0001283699 tmus:A5.500SeniorNotesDueMarch2070Member 2026-03-31 2026-03-31 0001283699 tmus:A5.500SeniorNotesDueJune2070Member 2026-03-31 2026-03-31 UNITED STATES SECURITIES AND EXCHANGE COMMISSION WASHINGTON, D.C. 20549 FORM 8-K CURRENT REPORT Pursuant to Section 13 or 15(d) of the Securities Exchange Act of 1934 Date of report (Date of earliest event reported): March 31, 2026 T-MOBILE US, INC. (Exact Name of Registrant as Specified in its Charter) Delaware 1-33409 20-0836269 (State or other jurisdiction of incorporation) (Commission File Number) (I.R.S. Employer Identification No.) 12920 SE 38th Street Bellevue , Washington 98006-1350 (Address of principal executive offices) (Zip Code) Registrant’s telephone number, including area code: ( 425 ) 378-4000 (Former Name or Former Address, if Changed Since Last Report): Check the appropriate box below if the Form 8-K filing is intended to simultaneously satisfy the filing obligation of the registrant under any of the following provisions: ☐ Written communications pursuant to Rule 425 under the Securities Act (17 CFR 230.425) ☐ Soliciting material pursuant to Rule 14a-12 under the Exchange Act (17 CFR 240.14a-12) ☐ Pre-commencement communications pursuant to Rule 14d-2(b) under the Exchange Act (17 CFR 240.14d-2(b)) ☐ Pre-commencement communications pursuant to Rule 13e-4(c) under the Exchange Act (17 CFR 240.13e-4(c)) Securities registered pursuant to Section 12(b) of the Act: Title of each class Trading Symbol Name of each exchange on which registered Common Stock, par value $0.00001 per share TMUS The NASDAQ Stock Market LLC 3.550% Senior Notes due 2029 TMUS29 The NASDAQ Stock Market LLC 3.700% Senior Notes due 2032 TMUS32 The NASDAQ Stock Market LLC 3.150% Senior Notes due 2032 TMUS32A The NASDAQ Stock Market LLC 3.200% Senior Notes due 2032 TMUS32B The NASDAQ Stock Market LLC 3.625% Senior Notes due 2035 TMUS35 The NASDAQ Stock Market LLC 3.850% Senior Notes due 2036 TMUS36 The NASDAQ Stock Market LLC 3.900% Senior Notes due 2038 TMUS38 The NASDAQ Stock Market LLC 3.500% Senior Notes due 2037 TMUS37 The NASDAQ Stock Market LLC 3.800% Senior Notes due 2045 TMUS45 The NASDAQ Stock Market LLC 6.250% Senior Notes due 2069 TMUSL The NASDAQ Stock Market LLC 5.500% Senior Notes due March 2070 TMUSZ The NASDAQ Stock Market LLC 5.500% Senior Notes due June 2070 TMUSI The NASDAQ Stock Market LLC Indicate by check mark whether the registrant is an emerging growth company as defined in Rule 405 of the Securities Act of 1933 (§230.405 of this chapter) or Rule 12b-2 of the Securities Exchange Act of 1934 (§240.12b-2 of this chapter). Emerging growth company ☐ If an emerging growth company, indicate by check mark if the registrant has elected not to use the extended transition period for complying with any new or revised financial accounting standards provided pursuant to Section 13(a) of the Exchange Act. ☐ Item 8.01. Other Events. On March 31, 2026, following the previous repayment of certain legacy indebtedness, T-Mobile USA, Inc. (“ TMUSA ”), a wholly-owned subsidiary of T-Mobile US, Inc. (“ TMUS ”), elected to release the guarantees of certain subsidiaries under its $10 billion revolving credit agreement pursuant to the terms thereof, resulting in a corresponding release under the indentures dated April 28, 2013, April 9, 2020 and September 15, 2022, governing its outstanding senior notes. As a result, following the release, the obligors under TMUSA’s revolving credit agreement and outstanding senior notes now consist of TMUSA, as issuer or borrower, and each of TMUS, Sprint LLC, Sprint Capital Corporation and Sprint Communications LLC, as guarantors. Corresponding subsidiary guarantor releases were also effected under other TMUSA debt facilities, including its export credit agency facilities and unsecured short-term commercial paper program. SIGNATURES Pursuant to the requirements of the Securities Exchange Act of 1934, the registrant has duly caused this report to be signed on its behalf by the undersigned hereunto duly authorized. T-MOBILE US, INC. March 31, 2026 /s/ Peter Osvaldik Name: Peter Osvaldik Title: Chief Financial Officer", "parsed_data": {}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/TSLA_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/TSLA_2026-04-04.jsonl new file mode 100644 index 0000000..603872c --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/TSLA_2026-04-04.jsonl @@ -0,0 +1,3 @@ +{"metadata": {"ticker": "TSLA", "form_type": "4", "filed_at": "2026-04-02T20:08:52-04:00", "accession_no": "0001972928-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/1318605/000197292826000002/xslF345X06/edgardoc.xml", "ingested_at": "2026-04-04T22:54:24.292686"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Zhu Xiaotong", "role": "SVP", "transactions": [{"date": "2026-03-31", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 20000.0, "price": 20.57, "total_value": 411400.0, "post_transaction_shares": 20000.0, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "TSLA", "form_type": "8-K", "filed_at": "2026-04-02T09:07:13-04:00", "accession_no": "0001628280-26-022956", "url": "https://www.sec.gov/Archives/edgar/data/1318605/000162828026022956/tsla-20260402.htm", "ingested_at": "2026-04-04T22:54:24.871733"}, "raw_text": "tsla-20260402 FALSE 0001318605 0001318605 2026-04-02 2026-04-02 UNITED STATES SECURITIES AND EXCHANGE COMMISSION WASHINGTON, DC 20549 FORM 8-K CURRENT REPORT Pursuant to Section 13 or 15(d) of the Securities Exchange Act of 1934 Date of report (Date of earliest event reported): April 2, 2026 Tesla, Inc. (Exact Name of Registrant as Specified in Charter) Texas 001-34756 91-2197729 (State or Other Jurisdiction of Incorporation) (Commission File Number) (I.R.S. Employer Identification No.) 1 Tesla Road Austin , Texas 78725 (Address of Principal Executive Offices, and Zip Code) ( 512 ) 516-8177 Registrant’s Telephone Number, Including Area Code Check the appropriate box below if the Form 8-K filing is intended to simultaneously satisfy the filing obligation of the registrant under any of the following provisions ( see General Instruction A.2. below): o Written communication pursuant to Rule 425 under the Securities Act (17 CFR 230.425) o Soliciting material pursuant to Rule 14a-12 under the Exchange Act (17 CFR 240.14a-12) o Pre-commencement communication pursuant to Rule 14d-2(b) under the Exchange Act (17 CFR 240.14d-2(b)) o Pre-commencement communication pursuant to Rule 13e-4(c) under the Exchange Act (17 CFR 240.13e-4(c)) Securities registered pursuant to Section 12(b) of the Act: Title of each class Trading Symbol(s) Name of each exchange on which registered Common stock TSLA The Nasdaq Global Select Market Indicate by check mark whether the registrant is an emerging growth company as defined in Rule 405 of the Securities Act of 1933 (17 CFR §230.405) or Rule 12b-2 of the Securities Exchange Act of 1934 (17 CFR §240.12b-2). Emerging growth company o If an emerging growth company, indicate by check mark if the registrant has elected not to use the extended transition period for complying with any new or revised financial accounting standards provided pursuant to Section 13(a) of the Exchange Act. o Item 2.02    Results of Operations and Financial Condition. On April 2, 2026, Tesla, Inc. published the press release which is attached hereto as Exhibit 99.1 and is incorporated herein by reference. This information is intended to be furnished under Item 2.02 of Form 8-K and shall not be deemed “filed” for purposes of Section 18 of the Securities Exchange Act of 1934, as amended (the “ Exchange Act ”), or incorporated by reference in any filing under the Securities Act of 1933, as amended, or the Exchange Act as shall be expressly set forth by specific reference in such a filing . Item 9.01    Financial Statements and Exhibits. (d) Exhibits. Exhibit No. Description 99.1 Press release of Tesla, Inc., dated April 2, 2026 . 104 Cover Page Interactive Data File (embedded within the Inline XBRL document). SIGNATURES Pursuant to the requirements of the Securities Exchange Act of 1934, the registrant has duly caused this report to be signed on its behalf by the undersigned hereunto duly authorized. TESLA, INC. By: /s/ Brandon Ehrhart Brandon Ehrhart General Counsel and Corporate Secretary Date: April 2, 2026", "parsed_data": {}} +{"metadata": {"ticker": "TSLA", "form_type": "4", "filed_at": "2026-04-01T19:00:13-04:00", "accession_no": "0001104659-26-038682", "url": "https://www.sec.gov/Archives/edgar/data/1318605/000110465926038682/xslF345X06/tm2610684-1_4seq1.xml", "ingested_at": "2026-04-04T22:54:25.463712"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Wilson-Thompson Kathleen", "role": "Other", "transactions": [{"date": "2026-03-30", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 40000.0, "price": 14.99, "total_value": 599600.0, "post_transaction_shares": 59669.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 2000.0, "price": 352.833, "total_value": 705666.0, "post_transaction_shares": 57669.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1640.0, "price": 353.658, "total_value": 579999.12, "post_transaction_shares": 56029.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1800.0, "price": 354.802, "total_value": 638643.6000000001, "post_transaction_shares": 54229.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 2481.0, "price": 355.644, "total_value": 882352.764, "post_transaction_shares": 51748.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 2360.0, "price": 356.794, "total_value": 842033.84, "post_transaction_shares": 49388.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1120.0, "price": 357.839, "total_value": 400779.68, "post_transaction_shares": 48268.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 520.0, "price": 358.77, "total_value": 186560.4, "post_transaction_shares": 47748.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1880.0, "price": 360.181, "total_value": 677140.2799999999, "post_transaction_shares": 45868.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1000.0, "price": 361.035, "total_value": 361035.0, "post_transaction_shares": 44868.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 2320.0, "price": 362.142, "total_value": 840169.44, "post_transaction_shares": 42548.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 4001.0, "price": 363.083, "total_value": 1452695.083, "post_transaction_shares": 38547.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 3927.0, "price": 363.947, "total_value": 1429219.869, "post_transaction_shares": 34620.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 560.0, "price": 364.888, "total_value": 204337.28, "post_transaction_shares": 34060.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 120.0, "price": 365.897, "total_value": 43907.64, "post_transaction_shares": 33940.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 80.0, "price": 366.855, "total_value": 29348.4, "post_transaction_shares": 33860.0, "is_10b5_1_planned": true}]}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/VRTX_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/VRTX_2026-04-04.jsonl new file mode 100644 index 0000000..86f43d9 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/VRTX_2026-04-04.jsonl @@ -0,0 +1,3 @@ +{"metadata": {"ticker": "VRTX", "form_type": "4", "filed_at": "2026-04-03T16:53:51-04:00", "accession_no": "0000875320-26-000157", "url": "https://www.sec.gov/Archives/edgar/data/875320/000087532026000157/xslF345X06/wk-form4_1775249628.xml", "ingested_at": "2026-04-04T22:54:58.343666"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Liu Joy", "role": "EVP and Chief Legal Officer", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 978.0, "price": 449.17, "total_value": 439288.26, "post_transaction_shares": 21833.0, "is_10b5_1_planned": true}]}} +{"metadata": {"ticker": "VRTX", "form_type": "4", "filed_at": "2026-03-31T16:10:23-04:00", "accession_no": "0000875320-26-000149", "url": "https://www.sec.gov/Archives/edgar/data/875320/000087532026000149/xslF345X06/wk-form4_1774987818.xml", "ingested_at": "2026-04-04T22:54:58.915828"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Bozic Carmen", "role": "EVP and CMO", "transactions": [{"date": "2026-03-27", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 2329.0, "price": 450.95, "total_value": 1050262.55, "post_transaction_shares": 33076.0, "is_10b5_1_planned": true}]}} +{"metadata": {"ticker": "VRTX", "form_type": "8-K", "filed_at": "2026-03-31T16:03:47-04:00", "accession_no": "0000875320-26-000147", "url": "https://www.sec.gov/Archives/edgar/data/875320/000087532026000147/vrtx-20260331.htm", "ingested_at": "2026-04-04T22:54:59.488007"}, "raw_text": "vrtx-20260331 0000875320 VERTEX PHARMACEUTICALS INC / MA false 0000875320 2026-03-31 2026-03-31 UNITED STATES SECURITIES AND EXCHANGE COMMISSION Washington, D.C. 20549 FORM 8-K CURRENT REPORT Pursuant to Section 13 OR 15(d) of The Securities Exchange Act of 1934 Date of Report (Date of earliest event reported) March 31, 2026 Vertex Pharmaceuticals Incorporated (Exact name of registrant as specified in its charter) Massachusetts 000-19319 04-3039129 (State or other jurisdiction of incorporation) (Commission File Number) (I.R.S. Employer Identification No.) 50 Northern Avenue Boston , Massachusetts 02210 (Address of principal executive offices) (Zip Code) ( 617 ) 341-6100 (Registrant's telephone number, including area code) Check the appropriate box below if the Form 8-K filing is intended to simultaneously satisfy the filing obligation of the registrant under any of the following provisions (see General Instruction A.2. below): ☐ Written communications pursuant to Rule 425 under the Securities Act (17 CFR 230.425) ☐ Soliciting material pursuant to Rule 14a-12 under the Exchange Act (17 CFR 240.14a-12) ☐ Pre-commencement communications pursuant to Rule 14d-2(b) under the Exchange Act (17 CFR 240.14d-2(b)) ☐ Pre-commencement communications pursuant to Rule 13e-4(c) under the Exchange Act (17 CFR 240.13e-4(c)) Securities registered pursuant to Section 12(b) of the Act: Title of each class Trading Symbol Name of each exchange on which registered Common Stock, $0.01 Par Value Per Share VRTX The Nasdaq Global Select Market Indicate by check mark whether the registrant is an emerging growth company as defined in Rule 405 of the Securities Act of 1933 (§230.405 of this chapter) or Rule 12b-2 of the Securities Exchange Act of 1934 (§240.12b-2 of this chapter). Emerging growth company ☐ If an emerging growth company, indicate by check mark if the registrant has elected not to use the extended transition period for complying with any new or revised financial accounting standards provided pursuant to Section 13(a) of the Exchange Act. ☐ Item 8.01. Other Events. Vertex Pharmaceuticals Incorporated (the “Company”) has completed the submission to the U.S. Food and Drug Administration (the “FDA”) of its rolling Biologics Licensing Application (“BLA”) for potential accelerated approval of povetacicept for the treatment of immunoglobulin A nephropathy (“IgAN”) in adults. The Company used a priority review voucher and therefore expects the FDA review of the povetacicept BLA to be expedited to six months from the date of the FDA’s acceptance of the BLA versus the typical ten-month review. Special Note Regarding Forward-Looking Statements This Current Report on Form 8-K contains forward-looking statements that are subject to risks, uncertainties and other factors including statements regarding the expected duration of the FDA review of the povetacicept BLA and potential for accelerated approval of povetacicept for the treatment of IgAN. While the Company believes the forward-looking statements contained in this communication are accurate, these forward-looking statements represent the beliefs of the Company only as of the date of this communication, and there are a number of risks and uncertainties that could cause actual events or results to differ materially from those expressed or implied by such forward-looking statements. Forward-looking statements are subject to certain risks, uncertainties, or other factors that are difficult to predict and could cause actual events or results to differ materially from those indicated in any such statements due to a number of risks and uncertainties. Forward-looking statements in this communication should be evaluated together with the many risks and uncertainties that affect the Company's business. Those risks and uncertainties include, among other things, that we may be unable to obtain or be delayed in obtaining regulatory approval and other risks listed under the heading “Risk Factors” and the other cautionary factors discussed in the Company's periodic reports filed with the Securities and Exchange Commission (the “SEC”), including the Company's annual report on Form 10-K for the year ended December 31, 2025, its quarterly reports on Form 10-Q, and its current reports on Form 8-K, all of which are available for free through the Company's website at www.vrtx.com and on the SEC’s website at www.sec.gov. You should not place undue reliance on these statements. All forward-looking statements are based on information currently available to the Company, and the Company disclaims any obligation to update the information contained in this communication as new information becomes available, except as required by law. SIGNATURES Pursuant to the requirements of the Securities Exchange Act of 1934, the Registrant has duly caused this report to be signed on its behalf by the undersigned hereunto duly authorized. VERTEX PHARMACEUTICALS INCORPORATED (Registrant) Date: March 31, 2026 /s/ Joy Liu Joy Liu Executive Vice President, Chief Legal Officer", "parsed_data": {}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/_SUMMARY.json b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/_SUMMARY.json new file mode 100644 index 0000000..029a777 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/_SUMMARY.json @@ -0,0 +1,86 @@ +{ + "date": "2026-04-04", + "total_filings": 72, + "ticker_breakdown": { + "VRTX": { + "4": 2, + "8-K": 1 + }, + "PANW": { + "4": 2, + "8-K": 0 + }, + "CMCSA": { + "4": 6, + "8-K": 0 + }, + "AVGO": { + "4": 0, + "8-K": 1 + }, + "SBUX": { + "4": 0, + "8-K": 2 + }, + "TSLA": { + "4": 2, + "8-K": 1 + }, + "AAPL": { + "4": 6, + "8-K": 0 + }, + "AMAT": { + "4": 1, + "8-K": 0 + }, + "INTU": { + "4": 6, + "8-K": 0 + }, + "TMUS": { + "4": 0, + "8-K": 1 + }, + "IBM": { + "4": 13, + "8-K": 0 + }, + "MDLZ": { + "4": 0, + "8-K": 0 + }, + "HON": { + "4": 2, + "8-K": 0 + }, + "NFLX": { + "4": 13, + "8-K": 0 + }, + "BKNG": { + "4": 0, + "8-K": 3 + }, + "INTC": { + "4": 0, + "8-K": 1 + }, + "QCOM": { + "4": 3, + "8-K": 0 + }, + "AMZN": { + "4": 1, + "8-K": 0 + }, + "COST": { + "4": 1, + "8-K": 0 + }, + "GOOG": { + "4": 3, + "8-K": 1 + } + } +} \ No newline at end of file diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_AAPL_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_AAPL_2026-04-04.jsonl new file mode 100644 index 0000000..a169476 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_AAPL_2026-04-04.jsonl @@ -0,0 +1,3 @@ +{"metadata": {"ticker": "AAPL", "form_type": "4", "filed_at": "2026-04-03T18:30:45-04:00", "accession_no": "0001140361-26-013192", "url": "https://www.sec.gov/Archives/edgar/data/320193/000114036126013192/xslF345X06/form4.xml", "ingested_at": "2026-04-04T22:49:03.052799"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "O'BRIEN DEIRDRE", "role": "Senior Vice President", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 64317.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 201127.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 34315.0, "price": 255.63, "total_value": 8771943.45, "post_transaction_shares": 166812.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 20338.0, "price": 255.12, "total_value": 5188630.5600000005, "post_transaction_shares": 146474.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 9664.0, "price": 255.82, "total_value": 2472244.48, "post_transaction_shares": 136810.0, "is_10b5_1_planned": true}]}} +{"metadata": {"ticker": "AAPL", "form_type": "4", "filed_at": "2026-04-03T18:30:43-04:00", "accession_no": "0001140361-26-013191", "url": "https://www.sec.gov/Archives/edgar/data/320193/000114036126013191/xslF345X06/form4.xml", "ingested_at": "2026-04-04T22:49:03.628698"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Khan Sabih", "role": "COO", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 64317.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 1107212.0, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 33317.0, "price": 255.63, "total_value": 8516824.709999999, "post_transaction_shares": 1073895.0, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "AAPL", "form_type": "4", "filed_at": "2026-04-03T18:30:41-04:00", "accession_no": "0001140361-26-013190", "url": "https://www.sec.gov/Archives/edgar/data/320193/000114036126013190/xslF345X06/form4.xml", "ingested_at": "2026-04-04T22:49:04.205425"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "COOK TIMOTHY D", "role": "Chief Executive Officer", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 131576.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 3411994.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 66627.0, "price": 255.63, "total_value": 17031860.009999998, "post_transaction_shares": 3345367.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 5087.0, "price": 251.25, "total_value": 1278108.75, "post_transaction_shares": 3340280.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 9147.0, "price": 252.11, "total_value": 2306050.17, "post_transaction_shares": 3331133.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1878.0, "price": 253.13, "total_value": 475378.14, "post_transaction_shares": 3329255.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 16083.0, "price": 254.37, "total_value": 4091032.71, "post_transaction_shares": 3313172.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 28188.0, "price": 255.17, "total_value": 7192731.96, "post_transaction_shares": 3284984.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 4566.0, "price": 256.0, "total_value": 1168896.0, "post_transaction_shares": 3280418.0, "is_10b5_1_planned": true}]}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_AMAT_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_AMAT_2026-04-04.jsonl new file mode 100644 index 0000000..e26acbf --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_AMAT_2026-04-04.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "AMAT", "form_type": "4", "filed_at": "2026-04-02T18:44:21-04:00", "accession_no": "0001628280-26-023379", "url": "https://www.sec.gov/Archives/edgar/data/6951/000162828026023379/xslF345X06/wk-form4_1775169858.xml", "ingested_at": "2026-04-04T22:54:48.024214"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Sanders Adam", "role": "Corp. Controller & CAO", "transactions": [{"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 125.0, "price": 353.8, "total_value": 44225.0, "post_transaction_shares": 4548.0, "is_10b5_1_planned": false}]}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_AMZN_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_AMZN_2026-04-04.jsonl new file mode 100644 index 0000000..9b4bfab --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_AMZN_2026-04-04.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "AMZN", "form_type": "4", "filed_at": "2026-04-03T16:41:29-04:00", "accession_no": "0001018724-26-000010", "url": "https://www.sec.gov/Archives/edgar/data/1018724/000101872426000010/xslF345X06/wk-form4_1775248886.xml", "ingested_at": "2026-04-04T22:54:20.480654"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Herrington Douglas J", "role": "CEO Worldwide Amazon Stores", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1000.0, "price": 210.5, "total_value": 210500.0, "post_transaction_shares": 520361.0, "is_10b5_1_planned": true}]}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_AVGO_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_AVGO_2026-04-04.jsonl new file mode 100644 index 0000000..af94b4c --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_AVGO_2026-04-04.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "AVGO", "form_type": "8-K", "filed_at": "2026-04-02T17:25:00-04:00", "accession_no": "0001193125-26-140574", "url": "https://www.sec.gov/Archives/edgar/data/1730168/000119312526140574/d109450d8k.htm", "ingested_at": "2026-04-04T22:54:26.159841"}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS", "parsed_data": {"is_chunked": true, "item_chunks": {"5.02": "Item 5.02 | Departure of Directors or Certain Officers; Election of Directors; Appointment of Certain Officers; Compensatory Arrangements of Certain Officers. |\n\nChief Financial Officer Transition\n\nOn March 30, 2026, Kirsten M. Spears notified Broadcom Inc. (the “Company”) of her retirement and resigned from her position as Chief Financial Officer and Chief Accounting Officer of the Company, effective as of June 12, 2026.\n\nOn March 30, 2026, the Board of Directors of the Company (the “Board”) appointed Amie Thuener to succeed Ms. Spears as the Chief Financial Officer of the Company, effective as of June 12, 2026. The employment of Ms. Thuener with the Company is expected to commence on May 4, 2026 and she will assume the role of Chief Financial Officer following the retirement of Ms. Spears on June 12, 2026.\n\nMs. Thuener, age 51, has served as Vice President, Corporate Controller and Chief Accounting Officer of Alphabet Inc. since 2018. Ms. Thuener held several senior finance positions at Alphabet from 2013 to 2018, including as Vice President and Chief Accountant. Prior to joining Alphabet, Ms. Thuener was at PricewaterhouseCoopers LLP from 1996 to 2012 and held several senior management positions, including as Managing Director, Transaction Services. Ms. Thuener is a Certified Public Accountant and a Chartered Global Management Accountant.\n\nThere are no family relationships between Ms. Thuener and any director or executive officer of the Company as defined in Item 401(d) of Regulation S-K, and Ms. Thuener has no direct or indirect material interest in any transaction or proposed transaction required to be disclosed pursuant to Item 404(a) of Regulation S-K.\n\nKirsten M. Spears Transition and Consulting Agreement\n\nIn connection with the retirement of Ms. Spears, the Company entered into a transition and consulting agreement with Ms. Spears, dated as of April 1, 2026 (the “Transition Agreement”).\n\nThe Transition Agreement provides that, following the conclusion of Ms. Spears’ employment with the Company on June 12, 2026, she will provide consulting services to the Company, as reasonably requested by the Chief Executive Officer of the Company, until March 15, 2027, unless the consulting period terminates earlier in accordance with the terms of the Transition Agreement. During the consulting period, Ms. Spears’ outstanding equity awards will continue to vest in accordance with their terms (provided that the performance-based equity awards will in no event vest at a level exceeding target). Ms. Spears will not receive any other compensation during the consulting period. The Transition Agreement includes a general release of claims in favor of the Company.\n\nAmie Thuener Offer Letter and Equity Awards\n\nIn connection with her employment with the Company and appointment as Chief Financial Officer of the Company, effective as of June 12, 2026, the Company entered into an offer letter with Ms. Thuener, dated as of March 30, 2026, which sets forth the material terms of her employment and compensation (the “Offer Letter”).\n\nPursuant to the Offer Letter, Ms. Thuener will receive an annual base salary of $700,000 and will be eligible to participate in the Company’s annual performance bonus plan with a target bonus opportunity of 100% of her base salary. Ms. Thuener will also receive a $1,000,000 sign-on cash bonus, payable within 30 days following the commencement of her employment.\n\nThe Offer Letter further provides that, subject to the approval of the Compensation Committee of the Board and Ms. Thuener’s continued employment through the applicable grant date, Ms. Thuener will be granted equity awards under the Company’s 2012 Stock Incentive Plan consisting of (i) 50,000 restricted stock units (“RSUs”) and (ii) 50,000 performance stock units (“PSUs”) at target. The equity awards are expected to be granted on June 15, 2026.\n\nThe RSUs will vest in equal quarterly installments over a four-year period following the grant date, subject to Ms. Thuener’s continued employment through each applicable vesting date. The PSUs will vest annually over a four-year period across four overlapping performance periods (March 2, 2026 through March 1, 2027, March 2, 2026 through March 1, 2028, March 2, 2026 through March 1, 2029 and March 2, 2026 through March 1, 2030) based on the Company’s total stockholder return relative to the S&P 500 and the Company’s absolute total stockholder return for the applicable performance period, in each case subject to Ms. Thuener’s continued employment through the anniversary of the grant date immediately following the end of each applicable performance period. The maximum vesting for the PSUs is 200% of the total target number of shares. The equity awards will be subject to the other terms and conditions set forth in the Company’s 2012 Stock Incentive Plan and the applicable award agreements.\n\n---\n\nIn addition, Ms. Thuener is expected to enter into the Company’s standard form of indemnification and advancement agreement and a severance benefit agreement on terms and conditions materially consistent with those applicable to Ms. Spears pursuant to her severance benefit agreement, as described in the Company’s definitive proxy statement filed with the U.S. Securities and Exchange Commission on March 2, 2026.\n\n---"}}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_BKNG_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_BKNG_2026-04-04.jsonl new file mode 100644 index 0000000..6ed6989 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_BKNG_2026-04-04.jsonl @@ -0,0 +1,3 @@ +{"metadata": {"ticker": "BKNG", "form_type": "8-K", "filed_at": "2026-04-02T16:34:43-04:00", "accession_no": "0000950157-26-000465", "url": "https://www.sec.gov/Archives/edgar/data/1075531/000095015726000465/form8-k.htm", "ingested_at": "2026-04-04T22:54:56.421512"}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS", "parsed_data": {"is_chunked": true, "item_chunks": {"5.03": "Item 5.03. Amendments to Articles of incorporation or Bylaws; Change in Fiscal Year.\n\nOn April 2, 2026, Booking Holdings Inc. (the “Company”) filed an amendment to its Restated Certificate of Incorporation with the Delaware Secretary of State to effect the\npreviously announced twenty-five-for-one forward stock split of the Company’s common stock and to proportionately increase the number of shares of the Company’s authorized common stock from 1,000,000,000 to 25,000,000,000. The amendment, which became\neffective at 4:01 p.m. Eastern Time on April 2, 2026, is filed as Exhibit 3.1 to this Current Report on Form 8-K. Trading is expected to commence on a split-adjusted basis at market open on Monday, April 6, 2026.", "9.01": "Item 9.01. Financial Statements and Exhibits.\n\n| | | |\n| --- | --- | --- |\n| (d) Exhibits | | |\n| Exhibit Number | | Description |\n| | | |\n| 3.1 | | Amendment to Restated Certificate of Incorporation of Booking Holdings Inc., dated April 2, 2026. |\n| 104 | | Cover Page Interactive Data File - the cover page interactive data file does not appear in the Interactive Data File because its XBRL tags are embedded within the Inline XBRL document. |\n\n---"}}} +{"metadata": {"ticker": "BKNG", "form_type": "8-K", "filed_at": "2026-04-02T16:12:50-04:00", "accession_no": "0001075531-26-000014", "url": "https://www.sec.gov/Archives/edgar/data/1075531/000107553126000014/bkng-20260402.htm", "ingested_at": "2026-04-04T22:54:57.020686"}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS", "parsed_data": {"is_chunked": true, "item_chunks": {"5.02": "Item 5.02.    Departure of Directors or Certain Officers; Election of Directors; Appointment\n\nof Certain Officers; Compensatory Arrangements of Certain Officers.\n\nOn April 2, 2026, Booking Holdings Inc. (the \"Company\") announced that it has appointed Caroline Sullivan as its Senior Vice President, Chief Accounting Officer, and Controller effective as of April 29, 2026. Ms. Sullivan, age 57, served as Vice President, Procurement and Real Estate of Elevance Health, a health insurance company, from June 2025 to March 2026. Prior to this, Ms. Sullivan was Senior Vice President, Chief Accounting Officer and Corporate Controller at Moody's Corporation, a global risk assessment firm, from December 2018 to March 2025. Ms. Sullivan also served as Global Banking Controller of Bank of America from 2017 to 2018. Earlier in her career, she held various finance positions with Morgan Stanley and Allied Irish Bank. Ms. Sullivan began her career at Ernst and Young and is a Certified Public Accountant.\n\nIn connection with Ms. Sullivan's appointment, she and the Company entered into an employment agreement with, among others, the following terms:\n\n•an initial annual base salary of $525,000;\n\n•a target annual bonus of 75% of base salary;\n\n•a grant of restricted stock units (\"RSUs\") expected to be made in May 2026 with a grant date fair value of $1,000,000;\n\n•a grant of performance share units (\"PSUs\") expected to be made in March 2027 with a grant date fair value at target of $1,000,000;\n\n•a new hire grant of RSUs expected to be made in May 2026 with a grant date fair value of $1,000,000;\n\n•a signing bonus of $300,000; and\n\n•in the event of her termination without cause, subject to the execution of a release of claims, severance benefits including payments equal to one times her base salary and target annual bonus, a pro-rated portion of any earned bonus for the year of termination if employment is terminated after June 30 of the then current year, health benefits for a period of 12 months, and any earned bonus for a prior completed year that has not yet been paid.\n\nMs. Sullivan's RSUs and new hire RSUs will each vest in three equal annual installments on each of the first three anniversaries of the grant date, subject to her continuous service from the date of grant until the vesting date, with pro rata vesting upon a termination without cause or due to disability, and full vesting upon a termination due to death. Ms. Sullivan's PSU award will vest subject to such service and performance-based vesting provisions generally consistent with those applicable to similarly-situated executives who receive PSU grants in 2027. The awards will be subject to the terms of the respective award agreements for awards under the Company’s 1999 Omnibus Plan.\n\nIn connection with Ms. Sullivan's appointment, the Company and Ms. Sullivan have also entered into a Non-Competition and Non-Solicitation Agreement and an Employee Confidentiality and Assignment Agreement.\n\n---"}}} +{"metadata": {"ticker": "BKNG", "form_type": "8-K", "filed_at": "2026-04-01T16:10:37-04:00", "accession_no": "0001075531-26-000012", "url": "https://www.sec.gov/Archives/edgar/data/1075531/000107553126000012/bkng-20260401.htm", "ingested_at": "2026-04-04T22:54:57.634231"}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS", "parsed_data": {"is_chunked": true, "item_chunks": {"5.02": "Item 5.02.    Departure of Directors or Certain Officers; Election of Directors; Appointment\n\nof Certain Officers; Compensatory Arrangements of Certain Officers.\n\nAppointment of Director\n\nOn April 1, 2026, Mr. Kurt Sievers was appointed to the Board of Directors (the \"Board\") of Booking Holdings Inc. (the \"Company\") and will be joining the Board's Corporate Governance Committee.\n\nMr. Sievers served as President and Chief Executive Officer of NXP Semiconductors N.V., a Netherlands-based semiconductor company (\"NXP\"), from 2020 until his retirement in 2025. He previously served as President beginning in 2018 and joined NXP’s Executive Management Team in 2009. Mr. Sievers currently serves on the board of directors of Capgemini SE, a multinational information technology services and consulting company, and is a member of its Strategy & CSR and Compensation Committees. He also serves on the supervisory board of Daimler Truck Holding AG, a commercial vehicle manufacturer.\n\nIn consideration of his services as a member of the Company's Board and any Board committees, Mr. Sievers will be compensated in accordance with the Company's non-employee director compensation program as in effect from time to time.\n\nRetirement of Director\n\nMs. Lynn Radakovich has informed the Company that she has decided to retire from the Board, effective at the Company's Annual Meeting in June 2026 (the \"Annual Meeting\"), and therefore is not standing for re-election at the Annual Meeting. The Company and the Board express their appreciation to Ms. Radakovich for her dedicated service.", "7.01": "Item 7.01    Regulation FD Disclosure.\n\nA copy of the press release announcing Mr. Sievers's appointment and Ms. Radakovich's retirement is furnished with this Current Report as Exhibit 99.1.\n\nThe information furnished herewith pursuant to this Item 7.01 of this Current Report shall not be deemed to be \"filed\" for purposes of Section 18 of the Securities Exchange Act of 1934, as amended (the \"Exchange Act\"), or otherwise subject to the liabilities of that section, and shall not be incorporated by reference into any registration statement or other document under the Securities Act of 1933, as amended, or the Exchange Act, except as shall be expressly set forth by specific reference in such filing.", "9.01": "Item 9.01.           Financial Statements and Exhibits.\n\n(d)    Exhibits\n\n| | | | | | | | | | | | | | | |\n| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| | | | | | | | | | | | | | | |\n| Exhibit Number | | | Description | | | | | | | | | | | |\n| | | | | | | | | | | | | | | |\n| 99.1 | | | Press Release, dated April 1, 2026. | | | | | | | | | | | |\n| 104 | | | Cover Page Interactive Data File - the cover page interactive data file does not appear in the Interactive Data File because its XBRL tags are embedded within the Inline XBRL document. | | | | | | | | | | | |\n| | | | | | | | | | | | | | | |\n| | | | | | | | | | | | | | | |\n| | | | | | | | | | | | | | | |\n| | | | | | | | | | | | | | | |\n| | | | | | | | | | | | | | | |\n| | | | | | | | | | | | | | | |\n| | | | | | | | | | | | | | | |\n| | | | | | | | | | | | | | | |\n| | | | | | | | | | | | | | | |\n\n---"}}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_CMCSA_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_CMCSA_2026-04-04.jsonl new file mode 100644 index 0000000..e601d52 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_CMCSA_2026-04-04.jsonl @@ -0,0 +1,6 @@ +{"metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-03T13:33:09-04:00", "accession_no": "0001225208-26-004342", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004342/xslF345X06/doc4.xml", "ingested_at": "2026-04-04T22:54:43.613356"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Murdock Daniel C.", "role": "EVP & Chief Accounting Officer", "transactions": [{"date": "2026-04-03", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 5268.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 64435.0497, "is_10b5_1_planned": false}, {"date": "2026-04-03", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 2073.0, "price": 27.93, "total_value": 57898.89, "post_transaction_shares": 62362.0497, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-02T16:27:31-04:00", "accession_no": "0001225208-26-004203", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004203/xslF345X06/doc4.xml", "ingested_at": "2026-04-04T22:54:44.188539"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Smith Gordon", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 1176.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 9045.0, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-02T16:26:30-04:00", "accession_no": "0001225208-26-004202", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004202/xslF345X06/doc4.xml", "ingested_at": "2026-04-04T22:54:44.751062"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Honickman Jeffrey A", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 1524.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 262583.021, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-02T16:25:30-04:00", "accession_no": "0001225208-26-004201", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004201/xslF345X06/doc4.xml", "ingested_at": "2026-04-04T22:54:45.317020"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "BREEN EDWARD D", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 697.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 56522.277, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-02T16:24:25-04:00", "accession_no": "0001225208-26-004200", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004200/xslF345X06/doc4.xml", "ingested_at": "2026-04-04T22:54:45.888239"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Brady Louise F.", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 1176.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 32682.89, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-02T16:23:19-04:00", "accession_no": "0001225208-26-004199", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004199/xslF345X06/doc4.xml", "ingested_at": "2026-04-04T22:54:46.458338"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Baltimore Thomas J Jr", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 1176.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 39043.493, "is_10b5_1_planned": false}]}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_COST_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_COST_2026-04-04.jsonl new file mode 100644 index 0000000..d576741 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_COST_2026-04-04.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "COST", "form_type": "4", "filed_at": "2026-04-01T18:13:26-04:00", "accession_no": "0000909832-26-000039", "url": "https://www.sec.gov/Archives/edgar/data/909832/000090983226000039/xslF345X06/form4.xml", "ingested_at": "2026-04-04T22:54:26.825658"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Frates Caton", "role": "Executive Vice President", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 700.0, "price": 993.0, "total_value": 695100.0, "post_transaction_shares": 5815.001, "is_10b5_1_planned": false}]}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_GOOG_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_GOOG_2026-04-04.jsonl new file mode 100644 index 0000000..0ced741 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_GOOG_2026-04-04.jsonl @@ -0,0 +1,4 @@ +{"metadata": {"ticker": "GOOG", "form_type": "4", "filed_at": "2026-04-03T17:31:35-04:00", "accession_no": "0001193125-26-142372", "url": "https://www.sec.gov/Archives/edgar/data/1652044/000119312526142372/xslF345X06/ownership.xml", "ingested_at": "2026-04-04T22:54:21.748568"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "O'Toole Amie Thuener", "role": "VP, Chief Accounting Officer", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 617.0, "price": 289.63, "total_value": 178701.71, "post_transaction_shares": 10093.0, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "GOOG", "form_type": "8-K", "filed_at": "2026-04-02T16:18:28-04:00", "accession_no": "0001652044-26-000031", "url": "https://www.sec.gov/Archives/edgar/data/1652044/000165204426000031/goog-20260330.htm", "ingested_at": "2026-04-04T22:54:22.331849"}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS", "parsed_data": {"is_chunked": true, "item_chunks": {"5.02": "Item 5.02 Departure of Directors or Certain Officers; Election of Directors; Appointment of Certain Officers; Compensatory Arrangements of Certain Officers.\n\nOn March 30, 2026, Amie Thuener O'Toole notified Alphabet Inc. (the “Company”) of her resignation as Vice President, Corporate Controller and Principal Accounting Officer of the Company, effective April 9, 2026, to pursue another professional opportunity. Ms. O'Toole’s decision to resign did not result from any disagreement with the Company on any matter relating to the Company’s operations, policies, or practices.\n\n---"}}} +{"metadata": {"ticker": "GOOG", "form_type": "4", "filed_at": "2026-03-31T21:43:02-04:00", "accession_no": "0001193125-26-135334", "url": "https://www.sec.gov/Archives/edgar/data/1238734/000119312526135334/xslF345X06/ownership.xml", "ingested_at": "2026-04-04T22:54:22.903382"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "WALKER JOHN KENT", "role": "President, Global Affairs, CLO", "transactions": [{"date": "2026-03-27", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 2677.0, "price": 273.91, "total_value": 733257.0700000001, "post_transaction_shares": 58124.0, "is_10b5_1_planned": false}, {"date": "2026-03-27", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1516.0, "price": 274.93, "total_value": 416793.88, "post_transaction_shares": 56608.0, "is_10b5_1_planned": false}, {"date": "2026-03-27", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1400.0, "price": 276.21, "total_value": 386694.0, "post_transaction_shares": 55208.0, "is_10b5_1_planned": false}, {"date": "2026-03-27", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 2100.0, "price": 277.42, "total_value": 582582.0, "post_transaction_shares": 53108.0, "is_10b5_1_planned": false}, {"date": "2026-03-27", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1300.0, "price": 278.3, "total_value": 361790.0, "post_transaction_shares": 51808.0, "is_10b5_1_planned": false}, {"date": "2026-03-31", "code": "G", "direction": "OTHER (D)", "shares": 8993.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 23508.0, "is_10b5_1_planned": false}, {"date": "2026-03-31", "code": "G", "direction": "OTHER (A)", "shares": 8993.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 60801.0, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "GOOG", "form_type": "4", "filed_at": "2026-03-31T20:39:05-04:00", "accession_no": "0001193125-26-135258", "url": "https://www.sec.gov/Archives/edgar/data/1652044/000119312526135258/xslF345X06/ownership.xml", "ingested_at": "2026-04-04T22:54:23.480449"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "ARNOLD FRANCES", "role": "Director", "transactions": [{"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 102.0, "price": 275.19, "total_value": 28069.38, "post_transaction_shares": 18316.0, "is_10b5_1_planned": false}]}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_HON_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_HON_2026-04-04.jsonl new file mode 100644 index 0000000..00baeb1 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_HON_2026-04-04.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "HON", "form_type": "4", "filed_at": "2026-04-02T17:57:33-04:00", "accession_no": "0000773840-26-000025", "url": "https://www.sec.gov/Archives/edgar/data/773840/000077384026000025/xslF345X06/wk-form4_1775167050.xml", "ingested_at": "2026-04-04T22:54:42.309982"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Flint Deborah", "role": "Other", "transactions": []}} +{"metadata": {"ticker": "HON", "form_type": "4", "filed_at": "2026-04-02T17:56:37-04:00", "accession_no": "0000773840-26-000024", "url": "https://www.sec.gov/Archives/edgar/data/773840/000077384026000024/xslF345X06/wk-form4_1775166995.xml", "ingested_at": "2026-04-04T22:54:42.895683"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "ANGOVE DUNCAN", "role": "Other", "transactions": []}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_IBM_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_IBM_2026-04-04.jsonl new file mode 100644 index 0000000..7ffbd9f --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_IBM_2026-04-04.jsonl @@ -0,0 +1,13 @@ +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01T17:11:35-04:00", "accession_no": "0001630253-26-000003", "url": "https://www.sec.gov/Archives/edgar/data/51143/000163025326000003/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-04T22:54:48.742964"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Laguarta Ramon", "role": "Director", "transactions": []}} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01T17:10:34-04:00", "accession_no": "0001804183-26-000004", "url": "https://www.sec.gov/Archives/edgar/data/51143/000180418326000004/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-04T22:54:49.319678"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Brown Marianne Catherine", "role": "Director", "transactions": []}} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01T17:09:51-04:00", "accession_no": "0001738987-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/51143/000173898726000002/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-04T22:54:49.890485"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Buberl Thomas", "role": "Director", "transactions": []}} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01T17:09:00-04:00", "accession_no": "0001183474-26-000003", "url": "https://www.sec.gov/Archives/edgar/data/51143/000118347426000003/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-04T22:54:50.474380"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "FARR DAVID N", "role": "Director", "transactions": []}} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01T17:08:11-04:00", "accession_no": "0001453149-26-000006", "url": "https://www.sec.gov/Archives/edgar/data/51143/000145314926000006/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-04T22:54:51.046789"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Gorsky Alex", "role": "Director", "transactions": []}} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01T17:05:39-04:00", "accession_no": "0001769389-26-000003", "url": "https://www.sec.gov/Archives/edgar/data/51143/000176938926000003/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-04T22:54:51.631365"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "HOWARD MICHELLE J", "role": "Director", "transactions": []}} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01T17:04:56-04:00", "accession_no": "0001269971-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/51143/000126997126000002/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-04T22:54:52.223698"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "LIVERIS ANDREW N", "role": "Director", "transactions": []}} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01T17:04:16-04:00", "accession_no": "0001731814-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/51143/000173181426000002/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-04T22:54:52.813351"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "MCNABB FREDERICK WILLIAM III", "role": "Director", "transactions": []}} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01T17:03:36-04:00", "accession_no": "0001771933-26-000005", "url": "https://www.sec.gov/Archives/edgar/data/51143/000177193326000005/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-04T22:54:53.392704"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Miebach Michael", "role": "Director", "transactions": []}} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01T17:02:53-04:00", "accession_no": "0001628797-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/51143/000162879726000002/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-04T22:54:53.968188"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "VOSER PETER R.", "role": "Director", "transactions": []}} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01T17:02:18-04:00", "accession_no": "0001223690-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/51143/000122369026000002/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-04T22:54:54.572877"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "WADDELL FREDERICK H", "role": "Director", "transactions": []}} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01T17:01:34-04:00", "accession_no": "0001196985-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/51143/000119698526000002/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-04T22:54:55.150928"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "ZOLLAR ALFRED W", "role": "Director", "transactions": []}} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01T17:00:51-04:00", "accession_no": "0001765271-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/51143/000176527126000002/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-04T22:54:55.747804"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Pollack Martha E", "role": "Director", "transactions": []}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_INTC_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_INTC_2026-04-04.jsonl new file mode 100644 index 0000000..65bac53 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_INTC_2026-04-04.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "INTC", "form_type": "8-K", "filed_at": "2026-04-03T12:50:37-04:00", "accession_no": "0000050863-26-000069", "url": "https://www.sec.gov/Archives/edgar/data/50863/000005086326000069/intc-20260330.htm", "ingested_at": "2026-04-04T22:54:47.308119"}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS", "parsed_data": {"is_chunked": true, "item_chunks": {"5.02": "Item 5.02    Departure of Directors or Certain Officers; Election of Directors; Appointment of Certain Officers; Compensatory Arrangements of Certain Officers.\n\nOn March 30,2026, Intel Corporation determined that April Miller Boise, Intel’s Executive Vice President and Chief Legal Officer, will separate from Intel effective as of June 1, 2026. Upon her departure on June 1, 2026, Ms. Miller Boise will be entitled to severance benefits in accordance with the terms and conditions of the Intel Corporation Executive Severance Plan, as previously disclosed, in exchange for a release of claims in favor of Intel.", "9.01": "Item 9.01     Financial Statements and Exhibits.\n\n(d)     Exhibits.\n\nThe following exhibits are provided as part of this report:\n\n| | | | | | |\n| --- | --- | --- | --- | --- | --- |\n| | | | | | |\n| Exhibit Number | | | Description | | |\n| 104 | | | Cover Page Interactive Data File, formatted in Inline XBRL and included as Exhibit 101. | | |\n\n---"}}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_INTU_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_INTU_2026-04-04.jsonl new file mode 100644 index 0000000..5b4b609 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_INTU_2026-04-04.jsonl @@ -0,0 +1,6 @@ +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03T16:51:34-04:00", "accession_no": "0001628280-26-023706", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023706/xslF345X06/wk-form4_1775249487.xml", "ingested_at": "2026-04-04T22:54:38.419929"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Goodarzi Sasan K", "role": "CEO, President and Director", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 653.529, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 14264.957, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 893.612, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 15158.569, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 802.006, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 15960.575, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 863.013, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 16823.588, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 30.832, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 16854.42, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 1277.861, "price": 432.38, "total_value": 552521.5391800001, "post_transaction_shares": 15576.559, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03T16:50:20-04:00", "accession_no": "0001628280-26-023704", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023704/xslF345X06/wk-form4_1775249417.xml", "ingested_at": "2026-04-04T22:54:39.027084"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "McLean Kerry J", "role": "EVP, Gen. Counsel & Corp. Sec.", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 244.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 28657.7666, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 236.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 28893.7666, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 199.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 29092.7666, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 170.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 29262.7666, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 301.627, "price": 432.38, "total_value": 130417.48226, "post_transaction_shares": 28961.1396, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03T16:48:01-04:00", "accession_no": "0001628280-26-023701", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023701/xslF345X06/wk-form4_1775249278.xml", "ingested_at": "2026-04-04T22:54:39.614244"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Hotz Lauren D", "role": "SVP, Chief Accounting Officer", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 41.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 2055.7352, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 104.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 2159.7352, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 97.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 2256.7352, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 88.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 2344.7352, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 120.548, "price": 432.38, "total_value": 52122.54424, "post_transaction_shares": 2224.1872, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03T16:46:29-04:00", "accession_no": "0001628280-26-023698", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023698/xslF345X06/wk-form4_1775249186.xml", "ingested_at": "2026-04-04T22:54:40.203764"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Hilliard Caryl Lyn", "role": "EVP, People and Places", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 122.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 23018.008, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 110.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 23128.008, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 87.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 23215.008, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 150.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 23365.008, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 212.093, "price": 432.38, "total_value": 91704.77133999999, "post_transaction_shares": 23152.915, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03T16:45:28-04:00", "accession_no": "0001628280-26-023696", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023696/xslF345X06/wk-form4_1775249122.xml", "ingested_at": "2026-04-04T22:54:40.778129"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Hanebrink Anton", "role": "EVP, Corp Strategy and Dev", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 348.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 29953.249, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 252.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 30205.249, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 224.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 30429.249, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 418.253, "price": 432.38, "total_value": 180844.23213999998, "post_transaction_shares": 30010.996, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03T16:39:06-04:00", "accession_no": "0001628280-26-023690", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023690/xslF345X06/wk-form4_1775248743.xml", "ingested_at": "2026-04-04T22:54:41.363317"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Aujla Sandeep", "role": "EVP and CFO", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 2665.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 3239.1366, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 346.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 3585.1366, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 349.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 3934.1366, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 1725.362, "price": 432.38, "total_value": 746012.02156, "post_transaction_shares": 2208.7746, "is_10b5_1_planned": false}]}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_MDLZ_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_MDLZ_2026-04-04.jsonl new file mode 100644 index 0000000..e69de29 diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_NFLX_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_NFLX_2026-04-04.jsonl new file mode 100644 index 0000000..b5751c8 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_NFLX_2026-04-04.jsonl @@ -0,0 +1,13 @@ +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-03T16:07:32-04:00", "accession_no": "0001543133-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000154313326000002/xslF345X06/wk-form4_1775246849.xml", "ingested_at": "2026-04-04T22:54:27.690770"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Neumann Spencer Adam", "role": "Chief Financial Officer", "transactions": [{"date": "2026-04-02", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 7770.0, "price": 38.105, "total_value": 296075.85, "post_transaction_shares": 81557.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 20860.0, "price": 36.408, "total_value": 759470.88, "post_transaction_shares": 102417.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 28630.0, "price": 98.0, "total_value": 2805740.0, "post_transaction_shares": 73787.0, "is_10b5_1_planned": true}]}} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02T18:02:54-04:00", "accession_no": "0001065280-26-000136", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000136/xslF345X06/wk-form4_1775167371.xml", "ingested_at": "2026-04-04T22:54:28.265373"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "KILGORE LESLIE J", "role": "Other", "transactions": []}} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02T18:02:46-04:00", "accession_no": "0001065280-26-000135", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000135/xslF345X06/wk-form4_1775167364.xml", "ingested_at": "2026-04-04T22:54:28.839154"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Masiyiwa Strive", "role": "Other", "transactions": []}} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02T18:02:38-04:00", "accession_no": "0001065280-26-000134", "url": "https://www.sec.gov/Archives/edgar/data/1033331/000106528026000134/xslF345X06/wk-form4_1775167354.xml", "ingested_at": "2026-04-04T22:54:29.443415"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "HASTINGS REED", "role": "Other", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 420550.0, "price": 9.437, "total_value": 3968730.3499999996, "post_transaction_shares": 424490.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 152047.0, "price": 95.015, "total_value": 14446745.705, "post_transaction_shares": 272443.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 247923.0, "price": 95.6767, "total_value": 23720454.4941, "post_transaction_shares": 24520.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 20580.0, "price": 96.6601, "total_value": 1989264.858, "post_transaction_shares": 3940.0, "is_10b5_1_planned": true}]}} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02T18:02:28-04:00", "accession_no": "0001065280-26-000133", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000133/xslF345X06/wk-form4_1775167345.xml", "ingested_at": "2026-04-04T22:54:30.038969"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Sweeney Anne M", "role": "Other", "transactions": []}} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02T18:02:20-04:00", "accession_no": "0001065280-26-000132", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000132/xslF345X06/wk-form4_1775167337.xml", "ingested_at": "2026-04-04T22:54:30.617313"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "MATHER ANN", "role": "Other", "transactions": []}} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02T18:01:52-04:00", "accession_no": "0001065280-26-000131", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000131/xslF345X06/wk-form4_1775167309.xml", "ingested_at": "2026-04-04T22:54:31.210332"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Dopfner Mathias", "role": "Other", "transactions": []}} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02T18:01:44-04:00", "accession_no": "0001065280-26-000130", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000130/xslF345X06/wk-form4_1775167302.xml", "ingested_at": "2026-04-04T22:54:31.787519"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Karbowski Jeffrey William", "role": "Chief Accounting Officer", "transactions": []}} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02T18:01:36-04:00", "accession_no": "0001065280-26-000129", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000129/xslF345X06/wk-form4_1775167293.xml", "ingested_at": "2026-04-04T22:54:32.363920"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "SMITH BRADFORD L", "role": "Other", "transactions": []}} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02T18:01:30-04:00", "accession_no": "0001065280-26-000128", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000128/xslF345X06/wk-form4_1775167286.xml", "ingested_at": "2026-04-04T22:54:32.939871"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "RICE SUSAN E", "role": "Other", "transactions": []}} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02T18:01:23-04:00", "accession_no": "0001065280-26-000127", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000127/xslF345X06/wk-form4_1775167280.xml", "ingested_at": "2026-04-04T22:54:33.516613"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "BARTON RICHARD N", "role": "Other", "transactions": []}} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02T18:01:07-04:00", "accession_no": "0001065280-26-000126", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000126/xslF345X06/wk-form4_1775167264.xml", "ingested_at": "2026-04-04T22:54:34.100797"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Mertz Elinor", "role": "Other", "transactions": []}} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02T16:04:17-04:00", "accession_no": "0001082906-26-000012", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000108290626000012/xslF345X06/form4.xml", "ingested_at": "2026-04-04T22:54:34.673370"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Hoag Jay C", "role": "Other", "transactions": []}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_PANW_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_PANW_2026-04-04.jsonl new file mode 100644 index 0000000..df6ee38 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_PANW_2026-04-04.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "PANW", "form_type": "4", "filed_at": "2026-04-03T16:30:29-04:00", "accession_no": "0001882285-26-000007", "url": "https://www.sec.gov/Archives/edgar/data/1327567/000188228526000007/xslF345X06/ownership.xml", "ingested_at": "2026-04-04T22:55:01.436892"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Paul Josh D.", "role": "Chief Accounting Officer", "transactions": [{"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 947.0, "price": 160.32, "total_value": 151823.03999999998, "post_transaction_shares": 84236.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1100.0, "price": 161.4, "total_value": 177540.0, "post_transaction_shares": 83136.0, "is_10b5_1_planned": true}]}} +{"metadata": {"ticker": "PANW", "form_type": "4", "filed_at": "2026-04-03T16:30:26-04:00", "accession_no": "0001852540-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/1327567/000185254026000002/xslF345X06/ownership.xml", "ingested_at": "2026-04-04T22:55:02.015659"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Golechha Dipak", "role": "EVP, Chief Financial Officer", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 200.0, "price": 157.81, "total_value": 31562.0, "post_transaction_shares": 155050.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1300.0, "price": 160.039, "total_value": 208050.69999999998, "post_transaction_shares": 153750.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 3500.0, "price": 160.704, "total_value": 562464.0, "post_transaction_shares": 150250.0, "is_10b5_1_planned": true}]}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_QCOM_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_QCOM_2026-04-04.jsonl new file mode 100644 index 0000000..139e887 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_QCOM_2026-04-04.jsonl @@ -0,0 +1,3 @@ +{"metadata": {"ticker": "QCOM", "form_type": "4", "filed_at": "2026-04-02T17:23:11-04:00", "accession_no": "0000804328-26-000051", "url": "https://www.sec.gov/Archives/edgar/data/804328/000080432826000051/xslF345X06/edgardoc.xml", "ingested_at": "2026-04-04T22:54:36.438677"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Grech Patricia Y", "role": "SVP, Chief Accounting Officer", "transactions": [{"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 85.0, "price": 125.5, "total_value": 10667.5, "post_transaction_shares": 192.0, "is_10b5_1_planned": true}]}} +{"metadata": {"ticker": "QCOM", "form_type": "4", "filed_at": "2026-04-02T16:08:27-04:00", "accession_no": "0000804328-26-000049", "url": "https://www.sec.gov/Archives/edgar/data/804328/000080432826000049/xslF345X06/edgardoc.xml", "ingested_at": "2026-04-04T22:54:37.033688"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "MCLAUGHLIN MARK D", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 538.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 12849.8312, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "QCOM", "form_type": "4", "filed_at": "2026-04-02T16:08:15-04:00", "accession_no": "0000804328-26-000048", "url": "https://www.sec.gov/Archives/edgar/data/804328/000080432826000048/xslF345X06/edgardoc.xml", "ingested_at": "2026-04-04T22:54:37.607779"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "TRICOIRE JEAN-PASCAL", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 262.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 13481.4716, "is_10b5_1_planned": false}]}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_SBUX_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_SBUX_2026-04-04.jsonl new file mode 100644 index 0000000..ed803fc --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_SBUX_2026-04-04.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "SBUX", "form_type": "8-K", "filed_at": "2026-04-02T16:55:33-04:00", "accession_no": "0000829224-26-000064", "url": "https://www.sec.gov/Archives/edgar/data/829224/000082922426000064/sbux-20260402.htm", "ingested_at": "2026-04-04T22:55:00.161523"}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS", "parsed_data": {"is_chunked": true, "item_chunks": {"7.01": "Item 7.01    Regulation FD Disclosure.\n\nAs previously disclosed on November 3, 2025, Starbucks entered an agreement to form a joint venture with Boyu Capital. On April 2, 2026, Starbucks announced that, following the satisfaction of all necessary closing conditions, it completed the transaction. Pursuant to the transaction, funds managed by Boyu Capital have acquired a 60% interest in Starbucks retail operations in China. Starbucks retains a 40% interest and will serve as the owner and licensor of the Starbucks global brand.\n\nA copy of the press release issued is furnished as Exhibit 99.1 to this Form 8-K.\n\nThe information contained in Item 7.01 of this report, including the information in Exhibit 99.1, is furnished pursuant to Item 7.01 of Form 8-K and shall not be deemed “filed” for the purposes of Section 18 of the Securities Exchange Act of 1934, as amended, or otherwise subject to the liabilities of that section. Furthermore, the information in Item 7.01 of this report, including the information in Exhibit 99.1 attached to this report, shall not be deemed to be incorporated by reference in the filings of Starbucks Corporation under the Securities Act of 1933, as amended.", "9.01": "Item 9.01Financial Statements and Exhibits.\n\n(d) Exhibits.\n\n| | | | | | | | | |\n| --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| | | | | | | | | |\n| Exhibit No. | | | | | | Description | | |\n| 99.1 | | | | | | Press Release, dated April 2, 2026 | | |\n| 104 | | | | | | Cover Page Interactive Data File (formatted as inline XBRL) | | |\n\n---"}}} +{"metadata": {"ticker": "SBUX", "form_type": "8-K", "filed_at": "2026-03-30T09:15:22-04:00", "accession_no": "0000829224-26-000058", "url": "https://www.sec.gov/Archives/edgar/data/829224/000082922426000058/sbux-20260325.htm", "ingested_at": "2026-04-04T22:55:00.764230"}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS", "parsed_data": {"is_chunked": true, "item_chunks": {"5.07": "Item 5.07 Submission of Matters to a Vote of Security Holders.\n\nOn March 25, 2026, Starbucks Corporation (the “Company”) held its 2026 Annual Meeting of Shareholders (the “Annual Meeting”). The matters submitted to a vote at the Annual Meeting and the voting results of such matters are as follows:\n\nProposal 1 - Election of Directors\n\nThe Company’s shareholders elected each of the eleven directors nominated by the Company’s Board of Directors to serve until the 2027 Annual Meeting of Shareholders or until their successors are duly elected and qualified. The following is a breakdown of the voting results:\n\n| | | | | | | | | | | | | | | |\n| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| | | | | | | | | | | | | | | |\n| Name of Nominee | | | For | | | Against | | | Withheld | | | Broker Non-Votes | | |\n| Ritch Allison | | | 846,955,724 | | | 28,832,837 | | | 1,081,482 | | | 127,972,619 | | |\n| Andy Campion | | | 764,749,951 | | | 110,976,652 | | | 1,143,440 | | | 127,972,619 | | |\n| Beth Ford | | | 808,145,942 | | | 66,979,908 | | | 1,744,193 | | | 127,972,619 | | |\n| Jørgen Vig Knudstorp | | | 828,586,462 | | | 46,185,327 | | | 2,098,254 | | | 127,972,619 | | |\n| Marissa Mayer | | | 867,967,230 | | | 7,925,365 | | | 977,448 | | | 127,972,619 | | |\n| Neal Mohan | | | 865,313,815 | | | 10,401,952 | | | 1,154,276 | | | 127,972,619 | | |\n| Dambisa Moyo | | | 864,744,438 | | | 11,015,863 | | | 1,109,742 | | | 127,972,619 | | |\n| Brian Niccol | | | 830,353,482 | | | 43,094,658 | | | 3,421,903 | | | 127,972,619 | | |\n| Daniel Servitje | | | 841,710,171 | | | 33,992,034 | | | 1,167,838 | | | 127,972,619 | | |\n| Mike Sievert | | | 863,809,451 | | | 11,894,524 | | | 1,166,068 | | | 127,972,619 | | |\n| Wei Zhang | | | 855,876,306 | | | 19,854,913 | | | 1,138,824 | | | 127,972,619 | | |\n\nProposal 2 - Advisory Resolution on Executive Compensation\n\nAt the Annual Meeting, the shareholders approved, on a nonbinding, advisory basis, the compensation paid to the Company’s named executive officers. The following is a breakdown of the voting results:\n\n| | | | | | | | | | | | |\n| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| | | | | | | | | | | | |\n| For | | | Against | | | Abstain | | | Broker Non-Votes | | |\n| 774,932,476 | | | 99,362,557 | | | 2,575,010 | | | 127,972,619 | | |\n\nProposal 3 - Ratification of the Selection of Deloitte & Touche LLP as the Company’s Independent Registered Public Accounting Firm for Fiscal Year 2026\n\nAt the Annual Meeting, the shareholders approved the ratification of the selection of Deloitte & Touche LLP as the Company’s independent registered public accounting firm for the fiscal year ending September 27, 2026. The following is a breakdown of the voting results:\n\n| | | | | | | | | | | | |\n| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| | | | | | | | | | | | |\n| For | | | Against | | | Abstain | | | Broker Non-Votes | | |\n| 965,325,253 | | | 38,304,225 | | | 1,213,184 | | | —— | | |\n\nProposal 4 - Shareholder Proposal Requesting Supermajority Shareholder Voting Requirements be Replaced with Majority Voting Requirements\n\nAt the Annual Meeting, the shareholders approved a shareholder proposal requesting supermajority shareholder voting requirements be replaced with majority voting requirements. The following is a breakdown of the voting results:\n\n| | | | | | | | | | | | |\n| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| | | | | | | | | | | | |\n| For | | | Against | | | Abstain | | | Broker Non-Votes | | |\n| 823,985,324 | | | 17,573,051 | | | 30,866,556 | | | 132,323,108 | | |\n\n---\n\nProposal 5 - Shareholder Proposal Requesting Adoption of an Independent Board Chair Policy\n\nAt the Annual Meeting, the shareholders did not approve a shareholder proposal requesting adoption of an independent board chair policy. The following is a breakdown of the voting results:\n\n| | | | | | | | | | | | |\n| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| | | | | | | | | | | | |\n| For | | | Against | | | Abstain | | | Broker Non-Votes | | |\n| 107,793,749 | | | 763,797,502 | | | 5,278,792 | | | 127,972,619 | | |\n\nProposal 6 - Shareholder Proposal Requesting a Report on the Company’s Apparent Exclusion of Detransitioning in its Healthcare Coverage\n\nAt the Annual Meeting, the shareholders did not approve a shareholder proposal requesting a report on the Company’s apparent exclusion of detransitioning in its healthcare coverage. The following is a breakdown of the voting results:\n\n| | | | | | | | | | | | |\n| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| | | | | | | | | | | | |\n| For | | | Against | | | Abstain | | | Broker Non-Votes | | |\n| 8,169,593 | | | 861,170,343 | | | 7,530,107 | | | 127,972,619 | | |\n\nProposal 7 - Shareholder Proposal Requesting a Report on Median Compensation and Benefits Gaps as They Address Reproductive and Gender Dysphoria Care\n\nAt the Annual Meeting, the shareholders did not approve a shareholder proposal requesting a report on median compensation and benefits gaps as they address reproductive and gender dysphoria care. The following is a breakdown of the voting results:\n\n| | | | | | | | | | | | |\n| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| | | | | | | | | | | | |\n| For | | | Against | | | Abstain | | | Broker Non-Votes | | |\n| 5,153,879 | | | 864,501,617 | | | 7,214,547 | | | 127,972,619 | | |\n\nProposal 8 - Shareholder Proposal Requesting a Report on the Company’s Use of Diagnostic Tools Created by Politicized Corporate Partners\n\nAt the Annual Meeting, the shareholders did not approve a shareholder proposal requesting a report on the Company’s use of diagnostic tools created by politicized corporate partners. The following is a breakdown of the voting results:\n\n| | | | | | | | | | | | |\n| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| | | | | | | | | | | | |\n| For | | | Against | | | Abstain | | | Broker Non-Votes | | |\n| 6,335,450 | | | 863,459,994 | | | 7,074,599 | | | 127,972,619 | | |\n\nProposal 9 - Shareholder Proposal Requesting a Report on the Risks of the Company Excluding Religious Charities from its Employee-Gift Match Program\n\nAt the Annual Meeting, the shareholders did not approve a shareholder proposal requesting a report on the risks of the Company excluding religious charities from its employee-gift match program. The following is a breakdown of the voting results:\n\n| | | | | | | | | | | | |\n| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| | | | | | | | | | | | |\n| For | | | Against | | | Abstain | | | Broker Non-Votes | | |\n| 5,749,240 | | | 864,268,337 | | | 6,852,466 | | | 127,972,619 | | |\n\nThe above proposals are further described in the Company’s definitive proxy statement on Schedule 14A filed with the U.S. Securities and Exchange Commission on January 26, 2026.\n\n---"}}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_TMUS_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_TMUS_2026-04-04.jsonl new file mode 100644 index 0000000..00dd2ad --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_TMUS_2026-04-04.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "TMUS", "form_type": "8-K", "filed_at": "2026-03-31T16:35:02-04:00", "accession_no": "0001193125-26-134731", "url": "https://www.sec.gov/Archives/edgar/data/1283699/000119312526134731/d136365d8k.htm", "ingested_at": "2026-04-04T22:54:35.624295"}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS", "parsed_data": {"is_chunked": true, "item_chunks": {"8.01": "Item 8.01. | Other Events. |\n\nOn March 31, 2026, following the previous repayment of certain legacy indebtedness, T-Mobile USA, Inc. (“TMUSA”), a wholly-owned subsidiary of T-Mobile US, Inc. (“TMUS”), elected to release the guarantees of certain subsidiaries under its $10 billion revolving credit agreement pursuant to the terms thereof, resulting in a corresponding release under the indentures dated April 28, 2013, April 9, 2020 and September 15, 2022, governing its outstanding senior notes. As a result, following the release, the obligors under TMUSA’s revolving credit agreement and outstanding senior notes now consist of TMUSA, as issuer or borrower, and each of TMUS, Sprint LLC, Sprint Capital Corporation and Sprint Communications LLC, as guarantors. Corresponding subsidiary guarantor releases were also effected under other TMUSA debt facilities, including its export credit agency facilities and unsecured short-term commercial paper program.\n\n---"}}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_TSLA_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_TSLA_2026-04-04.jsonl new file mode 100644 index 0000000..52eecbe --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_TSLA_2026-04-04.jsonl @@ -0,0 +1,3 @@ +{"metadata": {"ticker": "TSLA", "form_type": "4", "filed_at": "2026-04-02T20:08:52-04:00", "accession_no": "0001972928-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/1318605/000197292826000002/xslF345X06/edgardoc.xml", "ingested_at": "2026-04-04T22:54:24.292686"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Zhu Xiaotong", "role": "SVP", "transactions": [{"date": "2026-03-31", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 20000.0, "price": 20.57, "total_value": 411400.0, "post_transaction_shares": 20000.0, "is_10b5_1_planned": false}]}} +{"metadata": {"ticker": "TSLA", "form_type": "8-K", "filed_at": "2026-04-02T09:07:13-04:00", "accession_no": "0001628280-26-022956", "url": "https://www.sec.gov/Archives/edgar/data/1318605/000162828026022956/tsla-20260402.htm", "ingested_at": "2026-04-04T22:54:24.871733"}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS", "parsed_data": {"is_chunked": true, "item_chunks": {"2.02": "Item 2.02    Results of Operations and Financial Condition.\n\nOn April 2, 2026, Tesla, Inc. published the press release which is attached hereto as Exhibit 99.1 and is incorporated herein by reference.\n\nThis information is intended to be furnished under Item 2.02 of Form 8-K and shall not be deemed “filed” for purposes of Section 18 of the Securities Exchange Act of 1934, as amended (the “Exchange Act”), or incorporated by reference in any filing under the Securities Act of 1933, as amended, or the Exchange Act as shall be expressly set forth by specific reference in such a filing.", "9.01": "Item 9.01    Financial Statements and Exhibits.\n\n(d)Exhibits.\n\n| | | | | | | | | |\n| --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| | | | | | | | | |\n| Exhibit No. | | | | | | Description | | |\n| | | | | | | | | |\n| 99.1 | | | | | | Press release of Tesla, Inc., dated April 2, 2026. | | |\n| 104 | | | | | | Cover Page Interactive Data File (embedded within the Inline XBRL document). | | |\n\n---"}}} +{"metadata": {"ticker": "TSLA", "form_type": "4", "filed_at": "2026-04-01T19:00:13-04:00", "accession_no": "0001104659-26-038682", "url": "https://www.sec.gov/Archives/edgar/data/1318605/000110465926038682/xslF345X06/tm2610684-1_4seq1.xml", "ingested_at": "2026-04-04T22:54:25.463712"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Wilson-Thompson Kathleen", "role": "Other", "transactions": [{"date": "2026-03-30", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 40000.0, "price": 14.99, "total_value": 599600.0, "post_transaction_shares": 59669.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 2000.0, "price": 352.833, "total_value": 705666.0, "post_transaction_shares": 57669.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1640.0, "price": 353.658, "total_value": 579999.12, "post_transaction_shares": 56029.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1800.0, "price": 354.802, "total_value": 638643.6000000001, "post_transaction_shares": 54229.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 2481.0, "price": 355.644, "total_value": 882352.764, "post_transaction_shares": 51748.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 2360.0, "price": 356.794, "total_value": 842033.84, "post_transaction_shares": 49388.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1120.0, "price": 357.839, "total_value": 400779.68, "post_transaction_shares": 48268.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 520.0, "price": 358.77, "total_value": 186560.4, "post_transaction_shares": 47748.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1880.0, "price": 360.181, "total_value": 677140.2799999999, "post_transaction_shares": 45868.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1000.0, "price": 361.035, "total_value": 361035.0, "post_transaction_shares": 44868.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 2320.0, "price": 362.142, "total_value": 840169.44, "post_transaction_shares": 42548.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 4001.0, "price": 363.083, "total_value": 1452695.083, "post_transaction_shares": 38547.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 3927.0, "price": 363.947, "total_value": 1429219.869, "post_transaction_shares": 34620.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 560.0, "price": 364.888, "total_value": 204337.28, "post_transaction_shares": 34060.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 120.0, "price": 365.897, "total_value": 43907.64, "post_transaction_shares": 33940.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 80.0, "price": 366.855, "total_value": 29348.4, "post_transaction_shares": 33860.0, "is_10b5_1_planned": true}]}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_VRTX_2026-04-04.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_VRTX_2026-04-04.jsonl new file mode 100644 index 0000000..6edfe0c --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-04/patched_VRTX_2026-04-04.jsonl @@ -0,0 +1,3 @@ +{"metadata": {"ticker": "VRTX", "form_type": "4", "filed_at": "2026-04-03T16:53:51-04:00", "accession_no": "0000875320-26-000157", "url": "https://www.sec.gov/Archives/edgar/data/875320/000087532026000157/xslF345X06/wk-form4_1775249628.xml", "ingested_at": "2026-04-04T22:54:58.343666"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Liu Joy", "role": "EVP and Chief Legal Officer", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 978.0, "price": 449.17, "total_value": 439288.26, "post_transaction_shares": 21833.0, "is_10b5_1_planned": true}]}} +{"metadata": {"ticker": "VRTX", "form_type": "4", "filed_at": "2026-03-31T16:10:23-04:00", "accession_no": "0000875320-26-000149", "url": "https://www.sec.gov/Archives/edgar/data/875320/000087532026000149/xslF345X06/wk-form4_1774987818.xml", "ingested_at": "2026-04-04T22:54:58.915828"}, "raw_text": "XML_PARSED_SUCCESSFULLY", "parsed_data": {"reporting_owner": "Bozic Carmen", "role": "EVP and CMO", "transactions": [{"date": "2026-03-27", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 2329.0, "price": 450.95, "total_value": 1050262.55, "post_transaction_shares": 33076.0, "is_10b5_1_planned": true}]}} +{"metadata": {"ticker": "VRTX", "form_type": "8-K", "filed_at": "2026-03-31T16:03:47-04:00", "accession_no": "0000875320-26-000147", "url": "https://www.sec.gov/Archives/edgar/data/875320/000087532026000147/vrtx-20260331.htm", "ingested_at": "2026-04-04T22:54:59.488007"}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS", "parsed_data": {"is_chunked": true, "item_chunks": {"8.01": "Item 8.01. Other Events.\n\nVertex Pharmaceuticals Incorporated (the “Company”) has completed the submission to the U.S. Food and Drug Administration (the “FDA”) of its rolling Biologics Licensing Application (“BLA”) for potential accelerated approval of povetacicept for the treatment of immunoglobulin A nephropathy (“IgAN”) in adults. The Company used a priority review voucher and therefore expects the FDA review of the povetacicept BLA to be expedited to six months from the date of the FDA’s acceptance of the BLA versus the typical ten-month review.\n\nSpecial Note Regarding Forward-Looking Statements\n\nThis Current Report on Form 8-K contains forward-looking statements that are subject to risks, uncertainties and other factors including statements regarding the expected duration of the FDA review of the povetacicept BLA and potential for accelerated approval of povetacicept for the treatment of IgAN. While the Company believes the forward-looking statements contained in this communication are accurate, these forward-looking statements represent the beliefs of the Company only as of the date of this communication, and there are a number of risks and uncertainties that could cause actual events or results to differ materially from those expressed or implied by such forward-looking statements.\n\nForward-looking statements are subject to certain risks, uncertainties, or other factors that are difficult to predict and could cause actual events or results to differ materially from those indicated in any such statements due to a number of risks and uncertainties. Forward-looking statements in this communication should be evaluated together with the many risks and uncertainties that affect the Company's business. Those risks and uncertainties include, among other things, that we may be unable to obtain or be delayed in obtaining regulatory approval and other risks listed under the heading “Risk Factors” and the other cautionary factors discussed in the Company's periodic reports filed with the Securities and Exchange Commission (the “SEC”), including the Company's annual report on Form 10-K for the year ended December 31, 2025, its quarterly reports on Form 10-Q, and its current reports on Form 8-K, all of which are available for free through the Company's website at www.vrtx.com and on the SEC’s website at www.sec.gov. You should not place undue reliance on these statements. All forward-looking statements are based on information currently available to the Company, and the Company disclaims any obligation to update the information contained in this communication as new information becomes available, except as required by law.\n\n---"}}} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/_SUMMARY.json b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/_SUMMARY.json new file mode 100644 index 0000000..7c03d73 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/_SUMMARY.json @@ -0,0 +1,122 @@ +{ + "date": "2026-04-08", + "total_filings": 87, + "ticker_breakdown": { + "MAR": { + "4": 1, + "8-K": 0 + }, + "GOOGL": { + "4": 1, + "8-K": 1 + }, + "AMAT": { + "4": 1, + "8-K": 0 + }, + "GOOG": { + "4": 1, + "8-K": 1 + }, + "MDLZ": { + "4": 2, + "8-K": 0 + }, + "AVGO": { + "4": 0, + "8-K": 2 + }, + "AAPL": { + "4": 3, + "8-K": 0 + }, + "VRTX": { + "4": 1, + "8-K": 0 + }, + "AMZN": { + "4": 1, + "8-K": 0 + }, + "MELI": { + "4": 0, + "8-K": 1 + }, + "PANW": { + "4": 2, + "8-K": 0 + }, + "MU": { + "4": 3, + "8-K": 1 + }, + "IBM": { + "4": 13, + "8-K": 0 + }, + "INTU": { + "4": 6, + "8-K": 0 + }, + "NFLX": { + "4": 13, + "8-K": 0 + }, + "COST": { + "4": 1, + "8-K": 0 + }, + "CRWD": { + "4": 0, + "8-K": 1 + }, + "CMCSA": { + "4": 6, + "8-K": 0 + }, + "REGN": { + "4": 1, + "8-K": 1 + }, + "TSLA": { + "4": 2, + "8-K": 1 + }, + "INTC": { + "4": 0, + "8-K": 1 + }, + "SBUX": { + "4": 0, + "8-K": 1 + }, + "HON": { + "4": 2, + "8-K": 0 + }, + "CSX": { + "4": 1, + "8-K": 0 + }, + "CDNS": { + "4": 1, + "8-K": 0 + }, + "ADI": { + "4": 6, + "8-K": 0 + }, + "CSCO": { + "4": 1, + "8-K": 1 + }, + "BKNG": { + "4": 0, + "8-K": 3 + }, + "QCOM": { + "4": 3, + "8-K": 0 + } + } +} \ No newline at end of file diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_AAPL.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_AAPL.jsonl new file mode 100644 index 0000000..af07fb6 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_AAPL.jsonl @@ -0,0 +1,3 @@ +{"metadata": {"ticker": "AAPL", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001140361-26-013192", "url": "https://www.sec.gov/Archives/edgar/data/320193/000114036126013192/xslF345X06/form4.xml", "ingested_at": "2026-04-08T12:48:26.662928"}, "parsed_data": {"reporting_owner": "O'BRIEN DEIRDRE", "role": "Senior Vice President", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 64317.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 201127.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 34315.0, "price": 255.63, "total_value": 8771943.45, "post_transaction_shares": 166812.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 20338.0, "price": 255.12, "total_value": 5188630.5600000005, "post_transaction_shares": 146474.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 9664.0, "price": 255.82, "total_value": 2472244.48, "post_transaction_shares": 136810.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "AAPL", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001140361-26-013191", "url": "https://www.sec.gov/Archives/edgar/data/320193/000114036126013191/xslF345X06/form4.xml", "ingested_at": "2026-04-08T12:48:26.888609"}, "parsed_data": {"reporting_owner": "Khan Sabih", "role": "COO", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 64317.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 1107212.0, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 33317.0, "price": 255.63, "total_value": 8516824.709999999, "post_transaction_shares": 1073895.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "AAPL", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001140361-26-013190", "url": "https://www.sec.gov/Archives/edgar/data/320193/000114036126013190/xslF345X06/form4.xml", "ingested_at": "2026-04-08T12:48:27.106687"}, "parsed_data": {"reporting_owner": "COOK TIMOTHY D", "role": "Chief Executive Officer", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 131576.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 3411994.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 66627.0, "price": 255.63, "total_value": 17031860.009999998, "post_transaction_shares": 3345367.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 5087.0, "price": 251.25, "total_value": 1278108.75, "post_transaction_shares": 3340280.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 9147.0, "price": 252.11, "total_value": 2306050.17, "post_transaction_shares": 3331133.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1878.0, "price": 253.13, "total_value": 475378.14, "post_transaction_shares": 3329255.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 16083.0, "price": 254.37, "total_value": 4091032.71, "post_transaction_shares": 3313172.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 28188.0, "price": 255.17, "total_value": 7192731.96, "post_transaction_shares": 3284984.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 4566.0, "price": 256.0, "total_value": 1168896.0, "post_transaction_shares": 3280418.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_ADI.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_ADI.jsonl new file mode 100644 index 0000000..c45a6d1 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_ADI.jsonl @@ -0,0 +1,6 @@ +{"metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001201872-26-000008", "url": "https://www.sec.gov/Archives/edgar/data/6281/000120187226000008/xslF345X06/wk-form4_1775247205.xml", "ingested_at": "2026-04-08T12:48:56.199337"}, "parsed_data": {"reporting_owner": "ROCHE VINCENT", "role": "Chair & CEO", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 10000.0, "price": 94.41, "total_value": 944100.0, "post_transaction_shares": 177825.875, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 10000.0, "price": 318.14, "total_value": 3181400.0, "post_transaction_shares": 167825.875, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0001768266-26-000004", "url": "https://www.sec.gov/Archives/edgar/data/6281/000176826626000004/xslF345X06/wk-form4_1775074685.xml", "ingested_at": "2026-04-08T12:48:56.418972"}, "parsed_data": {"reporting_owner": "Sondel Michael", "role": "CAO (principal acct. officer)", "transactions": [{"date": "2026-03-30", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 405.712, "price": 303.1, "total_value": 122971.30720000001, "post_transaction_shares": 14513.578, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0001201872-26-000006", "url": "https://www.sec.gov/Archives/edgar/data/6281/000120187226000006/xslF345X06/wk-form4_1775074650.xml", "ingested_at": "2026-04-08T12:48:56.676905"}, "parsed_data": {"reporting_owner": "ROCHE VINCENT", "role": "Chair & CEO", "transactions": [{"date": "2026-03-30", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 27027.168, "price": 303.1, "total_value": 8191934.620800001, "post_transaction_shares": 167825.875, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0002044259-26-000007", "url": "https://www.sec.gov/Archives/edgar/data/6281/000204425926000007/xslF345X06/wk-form4_1775074599.xml", "ingested_at": "2026-04-08T12:48:56.894938"}, "parsed_data": {"reporting_owner": "Nakamura Katsufumi", "role": "SVP, Chief Customer Officer", "transactions": [{"date": "2026-03-30", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 120.901, "price": 303.1, "total_value": 36645.0931, "post_transaction_shares": 12145.04, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0000006281-26-000037", "url": "https://www.sec.gov/Archives/edgar/data/6281/000000628126000037/xslF345X06/wk-form4_1775074566.xml", "ingested_at": "2026-04-08T12:48:57.102825"}, "parsed_data": {"reporting_owner": "Jain Vivek", "role": "EVP, Global Operations", "transactions": [{"date": "2026-03-30", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 6386.093, "price": 303.1, "total_value": 1935624.7883000001, "post_transaction_shares": 42089.474, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0001685760-26-000004", "url": "https://www.sec.gov/Archives/edgar/data/6281/000168576026000004/xslF345X06/wk-form4_1775074528.xml", "ingested_at": "2026-04-08T12:48:57.316644"}, "parsed_data": {"reporting_owner": "Cotter Martin", "role": "SVP, Vertical Business Units", "transactions": [{"date": "2026-03-30", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 3880.571, "price": 303.1, "total_value": 1176201.0701000001, "post_transaction_shares": 50524.884, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_AMAT.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_AMAT.jsonl new file mode 100644 index 0000000..30ab908 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_AMAT.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "AMAT", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001628280-26-023379", "url": "https://www.sec.gov/Archives/edgar/data/6951/000162828026023379/xslF345X06/wk-form4_1775169858.xml", "ingested_at": "2026-04-08T12:48:46.179586"}, "parsed_data": {"reporting_owner": "Sanders Adam", "role": "Corp. Controller & CAO", "transactions": [{"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 125.0, "price": 353.8, "total_value": 44225.0, "post_transaction_shares": 4548.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_AMZN.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_AMZN.jsonl new file mode 100644 index 0000000..c292d36 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_AMZN.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "AMZN", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001018724-26-000010", "url": "https://www.sec.gov/Archives/edgar/data/1018724/000101872426000010/xslF345X06/wk-form4_1775248886.xml", "ingested_at": "2026-04-08T12:48:28.351458"}, "parsed_data": {"reporting_owner": "Herrington Douglas J", "role": "CEO Worldwide Amazon Stores", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1000.0, "price": 210.5, "total_value": 210500.0, "post_transaction_shares": 520361.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_AVGO.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_AVGO.jsonl new file mode 100644 index 0000000..37b7adc --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_AVGO.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "AVGO", "form_type": "8-K", "filed_at": "2026-04-06", "accession_no": "0001193125-26-144028", "url": "https://www.sec.gov/Archives/edgar/data/1730168/000119312526144028/d87999d8k.htm", "ingested_at": "2026-04-08T12:48:32.383033"}, "parsed_data": {"is_chunked": true, "item_chunks": {"8.01": "Item 8.01 | Other Events. |\n\nBroadcom Inc. (“Broadcom”) and Google LLC (“Google”) have entered into a Long Term Agreement for Broadcom to develop and supply custom Tensor Processing Units (“TPUs”) for Google’s future generations of TPUs and a Supply Assurance Agreement for Broadcom to supply networking and other components to be used in Google’s next-generation AI racks through up to 2031.\n\nSeparately, Broadcom, Google and Anthropic PBC (“Anthropic”) have expanded their current strategic collaboration under which Anthropic, beginning in 2027, will access through Broadcom approximately 3.5 gigawatts as part of the multiple gigawatts of next generation TPU-based AI compute capacity committed by Anthropic. The consumption of such expanded AI compute capacity by Anthropic is dependent on Anthropic’s continued commercial success. In connection with this deployment, the parties are in discussions with certain operational and financial partners.\n\nCautionary Note Regarding Forward-Looking Statements\n\nThis Current Report on Form 8-K contains forward-looking statements (including within the meaning of Section 21E of the Securities Exchange Act of 1934, as amended, and Section 27A of the Securities Act of 1933, as amended). These forward-looking statements are based on current expectations and beliefs of Broadcom’s management, current information available to Broadcom’s management, and current market trends and market conditions, and involve risks and uncertainties that may cause actual results to differ materially from those contained in the forward-looking statements. Accordingly, undue reliance should not be placed on such statements. All forward-looking statements are qualified in their entirety by reference to the risk factors discussed under the heading “Risk Factors” in Broadcom’s Annual Report on Form 10-K for the year ended November 2, 2025, Quarterly Report on Form 10-Q for the period ended February 1, 2026 and any subsequent reports that are filed with the Securities and Exchange Commission and include some important risk factors that may affect future results. Broadcom undertakes no intent or obligation to publicly update or revise the forward-looking statements made in this Current Report on Form 8-K, except as required by law.\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} +{"metadata": {"ticker": "AVGO", "form_type": "8-K", "filed_at": "2026-04-02", "accession_no": "0001193125-26-140574", "url": "https://www.sec.gov/Archives/edgar/data/1730168/000119312526140574/d109450d8k.htm", "ingested_at": "2026-04-08T12:48:32.628969"}, "parsed_data": {"is_chunked": true, "item_chunks": {"5.02": "Item 5.02 | Departure of Directors or Certain Officers; Election of Directors; Appointment of Certain Officers; Compensatory Arrangements of Certain Officers. |\n\nChief Financial Officer Transition\n\nOn March 30, 2026, Kirsten M. Spears notified Broadcom Inc. (the “Company”) of her retirement and resigned from her position as Chief Financial Officer and Chief Accounting Officer of the Company, effective as of June 12, 2026.\n\nOn March 30, 2026, the Board of Directors of the Company (the “Board”) appointed Amie Thuener to succeed Ms. Spears as the Chief Financial Officer of the Company, effective as of June 12, 2026. The employment of Ms. Thuener with the Company is expected to commence on May 4, 2026 and she will assume the role of Chief Financial Officer following the retirement of Ms. Spears on June 12, 2026.\n\nMs. Thuener, age 51, has served as Vice President, Corporate Controller and Chief Accounting Officer of Alphabet Inc. since 2018. Ms. Thuener held several senior finance positions at Alphabet from 2013 to 2018, including as Vice President and Chief Accountant. Prior to joining Alphabet, Ms. Thuener was at PricewaterhouseCoopers LLP from 1996 to 2012 and held several senior management positions, including as Managing Director, Transaction Services. Ms. Thuener is a Certified Public Accountant and a Chartered Global Management Accountant.\n\nThere are no family relationships between Ms. Thuener and any director or executive officer of the Company as defined in Item 401(d) of Regulation S-K, and Ms. Thuener has no direct or indirect material interest in any transaction or proposed transaction required to be disclosed pursuant to Item 404(a) of Regulation S-K.\n\nKirsten M. Spears Transition and Consulting Agreement\n\nIn connection with the retirement of Ms. Spears, the Company entered into a transition and consulting agreement with Ms. Spears, dated as of April 1, 2026 (the “Transition Agreement”).\n\nThe Transition Agreement provides that, following the conclusion of Ms. Spears’ employment with the Company on June 12, 2026, she will provide consulting services to the Company, as reasonably requested by the Chief Executive Officer of the Company, until March 15, 2027, unless the consulting period terminates earlier in accordance with the terms of the Transition Agreement. During the consulting period, Ms. Spears’ outstanding equity awards will continue to vest in accordance with their terms (provided that the performance-based equity awards will in no event vest at a level exceeding target). Ms. Spears will not receive any other compensation during the consulting period. The Transition Agreement includes a general release of claims in favor of the Company.\n\nAmie Thuener Offer Letter and Equity Awards\n\nIn connection with her employment with the Company and appointment as Chief Financial Officer of the Company, effective as of June 12, 2026, the Company entered into an offer letter with Ms. Thuener, dated as of March 30, 2026, which sets forth the material terms of her employment and compensation (the “Offer Letter”).\n\nPursuant to the Offer Letter, Ms. Thuener will receive an annual base salary of $700,000 and will be eligible to participate in the Company’s annual performance bonus plan with a target bonus opportunity of 100% of her base salary. Ms. Thuener will also receive a $1,000,000 sign-on cash bonus, payable within 30 days following the commencement of her employment.\n\nThe Offer Letter further provides that, subject to the approval of the Compensation Committee of the Board and Ms. Thuener’s continued employment through the applicable grant date, Ms. Thuener will be granted equity awards under the Company’s 2012 Stock Incentive Plan consisting of (i) 50,000 restricted stock units (“RSUs”) and (ii) 50,000 performance stock units (“PSUs”) at target. The equity awards are expected to be granted on June 15, 2026.\n\nThe RSUs will vest in equal quarterly installments over a four-year period following the grant date, subject to Ms. Thuener’s continued employment through each applicable vesting date. The PSUs will vest annually over a four-year period across four overlapping performance periods (March 2, 2026 through March 1, 2027, March 2, 2026 through March 1, 2028, March 2, 2026 through March 1, 2029 and March 2, 2026 through March 1, 2030) based on the Company’s total stockholder return relative to the S&P 500 and the Company’s absolute total stockholder return for the applicable performance period, in each case subject to Ms. Thuener’s continued employment through the anniversary of the grant date immediately following the end of each applicable performance period. The maximum vesting for the PSUs is 200% of the total target number of shares. The equity awards will be subject to the other terms and conditions set forth in the Company’s 2012 Stock Incentive Plan and the applicable award agreements.\n\n---\n\nIn addition, Ms. Thuener is expected to enter into the Company’s standard form of indemnification and advancement agreement and a severance benefit agreement on terms and conditions materially consistent with those applicable to Ms. Spears pursuant to her severance benefit agreement, as described in the Company’s definitive proxy statement filed with the U.S. Securities and Exchange Commission on March 2, 2026.\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_BKNG.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_BKNG.jsonl new file mode 100644 index 0000000..27b8476 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_BKNG.jsonl @@ -0,0 +1,3 @@ +{"metadata": {"ticker": "BKNG", "form_type": "8-K", "filed_at": "2026-04-02", "accession_no": "0000950157-26-000465", "url": "https://www.sec.gov/Archives/edgar/data/1075531/000095015726000465/form8-k.htm", "ingested_at": "2026-04-08T12:48:50.322210"}, "parsed_data": {"is_chunked": true, "item_chunks": {"5.03": "Item 5.03. Amendments to Articles of incorporation or Bylaws; Change in Fiscal Year.\n\nOn April 2, 2026, Booking Holdings Inc. (the “Company”) filed an amendment to its Restated Certificate of Incorporation with the Delaware Secretary of State to effect the\npreviously announced twenty-five-for-one forward stock split of the Company’s common stock and to proportionately increase the number of shares of the Company’s authorized common stock from 1,000,000,000 to 25,000,000,000. The amendment, which became\neffective at 4:01 p.m. Eastern Time on April 2, 2026, is filed as Exhibit 3.1 to this Current Report on Form 8-K. Trading is expected to commence on a split-adjusted basis at market open on Monday, April 6, 2026.", "9.01": "Item 9.01. Financial Statements and Exhibits.\n\n| | | |\n| --- | --- | --- |\n| (d) Exhibits | | |\n| Exhibit Number | | Description |\n| | | |\n| 3.1 | | Amendment to Restated Certificate of Incorporation of Booking Holdings Inc., dated April 2, 2026. |\n| 104 | | Cover Page Interactive Data File - the cover page interactive data file does not appear in the Interactive Data File because its XBRL tags are embedded within the Inline XBRL document. |\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} +{"metadata": {"ticker": "BKNG", "form_type": "8-K", "filed_at": "2026-04-02", "accession_no": "0001075531-26-000014", "url": "https://www.sec.gov/Archives/edgar/data/1075531/000107553126000014/bkng-20260402.htm", "ingested_at": "2026-04-08T12:48:50.613430"}, "parsed_data": {"is_chunked": true, "item_chunks": {"5.02": "Item 5.02.    Departure of Directors or Certain Officers; Election of Directors; Appointment\n\nof Certain Officers; Compensatory Arrangements of Certain Officers.\n\nOn April 2, 2026, Booking Holdings Inc. (the \"Company\") announced that it has appointed Caroline Sullivan as its Senior Vice President, Chief Accounting Officer, and Controller effective as of April 29, 2026. Ms. Sullivan, age 57, served as Vice President, Procurement and Real Estate of Elevance Health, a health insurance company, from June 2025 to March 2026. Prior to this, Ms. Sullivan was Senior Vice President, Chief Accounting Officer and Corporate Controller at Moody's Corporation, a global risk assessment firm, from December 2018 to March 2025. Ms. Sullivan also served as Global Banking Controller of Bank of America from 2017 to 2018. Earlier in her career, she held various finance positions with Morgan Stanley and Allied Irish Bank. Ms. Sullivan began her career at Ernst and Young and is a Certified Public Accountant.\n\nIn connection with Ms. Sullivan's appointment, she and the Company entered into an employment agreement with, among others, the following terms:\n\n•an initial annual base salary of $525,000;\n\n•a target annual bonus of 75% of base salary;\n\n•a grant of restricted stock units (\"RSUs\") expected to be made in May 2026 with a grant date fair value of $1,000,000;\n\n•a grant of performance share units (\"PSUs\") expected to be made in March 2027 with a grant date fair value at target of $1,000,000;\n\n•a new hire grant of RSUs expected to be made in May 2026 with a grant date fair value of $1,000,000;\n\n•a signing bonus of $300,000; and\n\n•in the event of her termination without cause, subject to the execution of a release of claims, severance benefits including payments equal to one times her base salary and target annual bonus, a pro-rated portion of any earned bonus for the year of termination if employment is terminated after June 30 of the then current year, health benefits for a period of 12 months, and any earned bonus for a prior completed year that has not yet been paid.\n\nMs. Sullivan's RSUs and new hire RSUs will each vest in three equal annual installments on each of the first three anniversaries of the grant date, subject to her continuous service from the date of grant until the vesting date, with pro rata vesting upon a termination without cause or due to disability, and full vesting upon a termination due to death. Ms. Sullivan's PSU award will vest subject to such service and performance-based vesting provisions generally consistent with those applicable to similarly-situated executives who receive PSU grants in 2027. The awards will be subject to the terms of the respective award agreements for awards under the Company’s 1999 Omnibus Plan.\n\nIn connection with Ms. Sullivan's appointment, the Company and Ms. Sullivan have also entered into a Non-Competition and Non-Solicitation Agreement and an Employee Confidentiality and Assignment Agreement.\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} +{"metadata": {"ticker": "BKNG", "form_type": "8-K", "filed_at": "2026-04-01", "accession_no": "0001075531-26-000012", "url": "https://www.sec.gov/Archives/edgar/data/1075531/000107553126000012/bkng-20260401.htm", "ingested_at": "2026-04-08T12:48:50.961407"}, "parsed_data": {"is_chunked": true, "item_chunks": {"5.02": "Item 5.02.    Departure of Directors or Certain Officers; Election of Directors; Appointment\n\nof Certain Officers; Compensatory Arrangements of Certain Officers.\n\nAppointment of Director\n\nOn April 1, 2026, Mr. Kurt Sievers was appointed to the Board of Directors (the \"Board\") of Booking Holdings Inc. (the \"Company\") and will be joining the Board's Corporate Governance Committee.\n\nMr. Sievers served as President and Chief Executive Officer of NXP Semiconductors N.V., a Netherlands-based semiconductor company (\"NXP\"), from 2020 until his retirement in 2025. He previously served as President beginning in 2018 and joined NXP’s Executive Management Team in 2009. Mr. Sievers currently serves on the board of directors of Capgemini SE, a multinational information technology services and consulting company, and is a member of its Strategy & CSR and Compensation Committees. He also serves on the supervisory board of Daimler Truck Holding AG, a commercial vehicle manufacturer.\n\nIn consideration of his services as a member of the Company's Board and any Board committees, Mr. Sievers will be compensated in accordance with the Company's non-employee director compensation program as in effect from time to time.\n\nRetirement of Director\n\nMs. Lynn Radakovich has informed the Company that she has decided to retire from the Board, effective at the Company's Annual Meeting in June 2026 (the \"Annual Meeting\"), and therefore is not standing for re-election at the Annual Meeting. The Company and the Board express their appreciation to Ms. Radakovich for her dedicated service.", "7.01": "Item 7.01    Regulation FD Disclosure.\n\nA copy of the press release announcing Mr. Sievers's appointment and Ms. Radakovich's retirement is furnished with this Current Report as Exhibit 99.1.\n\nThe information furnished herewith pursuant to this Item 7.01 of this Current Report shall not be deemed to be \"filed\" for purposes of Section 18 of the Securities Exchange Act of 1934, as amended (the \"Exchange Act\"), or otherwise subject to the liabilities of that section, and shall not be incorporated by reference into any registration statement or other document under the Securities Act of 1933, as amended, or the Exchange Act, except as shall be expressly set forth by specific reference in such filing.", "9.01": "Item 9.01.           Financial Statements and Exhibits.\n\n(d)    Exhibits\n\n| | | | | | | | | | | | | | | |\n| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| | | | | | | | | | | | | | | |\n| Exhibit Number | | | Description | | | | | | | | | | | |\n| | | | | | | | | | | | | | | |\n| 99.1 | | | Press Release, dated April 1, 2026. | | | | | | | | | | | |\n| 104 | | | Cover Page Interactive Data File - the cover page interactive data file does not appear in the Interactive Data File because its XBRL tags are embedded within the Inline XBRL document. | | | | | | | | | | | |\n| | | | | | | | | | | | | | | |\n| | | | | | | | | | | | | | | |\n| | | | | | | | | | | | | | | |\n| | | | | | | | | | | | | | | |\n| | | | | | | | | | | | | | | |\n| | | | | | | | | | | | | | | |\n| | | | | | | | | | | | | | | |\n| | | | | | | | | | | | | | | |\n| | | | | | | | | | | | | | | |\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_CDNS.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_CDNS.jsonl new file mode 100644 index 0000000..4673785 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_CDNS.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "CDNS", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0000813672-26-000040", "url": "https://www.sec.gov/Archives/edgar/data/813672/000081367226000040/xslF345X06/wk-form4_1775243708.xml", "ingested_at": "2026-04-08T12:48:59.459023"}, "parsed_data": {"reporting_owner": "Cunningham Paul", "role": "Sr. Vice President", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1000.0, "price": 280.19, "total_value": 280190.0, "post_transaction_shares": 128586.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_CMCSA.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_CMCSA.jsonl new file mode 100644 index 0000000..dc53233 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_CMCSA.jsonl @@ -0,0 +1,6 @@ +{"metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001225208-26-004342", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004342/xslF345X06/doc4.xml", "ingested_at": "2026-04-08T12:48:43.821475"}, "parsed_data": {"reporting_owner": "Murdock Daniel C.", "role": "EVP & Chief Accounting Officer", "transactions": [{"date": "2026-04-03", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 5268.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 64435.0497, "is_10b5_1_planned": false}, {"date": "2026-04-03", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 2073.0, "price": 27.93, "total_value": 57898.89, "post_transaction_shares": 62362.0497, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001225208-26-004203", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004203/xslF345X06/doc4.xml", "ingested_at": "2026-04-08T12:48:44.045592"}, "parsed_data": {"reporting_owner": "Smith Gordon", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 1176.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 9045.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001225208-26-004202", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004202/xslF345X06/doc4.xml", "ingested_at": "2026-04-08T12:48:44.268546"}, "parsed_data": {"reporting_owner": "Honickman Jeffrey A", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 1524.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 262583.021, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001225208-26-004201", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004201/xslF345X06/doc4.xml", "ingested_at": "2026-04-08T12:48:44.473523"}, "parsed_data": {"reporting_owner": "BREEN EDWARD D", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 697.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 56522.277, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001225208-26-004200", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004200/xslF345X06/doc4.xml", "ingested_at": "2026-04-08T12:48:44.697700"}, "parsed_data": {"reporting_owner": "Brady Louise F.", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 1176.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 32682.89, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001225208-26-004199", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004199/xslF345X06/doc4.xml", "ingested_at": "2026-04-08T12:48:44.896983"}, "parsed_data": {"reporting_owner": "Baltimore Thomas J Jr", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 1176.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 39043.493, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_COST.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_COST.jsonl new file mode 100644 index 0000000..5162c0e --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_COST.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "COST", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0000909832-26-000039", "url": "https://www.sec.gov/Archives/edgar/data/909832/000090983226000039/xslF345X06/form4.xml", "ingested_at": "2026-04-08T12:48:33.357291"}, "parsed_data": {"reporting_owner": "Frates Caton", "role": "Executive Vice President", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 700.0, "price": 993.0, "total_value": 695100.0, "post_transaction_shares": 5815.001, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_CRWD.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_CRWD.jsonl new file mode 100644 index 0000000..39c801f --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_CRWD.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "CRWD", "form_type": "8-K", "filed_at": "2026-04-06", "accession_no": "0001535527-26-000013", "url": "https://www.sec.gov/Archives/edgar/data/1535527/000153552726000013/crwd-20260406.htm", "ingested_at": "2026-04-08T12:49:01.938568"}, "parsed_data": {"is_chunked": true, "item_chunks": {"8.01": "Item 8.01 Other Events.\n\nOn April 6, 2026, the Company announced that its Board of Directors has approved the repurchase of up to an additional $500 million of the Company’s common stock, bringing the Company’s total repurchase authorization to $1.5 billion (together, the “Share Repurchase Program”). Under the Share Repurchase Program, the Company has repurchased 413,130 shares of its outstanding Class A common stock at an average price of $364.57 per share, for an aggregate purchase price of $150.6 million.\n\nThe Share Repurchase Program does not have a fixed expiration date and does not obligate the Company to acquire any specific number of shares. Repurchases may be made from time to time using a variety of methods, including open market purchases, privately negotiated transactions, Rule 10b5-1 trading plans and other means. The timing, manner, price and amount of any repurchases will be determined by the Company in its discretion and will depend on a variety of factors, including legal requirements, price and economic and market conditions. The Company currently expects to use the Share Repurchase Program opportunistically depending on the market price of the common stock and other factors, and there can be no assurance that any shares will be repurchased under the Share Repurchase Program.\n\nForward-Looking Statements\n\nThis Form 8-K contains forward-looking statements that involve risks and uncertainties, including statements regarding the Share Repurchase Program and the factors that will impact the amount and timing of purchases, if any, thereunder. A number of factors could cause outcomes to differ materially from our statements, including the risks and uncertainties included in our filings with the Securities and Exchange Commission, particularly under the caption “Risk Factors” in our most recently filed Annual Report on Form 10-K. Accordingly, you should not place undue reliance on these forward-looking statements. All forward-looking statements are based on information currently available to us, and we do not assume any obligation to update any statement to reflect changes in circumstances or our expectations.\n\n2\n\n---", "9.01": "Item 9.01    Financial Statements and Exhibits.\n\n(d) Exhibits\n\n| | | | | | | | | |\n| --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| | | | | | | | | |\n| Exhibit Number | | | | | | Description of Exhibit | | |\n| 99.1 | | | | | | Press release dated April 6, 2026 | | |\n| 104 | | | | | | Cover Page Interactive Data File - the cover page XBRL tags are embedded within the Inline XBRL document | | |\n\n3\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_CSCO.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_CSCO.jsonl new file mode 100644 index 0000000..84e8c0c --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_CSCO.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "CSCO", "form_type": "4", "filed_at": "2026-04-07", "accession_no": "0000858877-26-000052", "url": "https://www.sec.gov/Archives/edgar/data/858877/000085887726000052/xslF345X06/wk-form4_1775592372.xml", "ingested_at": "2026-04-08T12:48:37.663506"}, "parsed_data": {"reporting_owner": "Shimer Peter A", "role": "Other", "transactions": [{"date": "2026-04-06", "code": "A", "direction": "OTHER (A)", "shares": 2333.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 2333.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "CSCO", "form_type": "8-K", "filed_at": "2026-04-06", "accession_no": "0000858877-26-000048", "url": "https://www.sec.gov/Archives/edgar/data/858877/000085887726000048/csco-20260331.htm", "ingested_at": "2026-04-08T12:48:37.896486"}, "parsed_data": {"is_chunked": true, "item_chunks": {"5.02": "Item 5.02. | | | Departure of Directors or Certain Officers; Election of Directors; Appointment of Certain Officers; Compensatory Arrangements of Certain Officers. | | |\n\nDeparture of Director\n\nOn March 31, 2026, in light of the increased time and focus required of his new role as Chief Executive Officer of Verizon Communications Inc., Daniel H. Schulman notified Cisco Systems, Inc. (“Cisco”) of his decision to resign from the Board of Directors (\"Board\") of Cisco effective May 21, 2026.\n\nAppointment of Director\n\nOn April 4, 2026, the Board of Cisco appointed Peter A. Shimer as a member of the Board effective April 6, 2026. In connection with his appointment, the Board determined that Mr. Shimer is “independent” under the applicable listing standards of The Nasdaq Stock Market LLC. The Board has also appointed Mr. Shimer to serve as a member of the Audit Committee of the Board.\n\nIn connection with his service as a director, Mr. Shimer will receive Cisco’s standard non-employee director cash and equity compensation. Mr. Shimer will receive a pro rata portion of the $105,000 annual cash retainer, paid quarterly in arrears, for his service through the remaining portion of the year ending at Cisco's 2026 annual meeting of stockholders (the \"2026 Annual Meeting\"). Mr. Shimer will also receive a pro rata portion of the Audit Committee member annual cash retainer fees, paid quarterly in arrears, for service on such committee through the remaining portion of the year ending at the 2026 Annual Meeting. Non-employee directors may instead elect to receive the annual cash retainer, committee cash retainer fees or other cash fees in fully vested shares of Cisco common stock, fully vested deferred stock units that would be settled in shares after the non-employee director leaves the Board, or a deferred cash payment under the Cisco Systems, Inc. Deferred Compensation Plan. Upon his appointment, pursuant to the Board’s equity grant policy for non-employee directors, Mr. Shimer automatically received a fully vested initial non-employee director equity award under Cisco’s 2005 Stock Incentive Plan with a grant date fair value equal to a pro rata portion of $270,000 based on the portion of the year of his board service. Non-employee directors may elect to defer receipt of the equity award such that the award would be settled in shares after the non-employee director leaves the Board. Non-employee directors are also eligible to participate in Cisco’s charitable matching gifts program (for calendar year 2026, the maximum match amount is $25,000 for Cisco's non-employee directors).\n\nIn connection with his appointment, Mr. Shimer has entered into Cisco’s standard form of Indemnity Agreement with Cisco which provides for indemnification of an indemnitee to the fullest extent permitted by law. The foregoing description of the Indemnity Agreement does not purport to be complete and is qualified in its entirety by the full text of the form of Indemnity Agreement, which was filed with the Securities and Exchange Commission on January 25, 2021 as Exhibit 10.1 to Cisco’s Current Report on Form 8-K.\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_CSX.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_CSX.jsonl new file mode 100644 index 0000000..7c56a6c --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_CSX.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "CSX", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001193125-26-140177", "url": "https://www.sec.gov/Archives/edgar/data/277948/000119312526140177/xslF345X06/ownership.xml", "ingested_at": "2026-04-08T12:49:00.868872"}, "parsed_data": {"reporting_owner": "ANGEL STEPHEN F", "role": "President & CEO", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_GOOG.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_GOOG.jsonl new file mode 100644 index 0000000..25faec5 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_GOOG.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "GOOG", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001193125-26-142372", "url": "https://www.sec.gov/Archives/edgar/data/1652044/000119312526142372/xslF345X06/ownership.xml", "ingested_at": "2026-04-08T12:48:30.190015"}, "parsed_data": {"reporting_owner": "O'Toole Amie Thuener", "role": "VP, Chief Accounting Officer", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 617.0, "price": 289.63, "total_value": 178701.71, "post_transaction_shares": 10093.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "GOOG", "form_type": "8-K", "filed_at": "2026-04-02", "accession_no": "0001652044-26-000031", "url": "https://www.sec.gov/Archives/edgar/data/1652044/000165204426000031/goog-20260330.htm", "ingested_at": "2026-04-08T12:48:30.394411"}, "parsed_data": {"is_chunked": true, "item_chunks": {"5.02": "Item 5.02 Departure of Directors or Certain Officers; Election of Directors; Appointment of Certain Officers; Compensatory Arrangements of Certain Officers.\n\nOn March 30, 2026, Amie Thuener O'Toole notified Alphabet Inc. (the “Company”) of her resignation as Vice President, Corporate Controller and Principal Accounting Officer of the Company, effective April 9, 2026, to pursue another professional opportunity. Ms. O'Toole’s decision to resign did not result from any disagreement with the Company on any matter relating to the Company’s operations, policies, or practices.\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_GOOGL.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_GOOGL.jsonl new file mode 100644 index 0000000..065b61d --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_GOOGL.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "GOOGL", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001193125-26-142372", "url": "https://www.sec.gov/Archives/edgar/data/1652044/000119312526142372/xslF345X06/ownership.xml", "ingested_at": "2026-04-08T12:48:29.315822"}, "parsed_data": {"reporting_owner": "O'Toole Amie Thuener", "role": "VP, Chief Accounting Officer", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 617.0, "price": 289.63, "total_value": 178701.71, "post_transaction_shares": 10093.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "GOOGL", "form_type": "8-K", "filed_at": "2026-04-02", "accession_no": "0001652044-26-000031", "url": "https://www.sec.gov/Archives/edgar/data/1652044/000165204426000031/goog-20260330.htm", "ingested_at": "2026-04-08T12:48:29.521443"}, "parsed_data": {"is_chunked": true, "item_chunks": {"5.02": "Item 5.02 Departure of Directors or Certain Officers; Election of Directors; Appointment of Certain Officers; Compensatory Arrangements of Certain Officers.\n\nOn March 30, 2026, Amie Thuener O'Toole notified Alphabet Inc. (the “Company”) of her resignation as Vice President, Corporate Controller and Principal Accounting Officer of the Company, effective April 9, 2026, to pursue another professional opportunity. Ms. O'Toole’s decision to resign did not result from any disagreement with the Company on any matter relating to the Company’s operations, policies, or practices.\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_HON.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_HON.jsonl new file mode 100644 index 0000000..9f02f3a --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_HON.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "HON", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0000773840-26-000025", "url": "https://www.sec.gov/Archives/edgar/data/773840/000077384026000025/xslF345X06/wk-form4_1775167050.xml", "ingested_at": "2026-04-08T12:48:43.044450"}, "parsed_data": {"reporting_owner": "Flint Deborah", "role": "Other", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "HON", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0000773840-26-000024", "url": "https://www.sec.gov/Archives/edgar/data/773840/000077384026000024/xslF345X06/wk-form4_1775166995.xml", "ingested_at": "2026-04-08T12:48:43.247069"}, "parsed_data": {"reporting_owner": "ANGOVE DUNCAN", "role": "Other", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_IBM.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_IBM.jsonl new file mode 100644 index 0000000..a391368 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_IBM.jsonl @@ -0,0 +1,13 @@ +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0001630253-26-000003", "url": "https://www.sec.gov/Archives/edgar/data/51143/000163025326000003/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-08T12:48:46.706365"}, "parsed_data": {"reporting_owner": "Laguarta Ramon", "role": "Director", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0001804183-26-000004", "url": "https://www.sec.gov/Archives/edgar/data/51143/000180418326000004/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-08T12:48:46.946343"}, "parsed_data": {"reporting_owner": "Brown Marianne Catherine", "role": "Director", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0001738987-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/51143/000173898726000002/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-08T12:48:47.164648"}, "parsed_data": {"reporting_owner": "Buberl Thomas", "role": "Director", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0001183474-26-000003", "url": "https://www.sec.gov/Archives/edgar/data/51143/000118347426000003/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-08T12:48:47.446314"}, "parsed_data": {"reporting_owner": "FARR DAVID N", "role": "Director", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0001453149-26-000006", "url": "https://www.sec.gov/Archives/edgar/data/51143/000145314926000006/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-08T12:48:47.738627"}, "parsed_data": {"reporting_owner": "Gorsky Alex", "role": "Director", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0001769389-26-000003", "url": "https://www.sec.gov/Archives/edgar/data/51143/000176938926000003/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-08T12:48:47.993127"}, "parsed_data": {"reporting_owner": "HOWARD MICHELLE J", "role": "Director", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0001269971-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/51143/000126997126000002/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-08T12:48:48.200292"}, "parsed_data": {"reporting_owner": "LIVERIS ANDREW N", "role": "Director", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0001731814-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/51143/000173181426000002/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-08T12:48:48.492897"}, "parsed_data": {"reporting_owner": "MCNABB FREDERICK WILLIAM III", "role": "Director", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0001771933-26-000005", "url": "https://www.sec.gov/Archives/edgar/data/51143/000177193326000005/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-08T12:48:48.805919"}, "parsed_data": {"reporting_owner": "Miebach Michael", "role": "Director", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0001628797-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/51143/000162879726000002/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-08T12:48:49.059135"}, "parsed_data": {"reporting_owner": "VOSER PETER R.", "role": "Director", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0001223690-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/51143/000122369026000002/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-08T12:48:49.276566"}, "parsed_data": {"reporting_owner": "WADDELL FREDERICK H", "role": "Director", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0001196985-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/51143/000119698526000002/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-08T12:48:49.532260"}, "parsed_data": {"reporting_owner": "ZOLLAR ALFRED W", "role": "Director", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "IBM", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0001765271-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/51143/000176527126000002/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-08T12:48:49.820455"}, "parsed_data": {"reporting_owner": "Pollack Martha E", "role": "Director", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_INTC.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_INTC.jsonl new file mode 100644 index 0000000..9bf77f1 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_INTC.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "INTC", "form_type": "8-K", "filed_at": "2026-04-03", "accession_no": "0000050863-26-000069", "url": "https://www.sec.gov/Archives/edgar/data/50863/000005086326000069/intc-20260330.htm", "ingested_at": "2026-04-08T12:48:45.429994"}, "parsed_data": {"is_chunked": true, "item_chunks": {"5.02": "Item 5.02    Departure of Directors or Certain Officers; Election of Directors; Appointment of Certain Officers; Compensatory Arrangements of Certain Officers.\n\nOn March 30,2026, Intel Corporation determined that April Miller Boise, Intel’s Executive Vice President and Chief Legal Officer, will separate from Intel effective as of June 1, 2026. Upon her departure on June 1, 2026, Ms. Miller Boise will be entitled to severance benefits in accordance with the terms and conditions of the Intel Corporation Executive Severance Plan, as previously disclosed, in exchange for a release of claims in favor of Intel.", "9.01": "Item 9.01     Financial Statements and Exhibits.\n\n(d)     Exhibits.\n\nThe following exhibits are provided as part of this report:\n\n| | | | | | |\n| --- | --- | --- | --- | --- | --- |\n| | | | | | |\n| Exhibit Number | | | Description | | |\n| 104 | | | Cover Page Interactive Data File, formatted in Inline XBRL and included as Exhibit 101. | | |\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_INTU.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_INTU.jsonl new file mode 100644 index 0000000..8c7906d --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_INTU.jsonl @@ -0,0 +1,6 @@ +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023706", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023706/xslF345X06/wk-form4_1775249487.xml", "ingested_at": "2026-04-08T12:48:40.705654"}, "parsed_data": {"reporting_owner": "Goodarzi Sasan K", "role": "CEO, President and Director", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 653.529, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 14264.957, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 893.612, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 15158.569, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 802.006, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 15960.575, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 863.013, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 16823.588, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 30.832, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 16854.42, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 1277.861, "price": 432.38, "total_value": 552521.5391800001, "post_transaction_shares": 15576.559, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023704", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023704/xslF345X06/wk-form4_1775249417.xml", "ingested_at": "2026-04-08T12:48:40.933207"}, "parsed_data": {"reporting_owner": "McLean Kerry J", "role": "EVP, Gen. Counsel & Corp. Sec.", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 244.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 28657.7666, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 236.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 28893.7666, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 199.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 29092.7666, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 170.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 29262.7666, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 301.627, "price": 432.38, "total_value": 130417.48226, "post_transaction_shares": 28961.1396, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023701", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023701/xslF345X06/wk-form4_1775249278.xml", "ingested_at": "2026-04-08T12:48:41.133725"}, "parsed_data": {"reporting_owner": "Hotz Lauren D", "role": "SVP, Chief Accounting Officer", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 41.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 2055.7352, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 104.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 2159.7352, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 97.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 2256.7352, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 88.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 2344.7352, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 120.548, "price": 432.38, "total_value": 52122.54424, "post_transaction_shares": 2224.1872, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023698", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023698/xslF345X06/wk-form4_1775249186.xml", "ingested_at": "2026-04-08T12:48:41.343578"}, "parsed_data": {"reporting_owner": "Hilliard Caryl Lyn", "role": "EVP, People and Places", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 122.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 23018.008, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 110.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 23128.008, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 87.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 23215.008, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 150.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 23365.008, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 212.093, "price": 432.38, "total_value": 91704.77133999999, "post_transaction_shares": 23152.915, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023696", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023696/xslF345X06/wk-form4_1775249122.xml", "ingested_at": "2026-04-08T12:48:41.573994"}, "parsed_data": {"reporting_owner": "Hanebrink Anton", "role": "EVP, Corp Strategy and Dev", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 348.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 29953.249, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 252.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 30205.249, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 224.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 30429.249, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 418.253, "price": 432.38, "total_value": 180844.23213999998, "post_transaction_shares": 30010.996, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023690", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023690/xslF345X06/wk-form4_1775248743.xml", "ingested_at": "2026-04-08T12:48:41.795152"}, "parsed_data": {"reporting_owner": "Aujla Sandeep", "role": "EVP and CFO", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 2665.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 3239.1366, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 346.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 3585.1366, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 349.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 3934.1366, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 1725.362, "price": 432.38, "total_value": 746012.02156, "post_transaction_shares": 2208.7746, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_MAR.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_MAR.jsonl new file mode 100644 index 0000000..4122c8f --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_MAR.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "MAR", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0001225208-26-004132", "url": "https://www.sec.gov/Archives/edgar/data/1048286/000122520826004132/xslF345X06/doc4.xml", "ingested_at": "2026-04-08T12:49:02.493404"}, "parsed_data": {"reporting_owner": "LEWIS AYLWIN B", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 11.118, "price": 326.05, "total_value": 3625.0239, "post_transaction_shares": 12738.575, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_MDLZ.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_MDLZ.jsonl new file mode 100644 index 0000000..bc87077 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_MDLZ.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "MDLZ", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023648", "url": "https://www.sec.gov/Archives/edgar/data/1103982/000162828026023648/xslF345X06/wk-form4_1775247097.xml", "ingested_at": "2026-04-08T12:48:53.535143"}, "parsed_data": {"reporting_owner": "Lilak Stephanie", "role": "EVP and Chief People Officer", "transactions": [{"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 3218.0, "price": 57.07, "total_value": 183651.26, "post_transaction_shares": 24118.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "MDLZ", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023646", "url": "https://www.sec.gov/Archives/edgar/data/1103982/000162828026023646/xslF345X06/wk-form4_1775247057.xml", "ingested_at": "2026-04-08T12:48:53.778010"}, "parsed_data": {"reporting_owner": "Kuhn Volker", "role": "EVP and President, Europe", "transactions": [{"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 90.0, "price": 57.07, "total_value": 5136.3, "post_transaction_shares": 25820.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_MELI.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_MELI.jsonl new file mode 100644 index 0000000..8222cf0 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_MELI.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "MELI", "form_type": "8-K", "filed_at": "2026-04-03", "accession_no": "0001999371-26-007656", "url": "https://www.sec.gov/Archives/edgar/data/1099590/000199937126007656/meli_8k-033126.htm", "ingested_at": "2026-04-08T12:48:59.995354"}, "parsed_data": {"is_chunked": true, "item_chunks": {"5.02": "Item 5.02** | **Departure of Directors or Certain Officers; Election of Directors; Appointment of Certain Officers; Compensatory Arrangements of Certain Officers.** |\n\n**Establishment of Performance Goals under the 2026 Bonus Program**\n\nOn March 31, 2026, the Board of Directors (the “Board”) of\nMercadoLibre, Inc. (the “Company”) established the performance goals for the Company’s bonus program for the 2026 fiscal\nyear (the “2026 Bonus Program”). Under the 2026 Bonus Program, the bonus payout for each of Ariel Szarfsztejn (Chief Executive\nOfficer), Marcos Galperin (Executive Chairman), Osvaldo Giménez (Fintech President), Daniel Rabinovich (Technology & Operations\nPresident), and Martin de los Santos (EVP and Chief Financial Officer) (referred to below as “NEOs”) is based on achievement\nof Net revenues and financial income (in constant dollars), Income from operations (in constant dollars), Total payment volume - adjusted\n(the total sum of all transactions paid for using Mercado Pago, including marketplace and non-marketplace transactions, excluding peer-to-peer\ntransactions) (in constant dollars) and the Company’s Competitive Net Promoter Score. The Board has determined a target bonus for\neach NEO and applies an adjustment of up to + 50% or -50% to each bonus based upon the individual performance of each NEO.\n\nThe Board set each NEO’s target bonus under the 2026 Bonus Program\nas four months of base salary (33.33% of each NEO’s annual base salary).\n\n**Adoption of the 2026 Long Term Retention Program**\n\nOn March 31, 2026, the Board approved the adoption of the 2026 Long\nTerm Retention Program (the “2026 LTRP”) and, after taking into account a compensation competitiveness analysis carried out\nby the Company’s independent third-party compensation consultant, established the target award for each NEO under the 2026 LTRP.\nThe 2026 LTRP provides the NEOs, along with other members of senior management, with the opportunity to receive cash payments annually\nfor a period of six years (with the first payment occurring between January 1, 2027 and April 30, 2027, as determined by the Company),\nsubject to continued employment on each payment date (other than in specified circumstances). Each award to an NEO under the 2026 LTRP is deemed to have a Grant Date\n(as defined in the 2026 LTRP) of January 1, 2026. Under the 2026 LTRP, each NEO shall receive:\n\n| | | | |\n| --- | --- | --- | --- |\n| | ● | | 16.66% of half of his or her target 2026 LTRP award annually for a period of six years (with the first payment occurring between January 1, 2027 and April 30, 2027) (the “Annual Fixed Payment”); and |\n\n| | | | |\n| --- | --- | --- | --- |\n| | ● | | on each date the Company pays the Annual Fixed Payment, each NEO will also receive a payment equal to the product of (i) 16.66% of half of the NEO’s target 2026 LTRP award and (ii) the quotient of (a) the Applicable Year Stock Price (as defined below) over (b) the average closing price of the Company’s common stock on NASDAQ during the final 60 trading days of 2025. For purposes of the 2026 LTRP, the “Applicable Year Stock Price” is the average closing price of the Company’s common stock on NASDAQ during the final 60 trading days of the fiscal year preceding the fiscal year in which the applicable payment date occurs, for so long as our common stock is listed on NASDAQ. |\n\nThe target 2026 LTRP awards for our NEOs are set forth below.\n\n| | | | | | | |\n| --- | --- | --- | --- | --- | --- | --- |\n| Name | | Title | | Target 2026 LTRP Award (nominal) | | |\n| Ariel Szarfsztejn | | Chief Executive Officer | | $ | 14,000,000 | |\n| Osvaldo Giménez | | Fintech President | | $ | 10,000,000 | |\n| Daniel Rabinovich | | Technology & Operations President | | $ | 10,000,000 | |\n| Martin de los Santos | | Executive Vice President & Chief Financial Officer | | $ | 4,000,000 | |\n| Marcos Galperin | | Executive Chairman | | $ | 3,500,000 | |\n\n| |\n| --- |\n| |\n\nThe foregoing description of the 2026 LTRP does not purport to be complete\nand is qualified in its entirety by reference to the full text of the 2026 LTRP, which is filed as Exhibit 10.1 to this Current Report\non Form 8-K and is incorporated herein by reference.\n\n| | |\n| --- | --- |\n| **Item 9.01** | **Financial Statements and Exhibits.** |\n\n| | |\n| --- | --- |\n| (d) | *Exhibits.* |\n\nThe following exhibits are filed herewith.\n\n| | | | |\n| --- | --- | --- | --- |\n| **Exhibit** **Number** | | | **Description** |\n| | | | |\n| 10.1 | | | MercadoLibre, Inc. 2026 Long Term Retention Program |\n\n| |\n| --- |\n| |\n\n**EXHIBIT INDEX**\n\n| | | |\n| --- | --- | --- |\n| **Exhibit** **Number** | | **Description** |\n| | | |\n| 10.1 | | MercadoLibre, Inc. 2026 Long Term Retention Program |\n\n| |\n| --- |\n| |\n\n**SIGNATURES**\n\nPursuant to the requirements of the Securities Exchange\nAct of 1934, the registrant has duly caused this report to be signed on its behalf by the undersigned hereunto duly authorized.\n\n| | | | |\n| --- | --- | --- | --- |\n| | MercadoLibre, Inc. | | |\n| | | | |\n| Dated: April 3, 2026 | By: | /s/ Martin de los Santos | |\n| | Name: | Martin de los Santos | |\n| | Title: | Executive Vice President and Chief Financial Officer | |\n| | | | |\n\n \n\n| |\n| --- |\n| |"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_MU.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_MU.jsonl new file mode 100644 index 0000000..cc67761 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_MU.jsonl @@ -0,0 +1,4 @@ +{"metadata": {"ticker": "MU", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001632063-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/723125/000163206326000002/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-08T12:48:57.862487"}, "parsed_data": {"reporting_owner": "ARNZEN APRIL S", "role": "EVP and Chief People Officer", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 8630.0, "price": 345.13, "total_value": 2978471.9, "post_transaction_shares": 157107.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 5766.0, "price": 346.22, "total_value": 1996304.5200000003, "post_transaction_shares": 151341.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 604.0, "price": 346.83, "total_value": 209485.31999999998, "post_transaction_shares": 150737.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 25000.0, "price": 348.46, "total_value": 8711500.0, "post_transaction_shares": 125737.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "MU", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0002058769-26-000003", "url": "https://www.sec.gov/Archives/edgar/data/723125/000205876926000003/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-08T12:48:58.070656"}, "parsed_data": {"reporting_owner": "Liu Teyin M", "role": "Director", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 97.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 26007.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "MU", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001218363-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/723125/000121836326000002/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-08T12:48:58.298891"}, "parsed_data": {"reporting_owner": "SWAN ROBERT HOLMES", "role": "Director", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "MU", "form_type": "8-K", "filed_at": "2026-04-01", "accession_no": "0001104659-26-038249", "url": "https://www.sec.gov/Archives/edgar/data/723125/000110465926038249/tm2610810d1_8k.htm", "ingested_at": "2026-04-08T12:48:58.540588"}, "parsed_data": {"is_chunked": true, "item_chunks": {"8.01": "Item 8.01. Other Events.** | |\n\nOn March 31, 2026, Micron Technology, Inc. (the\n“Company”) issued a press release announcing the pricing of its cash tender offers for any and all of its outstanding 5.300%\nSenior Notes due 2031 (the “2031 Notes”), 5.650% Senior Notes due 2032 (the “2032 Notes”), 5.875% Senior Notes\ndue 2033 (the “2033A Notes”), 5.875% Senior Notes due 2033 (the “2033B Notes”), 5.800% Senior Notes due 2035 (the\n“2035A Notes”), and 6.050% Senior Notes due 2035 (the “2023B Notes”, and, together with the 2031 Notes, the 2032\nNotes, the 2033A Notes, the 2033B Notes and the 2035A Notes, the “Notes”), in connection with the Company’s previously\nannounced cash tender offers commenced on March 25, 2026.\n\nOn April 1, 2026, the Company issued a press release\nannouncing the expiration of its previously announced cash tender offers to purchase any and all of the Notes.\n\nCopies of the press releases are attached hereto\nas Exhibit 99.1 and Exhibit 99.2, respectively, and incorporated herein by reference.\n\n| | | |\n| --- | --- | --- |\n| **Item 9.01.** | | **Financial Statements and Exhibits.** |\n| | | |\n| | | (d) Exhibits. |\n| | | |\n| **Exhibit No.** | | **Description** |\n| 99.1 | | Press Release issued on March 31, 2026. |\n| 99.2 | | Press Release issued on April 1, 2026. |\n| 104 | | Cover Page Interactive Data File (embedded with the Inline XBRL document) |\n\n**SIGNATURE**\n\nPursuant to the requirements of the Securities Exchange Act of 1934,\nthe Registrant has duly caused this report to be signed on its behalf by the undersigned hereunto duly authorized.\n\n| | | |\n| --- | --- | --- |\n| | **MICRON TECHNOLOGY, INC.** | |\n| | | |\n| Date: April 1, 2026 | By: | /s/ Mark Murphy |\n| | Name: | Mark Murphy |\n| | Title: | Executive Vice President and Chief Financial Officer |"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_NFLX.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_NFLX.jsonl new file mode 100644 index 0000000..eada4d8 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_NFLX.jsonl @@ -0,0 +1,13 @@ +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001543133-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000154313326000002/xslF345X06/wk-form4_1775246849.xml", "ingested_at": "2026-04-08T12:48:34.271973"}, "parsed_data": {"reporting_owner": "Neumann Spencer Adam", "role": "Chief Financial Officer", "transactions": [{"date": "2026-04-02", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 7770.0, "price": 38.105, "total_value": 296075.85, "post_transaction_shares": 81557.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 20860.0, "price": 36.408, "total_value": 759470.88, "post_transaction_shares": 102417.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 28630.0, "price": 98.0, "total_value": 2805740.0, "post_transaction_shares": 73787.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001065280-26-000136", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000136/xslF345X06/wk-form4_1775167371.xml", "ingested_at": "2026-04-08T12:48:34.482708"}, "parsed_data": {"reporting_owner": "KILGORE LESLIE J", "role": "Other", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001065280-26-000135", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000135/xslF345X06/wk-form4_1775167364.xml", "ingested_at": "2026-04-08T12:48:34.705192"}, "parsed_data": {"reporting_owner": "Masiyiwa Strive", "role": "Other", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001065280-26-000134", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000134/xslF345X06/wk-form4_1775167354.xml", "ingested_at": "2026-04-08T12:48:34.906612"}, "parsed_data": {"reporting_owner": "HASTINGS REED", "role": "Other", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 420550.0, "price": 9.437, "total_value": 3968730.3499999996, "post_transaction_shares": 424490.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 152047.0, "price": 95.015, "total_value": 14446745.705, "post_transaction_shares": 272443.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 247923.0, "price": 95.6767, "total_value": 23720454.4941, "post_transaction_shares": 24520.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 20580.0, "price": 96.6601, "total_value": 1989264.858, "post_transaction_shares": 3940.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001065280-26-000133", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000133/xslF345X06/wk-form4_1775167345.xml", "ingested_at": "2026-04-08T12:48:35.108886"}, "parsed_data": {"reporting_owner": "Sweeney Anne M", "role": "Other", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001065280-26-000132", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000132/xslF345X06/wk-form4_1775167337.xml", "ingested_at": "2026-04-08T12:48:35.330733"}, "parsed_data": {"reporting_owner": "MATHER ANN", "role": "Other", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001065280-26-000131", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000131/xslF345X06/wk-form4_1775167309.xml", "ingested_at": "2026-04-08T12:48:35.535789"}, "parsed_data": {"reporting_owner": "Dopfner Mathias", "role": "Other", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001065280-26-000130", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000130/xslF345X06/wk-form4_1775167302.xml", "ingested_at": "2026-04-08T12:48:35.745631"}, "parsed_data": {"reporting_owner": "Karbowski Jeffrey William", "role": "Chief Accounting Officer", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001065280-26-000129", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000129/xslF345X06/wk-form4_1775167293.xml", "ingested_at": "2026-04-08T12:48:35.968973"}, "parsed_data": {"reporting_owner": "SMITH BRADFORD L", "role": "Other", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001065280-26-000128", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000128/xslF345X06/wk-form4_1775167286.xml", "ingested_at": "2026-04-08T12:48:36.170732"}, "parsed_data": {"reporting_owner": "RICE SUSAN E", "role": "Other", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001065280-26-000127", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000127/xslF345X06/wk-form4_1775167280.xml", "ingested_at": "2026-04-08T12:48:36.377176"}, "parsed_data": {"reporting_owner": "BARTON RICHARD N", "role": "Other", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001065280-26-000126", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000126/xslF345X06/wk-form4_1775167264.xml", "ingested_at": "2026-04-08T12:48:36.602115"}, "parsed_data": {"reporting_owner": "Mertz Elinor", "role": "Other", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001082906-26-000012", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000108290626000012/xslF345X06/form4.xml", "ingested_at": "2026-04-08T12:48:36.812885"}, "parsed_data": {"reporting_owner": "Hoag Jay C", "role": "Other", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_PANW.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_PANW.jsonl new file mode 100644 index 0000000..74db091 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_PANW.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "PANW", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001882285-26-000007", "url": "https://www.sec.gov/Archives/edgar/data/1327567/000188228526000007/xslF345X06/ownership.xml", "ingested_at": "2026-04-08T12:48:52.842465"}, "parsed_data": {"reporting_owner": "Paul Josh D.", "role": "Chief Accounting Officer", "transactions": [{"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 947.0, "price": 160.32, "total_value": 151823.03999999998, "post_transaction_shares": 84236.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1100.0, "price": 161.4, "total_value": 177540.0, "post_transaction_shares": 83136.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "PANW", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001852540-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/1327567/000185254026000002/xslF345X06/ownership.xml", "ingested_at": "2026-04-08T12:48:53.042265"}, "parsed_data": {"reporting_owner": "Golechha Dipak", "role": "EVP, Chief Financial Officer", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 200.0, "price": 157.81, "total_value": 31562.0, "post_transaction_shares": 155050.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1300.0, "price": 160.039, "total_value": 208050.69999999998, "post_transaction_shares": 153750.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 3500.0, "price": 160.704, "total_value": 562464.0, "post_transaction_shares": 150250.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_QCOM.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_QCOM.jsonl new file mode 100644 index 0000000..a7de1b0 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_QCOM.jsonl @@ -0,0 +1,3 @@ +{"metadata": {"ticker": "QCOM", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0000804328-26-000051", "url": "https://www.sec.gov/Archives/edgar/data/804328/000080432826000051/xslF345X06/edgardoc.xml", "ingested_at": "2026-04-08T12:48:39.267926"}, "parsed_data": {"reporting_owner": "Grech Patricia Y", "role": "SVP, Chief Accounting Officer", "transactions": [{"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 85.0, "price": 125.5, "total_value": 10667.5, "post_transaction_shares": 192.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "QCOM", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0000804328-26-000049", "url": "https://www.sec.gov/Archives/edgar/data/804328/000080432826000049/xslF345X06/edgardoc.xml", "ingested_at": "2026-04-08T12:48:39.472942"}, "parsed_data": {"reporting_owner": "MCLAUGHLIN MARK D", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 538.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 12849.8312, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "QCOM", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0000804328-26-000048", "url": "https://www.sec.gov/Archives/edgar/data/804328/000080432826000048/xslF345X06/edgardoc.xml", "ingested_at": "2026-04-08T12:48:39.683945"}, "parsed_data": {"reporting_owner": "TRICOIRE JEAN-PASCAL", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 262.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 13481.4716, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_REGN.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_REGN.jsonl new file mode 100644 index 0000000..f693d3e --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_REGN.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "REGN", "form_type": "8-K", "filed_at": "2026-04-08", "accession_no": "0001104659-26-040661", "url": "https://www.sec.gov/Archives/edgar/data/872589/000110465926040661/tm2611354d1_8k.htm", "ingested_at": "2026-04-08T12:48:54.660815"}, "parsed_data": {"is_chunked": true, "item_chunks": {"2.02": "Item 2.02.** | **Results of Operations and Financial Condition.** |\n\nRegeneron Pharmaceuticals, Inc. (“Regeneron”\nor the “Company”) currently expects that its financial results calculated in accordance with U.S. generally accepted\naccounting principles (“GAAP”) and its non-GAAP financial results for the first quarter 2026 will include an acquired\nin-process research and development (“IPR&D”) charge of approximately $102 million on a pre-tax basis. This charge\nprimarily relates to premium on equity securities purchased, as well as development milestone and up-front payments, in connection with\ncollaboration and licensing agreements. The acquired IPR&D charge is expected to negatively impact each of GAAP and non-GAAP net income\nper diluted share for the first quarter 2026 by approximately $0.81.\n\nAcquired IPR&D charges may include IPR&D\nacquired in connection with asset acquisitions as well as up-front, opt-in, certain development milestone payments, and premiums paid\non equity securities related to collaboration and licensing agreements. Regeneron does not forecast such acquired IPR&D charges due\nto the uncertainty of the future occurrence, magnitude, and timing of these transactions in any given period.\n\nRegeneron’s results for the first quarter\n2026 have not been finalized and are subject to Regeneron’s financial statement closing procedures. There can be no assurance that\nactual results will not differ from the preliminary (unaudited) estimates described herein.\n\nThe information included in this Current Report\non Form 8-K shall not be deemed “filed” for purposes of Section 18 of the Securities Exchange Act of 1934, as amended,\nnor shall such information be deemed incorporated by reference in any filing under the Securities Act of 1933, as amended, except as shall\nbe expressly set forth by specific reference in such a filing.\n\n***Note\nRegarding Forward-Looking Statements***\n\n*This Current Report\non Form 8-K (this “Report”) includes forward-looking statements that involve risks and uncertainties relating\nto future events and the future performance of Regeneron Pharmaceuticals, Inc. (“Regeneron” or the “Company”),\nand actual events or results may differ materially from these forward-looking statements. Words such as “anticipate,” “expect,”\n“intend,” “plan,” “believe,” “seek,” “estimate,” variations of such words,\nand similar expressions are intended to identify such forward-looking statements, although not all forward-looking statements contain\nthese identifying words. These statements concern, and these risks and uncertainties include, among others, Regeneron’s expected\nacquired in-process research and development charge for the quarterly period ended March 31, 2026 and its expected impact on GAAP\nand non-GAAP net income per diluted share for this period as discussed in this Report. A more complete description of these and other\nmaterial risks can be found in Regeneron’s filings with the U.S. Securities and Exchange Commission. Any forward-looking statements\nare made based on management’s current beliefs and judgment, and the reader is cautioned not to rely on any forward-looking statements\nmade by Regeneron. Regeneron does not undertake any obligation to update (publicly or otherwise) any forward-looking statement, including\nwithout limitation any financial projection or guidance, whether as a result of new information, future events, or otherwise.*\n\n***Note Regarding Non-GAAP Financial Measures***\n\n*This Report references non-GAAP net income\nper diluted share, which is a financial measure that is not calculated in accordance with U.S. Generally Accepted Accounting Principles\n(“GAAP”). This non-GAAP financial measure is computed by excluding certain non-cash and/or other items from the related\nGAAP financial measure. The Company also includes a non-GAAP adjustment for the estimated income tax effect of reconciling items. The\nCompany makes such adjustments for items the Company does not view as useful in evaluating its operating performance. Management uses\nthis and other non-GAAP measures for planning, budgeting, forecasting, assessing historical performance, and making financial and operational\ndecisions, and also provides forecasts to investors on this basis. Additionally, such non-GAAP measures provide investors with an enhanced\nunderstanding of the financial performance of the Company's core business operations. However, there are limitations in the use of such\nnon-GAAP financial measures as they exclude certain expenses that are recurring in nature. Furthermore, the Company's non-GAAP financial\nmeasures may not be comparable with non-GAAP information provided by other companies. Any non-GAAP financial measure presented by Regeneron\nshould be considered supplemental to, and not a substitute for, measures of financial performance prepared in accordance with GAAP.*\n\n**SIGNATURES**\n\nPursuant to the requirements of the Securities\nExchange Act of 1934, the registrant has duly caused this report to be signed on its behalf by the undersigned thereunto duly authorized.\n\n| | |\n| --- | --- |\n| | **REGENERON PHARMACEUTICALS, INC.** |\n| | |\n| | /s/ Joseph J. LaRosa |\n| | Joseph J. LaRosa |\n| | Executive Vice President, General Counsel and Secretary |\n\nDate: April 8, 2026"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} +{"metadata": {"ticker": "REGN", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001104659-26-039613", "url": "https://www.sec.gov/Archives/edgar/data/872589/000110465926039613/xslF345X06/tm2611142-1_4seq1.xml", "ingested_at": "2026-04-08T12:48:54.906167"}, "parsed_data": {"reporting_owner": "RYAN ARTHUR F", "role": "Other", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1.0, "price": 771.32, "total_value": 771.32, "post_transaction_shares": 17702.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 3.0, "price": 772.76, "total_value": 2318.2799999999997, "post_transaction_shares": 17699.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 8.0, "price": 773.59, "total_value": 6188.72, "post_transaction_shares": 17691.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 8.0, "price": 774.58, "total_value": 6196.64, "post_transaction_shares": 17683.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 14.0, "price": 775.58, "total_value": 10858.12, "post_transaction_shares": 17669.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 13.0, "price": 776.62, "total_value": 10096.06, "post_transaction_shares": 17656.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 9.0, "price": 777.42, "total_value": 6996.78, "post_transaction_shares": 17647.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 4.0, "price": 778.24, "total_value": 3112.96, "post_transaction_shares": 17643.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 40.0, "price": 779.71, "total_value": 31188.4, "post_transaction_shares": 17603.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_SBUX.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_SBUX.jsonl new file mode 100644 index 0000000..632a173 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_SBUX.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "SBUX", "form_type": "8-K", "filed_at": "2026-04-02", "accession_no": "0000829224-26-000064", "url": "https://www.sec.gov/Archives/edgar/data/829224/000082922426000064/sbux-20260402.htm", "ingested_at": "2026-04-08T12:48:52.264984"}, "parsed_data": {"is_chunked": true, "item_chunks": {"7.01": "Item 7.01    Regulation FD Disclosure.\n\nAs previously disclosed on November 3, 2025, Starbucks entered an agreement to form a joint venture with Boyu Capital. On April 2, 2026, Starbucks announced that, following the satisfaction of all necessary closing conditions, it completed the transaction. Pursuant to the transaction, funds managed by Boyu Capital have acquired a 60% interest in Starbucks retail operations in China. Starbucks retains a 40% interest and will serve as the owner and licensor of the Starbucks global brand.\n\nA copy of the press release issued is furnished as Exhibit 99.1 to this Form 8-K.\n\nThe information contained in Item 7.01 of this report, including the information in Exhibit 99.1, is furnished pursuant to Item 7.01 of Form 8-K and shall not be deemed “filed” for the purposes of Section 18 of the Securities Exchange Act of 1934, as amended, or otherwise subject to the liabilities of that section. Furthermore, the information in Item 7.01 of this report, including the information in Exhibit 99.1 attached to this report, shall not be deemed to be incorporated by reference in the filings of Starbucks Corporation under the Securities Act of 1933, as amended.", "9.01": "Item 9.01Financial Statements and Exhibits.\n\n(d) Exhibits.\n\n| | | | | | | | | |\n| --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| | | | | | | | | |\n| Exhibit No. | | | | | | Description | | |\n| 99.1 | | | | | | Press Release, dated April 2, 2026 | | |\n| 104 | | | | | | Cover Page Interactive Data File (formatted as inline XBRL) | | |\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_TSLA.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_TSLA.jsonl new file mode 100644 index 0000000..e7df39a --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_TSLA.jsonl @@ -0,0 +1,3 @@ +{"metadata": {"ticker": "TSLA", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001972928-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/1318605/000197292826000002/xslF345X06/edgardoc.xml", "ingested_at": "2026-04-08T12:48:31.110524"}, "parsed_data": {"reporting_owner": "Zhu Xiaotong", "role": "SVP", "transactions": [{"date": "2026-03-31", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 20000.0, "price": 20.57, "total_value": 411400.0, "post_transaction_shares": 20000.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "TSLA", "form_type": "8-K", "filed_at": "2026-04-02", "accession_no": "0001628280-26-022956", "url": "https://www.sec.gov/Archives/edgar/data/1318605/000162828026022956/tsla-20260402.htm", "ingested_at": "2026-04-08T12:48:31.313708"}, "parsed_data": {"is_chunked": true, "item_chunks": {"2.02": "Item 2.02    Results of Operations and Financial Condition.\n\nOn April 2, 2026, Tesla, Inc. published the press release which is attached hereto as Exhibit 99.1 and is incorporated herein by reference.\n\nThis information is intended to be furnished under Item 2.02 of Form 8-K and shall not be deemed “filed” for purposes of Section 18 of the Securities Exchange Act of 1934, as amended (the “Exchange Act”), or incorporated by reference in any filing under the Securities Act of 1933, as amended, or the Exchange Act as shall be expressly set forth by specific reference in such a filing.", "9.01": "Item 9.01    Financial Statements and Exhibits.\n\n(d)Exhibits.\n\n| | | | | | | | | |\n| --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| | | | | | | | | |\n| Exhibit No. | | | | | | Description | | |\n| | | | | | | | | |\n| 99.1 | | | | | | Press release of Tesla, Inc., dated April 2, 2026. | | |\n| 104 | | | | | | Cover Page Interactive Data File (embedded within the Inline XBRL document). | | |\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} +{"metadata": {"ticker": "TSLA", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0001104659-26-038682", "url": "https://www.sec.gov/Archives/edgar/data/1318605/000110465926038682/xslF345X06/tm2610684-1_4seq1.xml", "ingested_at": "2026-04-08T12:48:31.571595"}, "parsed_data": {"reporting_owner": "Wilson-Thompson Kathleen", "role": "Other", "transactions": [{"date": "2026-03-30", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 40000.0, "price": 14.99, "total_value": 599600.0, "post_transaction_shares": 59669.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 2000.0, "price": 352.833, "total_value": 705666.0, "post_transaction_shares": 57669.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1640.0, "price": 353.658, "total_value": 579999.12, "post_transaction_shares": 56029.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1800.0, "price": 354.802, "total_value": 638643.6000000001, "post_transaction_shares": 54229.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 2481.0, "price": 355.644, "total_value": 882352.764, "post_transaction_shares": 51748.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 2360.0, "price": 356.794, "total_value": 842033.84, "post_transaction_shares": 49388.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1120.0, "price": 357.839, "total_value": 400779.68, "post_transaction_shares": 48268.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 520.0, "price": 358.77, "total_value": 186560.4, "post_transaction_shares": 47748.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1880.0, "price": 360.181, "total_value": 677140.2799999999, "post_transaction_shares": 45868.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1000.0, "price": 361.035, "total_value": 361035.0, "post_transaction_shares": 44868.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 2320.0, "price": 362.142, "total_value": 840169.44, "post_transaction_shares": 42548.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 4001.0, "price": 363.083, "total_value": 1452695.083, "post_transaction_shares": 38547.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 3927.0, "price": 363.947, "total_value": 1429219.869, "post_transaction_shares": 34620.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 560.0, "price": 364.888, "total_value": 204337.28, "post_transaction_shares": 34060.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 120.0, "price": 365.897, "total_value": 43907.64, "post_transaction_shares": 33940.0, "is_10b5_1_planned": true}, {"date": "2026-03-30", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 80.0, "price": 366.855, "total_value": 29348.4, "post_transaction_shares": 33860.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_VRTX.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_VRTX.jsonl new file mode 100644 index 0000000..2ef2f08 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-08/raw_VRTX.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "VRTX", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0000875320-26-000157", "url": "https://www.sec.gov/Archives/edgar/data/875320/000087532026000157/xslF345X06/wk-form4_1775249628.xml", "ingested_at": "2026-04-08T12:48:51.663358"}, "parsed_data": {"reporting_owner": "Liu Joy", "role": "EVP and Chief Legal Officer", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 978.0, "price": 449.17, "total_value": 439288.26, "post_transaction_shares": 21833.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/AAPL.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/AAPL.jsonl new file mode 100644 index 0000000..3830839 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/AAPL.jsonl @@ -0,0 +1,3 @@ +{"metadata": {"ticker": "AAPL", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001140361-26-013192", "url": "https://www.sec.gov/Archives/edgar/data/320193/000114036126013192/xslF345X06/form4.xml", "ingested_at": "2026-04-09T14:35:15.028367"}, "parsed_data": {"reporting_owner": "O'BRIEN DEIRDRE", "role": "Senior Vice President", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 64317.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 201127.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 34315.0, "price": 255.63, "total_value": 8771943.45, "post_transaction_shares": 166812.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 20338.0, "price": 255.12, "total_value": 5188630.5600000005, "post_transaction_shares": 146474.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 9664.0, "price": 255.82, "total_value": 2472244.48, "post_transaction_shares": 136810.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "AAPL", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001140361-26-013191", "url": "https://www.sec.gov/Archives/edgar/data/320193/000114036126013191/xslF345X06/form4.xml", "ingested_at": "2026-04-09T14:35:15.222498"}, "parsed_data": {"reporting_owner": "Khan Sabih", "role": "COO", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 64317.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 1107212.0, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 33317.0, "price": 255.63, "total_value": 8516824.709999999, "post_transaction_shares": 1073895.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "AAPL", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001140361-26-013190", "url": "https://www.sec.gov/Archives/edgar/data/320193/000114036126013190/xslF345X06/form4.xml", "ingested_at": "2026-04-09T14:35:15.417304"}, "parsed_data": {"reporting_owner": "COOK TIMOTHY D", "role": "Chief Executive Officer", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 131576.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 3411994.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 66627.0, "price": 255.63, "total_value": 17031860.009999998, "post_transaction_shares": 3345367.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 5087.0, "price": 251.25, "total_value": 1278108.75, "post_transaction_shares": 3340280.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 9147.0, "price": 252.11, "total_value": 2306050.17, "post_transaction_shares": 3331133.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1878.0, "price": 253.13, "total_value": 475378.14, "post_transaction_shares": 3329255.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 16083.0, "price": 254.37, "total_value": 4091032.71, "post_transaction_shares": 3313172.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 28188.0, "price": 255.17, "total_value": 7192731.96, "post_transaction_shares": 3284984.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 4566.0, "price": 256.0, "total_value": 1168896.0, "post_transaction_shares": 3280418.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/ADI.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/ADI.jsonl new file mode 100644 index 0000000..b4100fd --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/ADI.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001201872-26-000008", "url": "https://www.sec.gov/Archives/edgar/data/6281/000120187226000008/xslF345X06/wk-form4_1775247205.xml", "ingested_at": "2026-04-09T14:35:36.550448"}, "parsed_data": {"reporting_owner": "ROCHE VINCENT", "role": "Chair & CEO", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 10000.0, "price": 94.41, "total_value": 944100.0, "post_transaction_shares": 177825.875, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 10000.0, "price": 318.14, "total_value": 3181400.0, "post_transaction_shares": 167825.875, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/AMAT.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/AMAT.jsonl new file mode 100644 index 0000000..15047e9 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/AMAT.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "AMAT", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001628280-26-023379", "url": "https://www.sec.gov/Archives/edgar/data/6951/000162828026023379/xslF345X06/wk-form4_1775169858.xml", "ingested_at": "2026-04-09T14:35:30.921699"}, "parsed_data": {"reporting_owner": "Sanders Adam", "role": "Corp. Controller & CAO", "transactions": [{"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 125.0, "price": 353.8, "total_value": 44225.0, "post_transaction_shares": 4548.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/AMD.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/AMD.jsonl new file mode 100644 index 0000000..68ebba4 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/AMD.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "AMD", "form_type": "4", "filed_at": "2026-04-08", "accession_no": "0000002488-26-000064", "url": "https://www.sec.gov/Archives/edgar/data/2488/000000248826000064/xslF345X06/wk-form4_1775679123.xml", "ingested_at": "2026-04-09T14:35:22.976531"}, "parsed_data": {"reporting_owner": "Papermaster Mark D", "role": "Chief Technology Officer & EVP", "transactions": [{"date": "2026-04-06", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 3293.0, "price": 225.0, "total_value": 740925.0, "post_transaction_shares": 1294466.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/AMZN.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/AMZN.jsonl new file mode 100644 index 0000000..722c992 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/AMZN.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "AMZN", "form_type": "8-K", "filed_at": "2026-04-09", "accession_no": "0001104659-26-041034", "url": "https://www.sec.gov/Archives/edgar/data/1018724/000110465926041034/tm263815d2_8k.htm", "ingested_at": "2026-04-09T14:35:16.491691"}, "parsed_data": {"is_chunked": true, "item_chunks": {"7.01": "ITEM 7.01.  REGULATION FD DISCLOSURE.** | **3** |\n| | |\n| **ITEM 9.01.  FINANCIAL STATEMENTS AND EXHIBITS.** | **3** |\n| | |\n| **SIGNATURES** | **4** |\n| | |\n| EXHIBIT 99.1 | |\n| | |\n| EXHIBIT 99.2 | |\n\n2\n\nTable of Contents\n\n**ITEM 7.01.****REGULATION\nFD DISCLOSURE.**\n\nThe Company’s\nLetter to Shareholders, which accompanies its Annual Report for the Year Ended December 31, 2025, is attached as Exhibit 99.1, and a\nreconciliation of a non-GAAP financial measure included in the Letter to Shareholders to the most directly comparable financial\nmeasure calculated and presented in accordance with GAAP is included as Exhibit 99.2.\n\n**ITEM 9.01.  FINANCIAL STATEMENTS AND EXHIBITS.**\n\n***(d) Exhibits.***\n\n| | |\n| --- | --- |\n| **Exhibit** **Number** | **Description** |\n| | |\n| 99.1 | 2025 Letter to Shareholders. |\n| 99.2 | Reconciliation of Non-GAAP Financial Measure. |\n| 104 | The cover page from this Current Report on Form 8-K, formatted in Inline XBRL (included as Exhibit 101). |\n\n3\n\nTable of Contents\n\n**SIGNATURES**\n\nPursuant to the requirements of the Securities Exchange Act of 1934, the registrant has duly caused this report to be signed on its behalf by the\nundersigned hereunto duly authorized.\n\n| | | |\n| --- | --- | --- |\n| | AMAZON.COM, INC. (REGISTRANT) | |\n| | | |\n| | By: | /s/ Susan K. Jong |\n| | | **Susan K. Jong** |\n| | | **Vice President and Secretary** |\n\nDated: April 9, 2026\n\n4"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} +{"metadata": {"ticker": "AMZN", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001018724-26-000010", "url": "https://www.sec.gov/Archives/edgar/data/1018724/000101872426000010/xslF345X06/wk-form4_1775248886.xml", "ingested_at": "2026-04-09T14:35:16.734993"}, "parsed_data": {"reporting_owner": "Herrington Douglas J", "role": "CEO Worldwide Amazon Stores", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1000.0, "price": 210.5, "total_value": 210500.0, "post_transaction_shares": 520361.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/AVGO.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/AVGO.jsonl new file mode 100644 index 0000000..a9822ea --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/AVGO.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "AVGO", "form_type": "8-K", "filed_at": "2026-04-06", "accession_no": "0001193125-26-144028", "url": "https://www.sec.gov/Archives/edgar/data/1730168/000119312526144028/d87999d8k.htm", "ingested_at": "2026-04-09T14:35:18.906268"}, "parsed_data": {"is_chunked": true, "item_chunks": {"8.01": "Item 8.01 | Other Events. |\n\nBroadcom Inc. (“Broadcom”) and Google LLC (“Google”) have entered into a Long Term Agreement for Broadcom to develop and supply custom Tensor Processing Units (“TPUs”) for Google’s future generations of TPUs and a Supply Assurance Agreement for Broadcom to supply networking and other components to be used in Google’s next-generation AI racks through up to 2031.\n\nSeparately, Broadcom, Google and Anthropic PBC (“Anthropic”) have expanded their current strategic collaboration under which Anthropic, beginning in 2027, will access through Broadcom approximately 3.5 gigawatts as part of the multiple gigawatts of next generation TPU-based AI compute capacity committed by Anthropic. The consumption of such expanded AI compute capacity by Anthropic is dependent on Anthropic’s continued commercial success. In connection with this deployment, the parties are in discussions with certain operational and financial partners.\n\nCautionary Note Regarding Forward-Looking Statements\n\nThis Current Report on Form 8-K contains forward-looking statements (including within the meaning of Section 21E of the Securities Exchange Act of 1934, as amended, and Section 27A of the Securities Act of 1933, as amended). These forward-looking statements are based on current expectations and beliefs of Broadcom’s management, current information available to Broadcom’s management, and current market trends and market conditions, and involve risks and uncertainties that may cause actual results to differ materially from those contained in the forward-looking statements. Accordingly, undue reliance should not be placed on such statements. All forward-looking statements are qualified in their entirety by reference to the risk factors discussed under the heading “Risk Factors” in Broadcom’s Annual Report on Form 10-K for the year ended November 2, 2025, Quarterly Report on Form 10-Q for the period ended February 1, 2026 and any subsequent reports that are filed with the Securities and Exchange Commission and include some important risk factors that may affect future results. Broadcom undertakes no intent or obligation to publicly update or revise the forward-looking statements made in this Current Report on Form 8-K, except as required by law.\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} +{"metadata": {"ticker": "AVGO", "form_type": "8-K", "filed_at": "2026-04-02", "accession_no": "0001193125-26-140574", "url": "https://www.sec.gov/Archives/edgar/data/1730168/000119312526140574/d109450d8k.htm", "ingested_at": "2026-04-09T14:35:19.131239"}, "parsed_data": {"is_chunked": true, "item_chunks": {"5.02": "Item 5.02 | Departure of Directors or Certain Officers; Election of Directors; Appointment of Certain Officers; Compensatory Arrangements of Certain Officers. |\n\nChief Financial Officer Transition\n\nOn March 30, 2026, Kirsten M. Spears notified Broadcom Inc. (the “Company”) of her retirement and resigned from her position as Chief Financial Officer and Chief Accounting Officer of the Company, effective as of June 12, 2026.\n\nOn March 30, 2026, the Board of Directors of the Company (the “Board”) appointed Amie Thuener to succeed Ms. Spears as the Chief Financial Officer of the Company, effective as of June 12, 2026. The employment of Ms. Thuener with the Company is expected to commence on May 4, 2026 and she will assume the role of Chief Financial Officer following the retirement of Ms. Spears on June 12, 2026.\n\nMs. Thuener, age 51, has served as Vice President, Corporate Controller and Chief Accounting Officer of Alphabet Inc. since 2018. Ms. Thuener held several senior finance positions at Alphabet from 2013 to 2018, including as Vice President and Chief Accountant. Prior to joining Alphabet, Ms. Thuener was at PricewaterhouseCoopers LLP from 1996 to 2012 and held several senior management positions, including as Managing Director, Transaction Services. Ms. Thuener is a Certified Public Accountant and a Chartered Global Management Accountant.\n\nThere are no family relationships between Ms. Thuener and any director or executive officer of the Company as defined in Item 401(d) of Regulation S-K, and Ms. Thuener has no direct or indirect material interest in any transaction or proposed transaction required to be disclosed pursuant to Item 404(a) of Regulation S-K.\n\nKirsten M. Spears Transition and Consulting Agreement\n\nIn connection with the retirement of Ms. Spears, the Company entered into a transition and consulting agreement with Ms. Spears, dated as of April 1, 2026 (the “Transition Agreement”).\n\nThe Transition Agreement provides that, following the conclusion of Ms. Spears’ employment with the Company on June 12, 2026, she will provide consulting services to the Company, as reasonably requested by the Chief Executive Officer of the Company, until March 15, 2027, unless the consulting period terminates earlier in accordance with the terms of the Transition Agreement. During the consulting period, Ms. Spears’ outstanding equity awards will continue to vest in accordance with their terms (provided that the performance-based equity awards will in no event vest at a level exceeding target). Ms. Spears will not receive any other compensation during the consulting period. The Transition Agreement includes a general release of claims in favor of the Company.\n\nAmie Thuener Offer Letter and Equity Awards\n\nIn connection with her employment with the Company and appointment as Chief Financial Officer of the Company, effective as of June 12, 2026, the Company entered into an offer letter with Ms. Thuener, dated as of March 30, 2026, which sets forth the material terms of her employment and compensation (the “Offer Letter”).\n\nPursuant to the Offer Letter, Ms. Thuener will receive an annual base salary of $700,000 and will be eligible to participate in the Company’s annual performance bonus plan with a target bonus opportunity of 100% of her base salary. Ms. Thuener will also receive a $1,000,000 sign-on cash bonus, payable within 30 days following the commencement of her employment.\n\nThe Offer Letter further provides that, subject to the approval of the Compensation Committee of the Board and Ms. Thuener’s continued employment through the applicable grant date, Ms. Thuener will be granted equity awards under the Company’s 2012 Stock Incentive Plan consisting of (i) 50,000 restricted stock units (“RSUs”) and (ii) 50,000 performance stock units (“PSUs”) at target. The equity awards are expected to be granted on June 15, 2026.\n\nThe RSUs will vest in equal quarterly installments over a four-year period following the grant date, subject to Ms. Thuener’s continued employment through each applicable vesting date. The PSUs will vest annually over a four-year period across four overlapping performance periods (March 2, 2026 through March 1, 2027, March 2, 2026 through March 1, 2028, March 2, 2026 through March 1, 2029 and March 2, 2026 through March 1, 2030) based on the Company’s total stockholder return relative to the S&P 500 and the Company’s absolute total stockholder return for the applicable performance period, in each case subject to Ms. Thuener’s continued employment through the anniversary of the grant date immediately following the end of each applicable performance period. The maximum vesting for the PSUs is 200% of the total target number of shares. The equity awards will be subject to the other terms and conditions set forth in the Company’s 2012 Stock Incentive Plan and the applicable award agreements.\n\n---\n\nIn addition, Ms. Thuener is expected to enter into the Company’s standard form of indemnification and advancement agreement and a severance benefit agreement on terms and conditions materially consistent with those applicable to Ms. Spears pursuant to her severance benefit agreement, as described in the Company’s definitive proxy statement filed with the U.S. Securities and Exchange Commission on March 2, 2026.\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/BKNG.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/BKNG.jsonl new file mode 100644 index 0000000..00ba456 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/BKNG.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "BKNG", "form_type": "8-K", "filed_at": "2026-04-02", "accession_no": "0000950157-26-000465", "url": "https://www.sec.gov/Archives/edgar/data/1075531/000095015726000465/form8-k.htm", "ingested_at": "2026-04-09T14:35:31.714159"}, "parsed_data": {"is_chunked": true, "item_chunks": {"5.03": "Item 5.03. Amendments to Articles of incorporation or Bylaws; Change in Fiscal Year.\n\nOn April 2, 2026, Booking Holdings Inc. (the “Company”) filed an amendment to its Restated Certificate of Incorporation with the Delaware Secretary of State to effect the\npreviously announced twenty-five-for-one forward stock split of the Company’s common stock and to proportionately increase the number of shares of the Company’s authorized common stock from 1,000,000,000 to 25,000,000,000. The amendment, which became\neffective at 4:01 p.m. Eastern Time on April 2, 2026, is filed as Exhibit 3.1 to this Current Report on Form 8-K. Trading is expected to commence on a split-adjusted basis at market open on Monday, April 6, 2026.", "9.01": "Item 9.01. Financial Statements and Exhibits.\n\n| | | |\n| --- | --- | --- |\n| (d) Exhibits | | |\n| Exhibit Number | | Description |\n| | | |\n| 3.1 | | Amendment to Restated Certificate of Incorporation of Booking Holdings Inc., dated April 2, 2026. |\n| 104 | | Cover Page Interactive Data File - the cover page interactive data file does not appear in the Interactive Data File because its XBRL tags are embedded within the Inline XBRL document. |\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} +{"metadata": {"ticker": "BKNG", "form_type": "8-K", "filed_at": "2026-04-02", "accession_no": "0001075531-26-000014", "url": "https://www.sec.gov/Archives/edgar/data/1075531/000107553126000014/bkng-20260402.htm", "ingested_at": "2026-04-09T14:35:31.981521"}, "parsed_data": {"is_chunked": true, "item_chunks": {"5.02": "Item 5.02.    Departure of Directors or Certain Officers; Election of Directors; Appointment\n\nof Certain Officers; Compensatory Arrangements of Certain Officers.\n\nOn April 2, 2026, Booking Holdings Inc. (the \"Company\") announced that it has appointed Caroline Sullivan as its Senior Vice President, Chief Accounting Officer, and Controller effective as of April 29, 2026. Ms. Sullivan, age 57, served as Vice President, Procurement and Real Estate of Elevance Health, a health insurance company, from June 2025 to March 2026. Prior to this, Ms. Sullivan was Senior Vice President, Chief Accounting Officer and Corporate Controller at Moody's Corporation, a global risk assessment firm, from December 2018 to March 2025. Ms. Sullivan also served as Global Banking Controller of Bank of America from 2017 to 2018. Earlier in her career, she held various finance positions with Morgan Stanley and Allied Irish Bank. Ms. Sullivan began her career at Ernst and Young and is a Certified Public Accountant.\n\nIn connection with Ms. Sullivan's appointment, she and the Company entered into an employment agreement with, among others, the following terms:\n\n•an initial annual base salary of $525,000;\n\n•a target annual bonus of 75% of base salary;\n\n•a grant of restricted stock units (\"RSUs\") expected to be made in May 2026 with a grant date fair value of $1,000,000;\n\n•a grant of performance share units (\"PSUs\") expected to be made in March 2027 with a grant date fair value at target of $1,000,000;\n\n•a new hire grant of RSUs expected to be made in May 2026 with a grant date fair value of $1,000,000;\n\n•a signing bonus of $300,000; and\n\n•in the event of her termination without cause, subject to the execution of a release of claims, severance benefits including payments equal to one times her base salary and target annual bonus, a pro-rated portion of any earned bonus for the year of termination if employment is terminated after June 30 of the then current year, health benefits for a period of 12 months, and any earned bonus for a prior completed year that has not yet been paid.\n\nMs. Sullivan's RSUs and new hire RSUs will each vest in three equal annual installments on each of the first three anniversaries of the grant date, subject to her continuous service from the date of grant until the vesting date, with pro rata vesting upon a termination without cause or due to disability, and full vesting upon a termination due to death. Ms. Sullivan's PSU award will vest subject to such service and performance-based vesting provisions generally consistent with those applicable to similarly-situated executives who receive PSU grants in 2027. The awards will be subject to the terms of the respective award agreements for awards under the Company’s 1999 Omnibus Plan.\n\nIn connection with Ms. Sullivan's appointment, the Company and Ms. Sullivan have also entered into a Non-Competition and Non-Solicitation Agreement and an Employee Confidentiality and Assignment Agreement.\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/CDNS.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/CDNS.jsonl new file mode 100644 index 0000000..1269149 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/CDNS.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "CDNS", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0000813672-26-000040", "url": "https://www.sec.gov/Archives/edgar/data/813672/000081367226000040/xslF345X06/wk-form4_1775243708.xml", "ingested_at": "2026-04-09T14:35:38.462751"}, "parsed_data": {"reporting_owner": "Cunningham Paul", "role": "Sr. Vice President", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1000.0, "price": 280.19, "total_value": 280190.0, "post_transaction_shares": 128586.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/CMCSA.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/CMCSA.jsonl new file mode 100644 index 0000000..0dd75c2 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/CMCSA.jsonl @@ -0,0 +1,6 @@ +{"metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001225208-26-004342", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004342/xslF345X06/doc4.xml", "ingested_at": "2026-04-09T14:35:28.665936"}, "parsed_data": {"reporting_owner": "Murdock Daniel C.", "role": "EVP & Chief Accounting Officer", "transactions": [{"date": "2026-04-03", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 5268.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 64435.0497, "is_10b5_1_planned": false}, {"date": "2026-04-03", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 2073.0, "price": 27.93, "total_value": 57898.89, "post_transaction_shares": 62362.0497, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001225208-26-004203", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004203/xslF345X06/doc4.xml", "ingested_at": "2026-04-09T14:35:28.862239"}, "parsed_data": {"reporting_owner": "Smith Gordon", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 1176.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 9045.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001225208-26-004202", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004202/xslF345X06/doc4.xml", "ingested_at": "2026-04-09T14:35:29.056337"}, "parsed_data": {"reporting_owner": "Honickman Jeffrey A", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 1524.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 262583.021, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001225208-26-004201", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004201/xslF345X06/doc4.xml", "ingested_at": "2026-04-09T14:35:29.233609"}, "parsed_data": {"reporting_owner": "BREEN EDWARD D", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 697.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 56522.277, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001225208-26-004200", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004200/xslF345X06/doc4.xml", "ingested_at": "2026-04-09T14:35:29.413496"}, "parsed_data": {"reporting_owner": "Brady Louise F.", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 1176.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 32682.89, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001225208-26-004199", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004199/xslF345X06/doc4.xml", "ingested_at": "2026-04-09T14:35:29.591730"}, "parsed_data": {"reporting_owner": "Baltimore Thomas J Jr", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 1176.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 39043.493, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/CRWD.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/CRWD.jsonl new file mode 100644 index 0000000..bc24c21 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/CRWD.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "CRWD", "form_type": "8-K", "filed_at": "2026-04-06", "accession_no": "0001535527-26-000013", "url": "https://www.sec.gov/Archives/edgar/data/1535527/000153552726000013/crwd-20260406.htm", "ingested_at": "2026-04-09T14:35:40.512509"}, "parsed_data": {"is_chunked": true, "item_chunks": {"8.01": "Item 8.01 Other Events.\n\nOn April 6, 2026, the Company announced that its Board of Directors has approved the repurchase of up to an additional $500 million of the Company’s common stock, bringing the Company’s total repurchase authorization to $1.5 billion (together, the “Share Repurchase Program”). Under the Share Repurchase Program, the Company has repurchased 413,130 shares of its outstanding Class A common stock at an average price of $364.57 per share, for an aggregate purchase price of $150.6 million.\n\nThe Share Repurchase Program does not have a fixed expiration date and does not obligate the Company to acquire any specific number of shares. Repurchases may be made from time to time using a variety of methods, including open market purchases, privately negotiated transactions, Rule 10b5-1 trading plans and other means. The timing, manner, price and amount of any repurchases will be determined by the Company in its discretion and will depend on a variety of factors, including legal requirements, price and economic and market conditions. The Company currently expects to use the Share Repurchase Program opportunistically depending on the market price of the common stock and other factors, and there can be no assurance that any shares will be repurchased under the Share Repurchase Program.\n\nForward-Looking Statements\n\nThis Form 8-K contains forward-looking statements that involve risks and uncertainties, including statements regarding the Share Repurchase Program and the factors that will impact the amount and timing of purchases, if any, thereunder. A number of factors could cause outcomes to differ materially from our statements, including the risks and uncertainties included in our filings with the Securities and Exchange Commission, particularly under the caption “Risk Factors” in our most recently filed Annual Report on Form 10-K. Accordingly, you should not place undue reliance on these forward-looking statements. All forward-looking statements are based on information currently available to us, and we do not assume any obligation to update any statement to reflect changes in circumstances or our expectations.\n\n2\n\n---", "9.01": "Item 9.01    Financial Statements and Exhibits.\n\n(d) Exhibits\n\n| | | | | | | | | |\n| --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| | | | | | | | | |\n| Exhibit Number | | | | | | Description of Exhibit | | |\n| 99.1 | | | | | | Press release dated April 6, 2026 | | |\n| 104 | | | | | | Cover Page Interactive Data File - the cover page XBRL tags are embedded within the Inline XBRL document | | |\n\n3\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/CSCO.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/CSCO.jsonl new file mode 100644 index 0000000..b70293d --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/CSCO.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "CSCO", "form_type": "4", "filed_at": "2026-04-07", "accession_no": "0000858877-26-000052", "url": "https://www.sec.gov/Archives/edgar/data/858877/000085887726000052/xslF345X06/wk-form4_1775592372.xml", "ingested_at": "2026-04-09T14:35:23.463961"}, "parsed_data": {"reporting_owner": "Shimer Peter A", "role": "Other", "transactions": [{"date": "2026-04-06", "code": "A", "direction": "OTHER (A)", "shares": 2333.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 2333.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "CSCO", "form_type": "8-K", "filed_at": "2026-04-06", "accession_no": "0000858877-26-000048", "url": "https://www.sec.gov/Archives/edgar/data/858877/000085887726000048/csco-20260331.htm", "ingested_at": "2026-04-09T14:35:23.641536"}, "parsed_data": {"is_chunked": true, "item_chunks": {"5.02": "Item 5.02. | | | Departure of Directors or Certain Officers; Election of Directors; Appointment of Certain Officers; Compensatory Arrangements of Certain Officers. | | |\n\nDeparture of Director\n\nOn March 31, 2026, in light of the increased time and focus required of his new role as Chief Executive Officer of Verizon Communications Inc., Daniel H. Schulman notified Cisco Systems, Inc. (“Cisco”) of his decision to resign from the Board of Directors (\"Board\") of Cisco effective May 21, 2026.\n\nAppointment of Director\n\nOn April 4, 2026, the Board of Cisco appointed Peter A. Shimer as a member of the Board effective April 6, 2026. In connection with his appointment, the Board determined that Mr. Shimer is “independent” under the applicable listing standards of The Nasdaq Stock Market LLC. The Board has also appointed Mr. Shimer to serve as a member of the Audit Committee of the Board.\n\nIn connection with his service as a director, Mr. Shimer will receive Cisco’s standard non-employee director cash and equity compensation. Mr. Shimer will receive a pro rata portion of the $105,000 annual cash retainer, paid quarterly in arrears, for his service through the remaining portion of the year ending at Cisco's 2026 annual meeting of stockholders (the \"2026 Annual Meeting\"). Mr. Shimer will also receive a pro rata portion of the Audit Committee member annual cash retainer fees, paid quarterly in arrears, for service on such committee through the remaining portion of the year ending at the 2026 Annual Meeting. Non-employee directors may instead elect to receive the annual cash retainer, committee cash retainer fees or other cash fees in fully vested shares of Cisco common stock, fully vested deferred stock units that would be settled in shares after the non-employee director leaves the Board, or a deferred cash payment under the Cisco Systems, Inc. Deferred Compensation Plan. Upon his appointment, pursuant to the Board’s equity grant policy for non-employee directors, Mr. Shimer automatically received a fully vested initial non-employee director equity award under Cisco’s 2005 Stock Incentive Plan with a grant date fair value equal to a pro rata portion of $270,000 based on the portion of the year of his board service. Non-employee directors may elect to defer receipt of the equity award such that the award would be settled in shares after the non-employee director leaves the Board. Non-employee directors are also eligible to participate in Cisco’s charitable matching gifts program (for calendar year 2026, the maximum match amount is $25,000 for Cisco's non-employee directors).\n\nIn connection with his appointment, Mr. Shimer has entered into Cisco’s standard form of Indemnity Agreement with Cisco which provides for indemnification of an indemnitee to the fullest extent permitted by law. The foregoing description of the Indemnity Agreement does not purport to be complete and is qualified in its entirety by the full text of the form of Indemnity Agreement, which was filed with the Securities and Exchange Commission on January 25, 2021 as Exhibit 10.1 to Cisco’s Current Report on Form 8-K.\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/CSX.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/CSX.jsonl new file mode 100644 index 0000000..540622e --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/CSX.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "CSX", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001193125-26-140177", "url": "https://www.sec.gov/Archives/edgar/data/277948/000119312526140177/xslF345X06/ownership.xml", "ingested_at": "2026-04-09T14:35:39.473435"}, "parsed_data": {"reporting_owner": "ANGEL STEPHEN F", "role": "President & CEO", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/GOOGL.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/GOOGL.jsonl new file mode 100644 index 0000000..31706b8 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/GOOGL.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "GOOGL", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001193125-26-142372", "url": "https://www.sec.gov/Archives/edgar/data/1652044/000119312526142372/xslF345X06/ownership.xml", "ingested_at": "2026-04-09T14:35:17.511403"}, "parsed_data": {"reporting_owner": "O'Toole Amie Thuener", "role": "VP, Chief Accounting Officer", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 617.0, "price": 289.63, "total_value": 178701.71, "post_transaction_shares": 10093.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "GOOGL", "form_type": "8-K", "filed_at": "2026-04-02", "accession_no": "0001652044-26-000031", "url": "https://www.sec.gov/Archives/edgar/data/1652044/000165204426000031/goog-20260330.htm", "ingested_at": "2026-04-09T14:35:17.690647"}, "parsed_data": {"is_chunked": true, "item_chunks": {"5.02": "Item 5.02 Departure of Directors or Certain Officers; Election of Directors; Appointment of Certain Officers; Compensatory Arrangements of Certain Officers.\n\nOn March 30, 2026, Amie Thuener O'Toole notified Alphabet Inc. (the “Company”) of her resignation as Vice President, Corporate Controller and Principal Accounting Officer of the Company, effective April 9, 2026, to pursue another professional opportunity. Ms. O'Toole’s decision to resign did not result from any disagreement with the Company on any matter relating to the Company’s operations, policies, or practices.\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/HON.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/HON.jsonl new file mode 100644 index 0000000..e04e533 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/HON.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "HON", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0000773840-26-000025", "url": "https://www.sec.gov/Archives/edgar/data/773840/000077384026000025/xslF345X06/wk-form4_1775167050.xml", "ingested_at": "2026-04-09T14:35:27.962067"}, "parsed_data": {"reporting_owner": "Flint Deborah", "role": "Other", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "HON", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0000773840-26-000024", "url": "https://www.sec.gov/Archives/edgar/data/773840/000077384026000024/xslF345X06/wk-form4_1775166995.xml", "ingested_at": "2026-04-09T14:35:28.141392"}, "parsed_data": {"reporting_owner": "ANGOVE DUNCAN", "role": "Other", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/INTC.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/INTC.jsonl new file mode 100644 index 0000000..ad3e55d --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/INTC.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "INTC", "form_type": "8-K", "filed_at": "2026-04-08", "accession_no": "0000050863-26-000072", "url": "https://www.sec.gov/Archives/edgar/data/50863/000005086326000072/intc-20260408.htm", "ingested_at": "2026-04-09T14:35:30.225494"}, "parsed_data": {"is_chunked": true, "item_chunks": {"8.01": "Item 8.01    Other Events\n\nOn April 8, 2026, Intel Corporation (“Intel”) repurchased from Apollo-managed funds and affiliates their 49% equity interest in the parties’ joint venture related to Intel’s Fab 34 in Ireland. The $14.2 billion repurchase price was financed by Intel with cash on hand and a bridge loan of $6.5 billion, which Intel intends to refinance, subject to market conditions. Intel owns 100% of the joint venture following the repurchase.\n\nThe joint venture was created and operated pursuant to agreements entered into by the parties in June 2024. At that time, Apollo-managed funds and affiliates acquired their 49% ownership interest in the joint venture and the parties entered into ancillary agreements with respect to Intel’s construction, commissioning, operation, management, maintenance, utilization and purchase of wafers produced in Fab 34. The repurchase of the joint venture interest by Intel was completed pursuant to an April 1, 2026 agreement between the parties, and Intel expects to terminate the various ancillary agreements that had governed the arrangement and wind up the joint venture.", "9.01": "Item 9.01     Financial Statements and Exhibits.\n\n(d)     Exhibits.\n\nThe following exhibits are provided as part of this report:\n\n| | | | | | |\n| --- | --- | --- | --- | --- | --- |\n| | | | | | |\n| Exhibit Number | | | Description | | |\n| 104 | | | Cover Page Interactive Data File, formatted in Inline XBRL and included as Exhibit 101. | | |\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} +{"metadata": {"ticker": "INTC", "form_type": "8-K", "filed_at": "2026-04-03", "accession_no": "0000050863-26-000069", "url": "https://www.sec.gov/Archives/edgar/data/50863/000005086326000069/intc-20260330.htm", "ingested_at": "2026-04-09T14:35:30.447636"}, "parsed_data": {"is_chunked": true, "item_chunks": {"5.02": "Item 5.02    Departure of Directors or Certain Officers; Election of Directors; Appointment of Certain Officers; Compensatory Arrangements of Certain Officers.\n\nOn March 30,2026, Intel Corporation determined that April Miller Boise, Intel’s Executive Vice President and Chief Legal Officer, will separate from Intel effective as of June 1, 2026. Upon her departure on June 1, 2026, Ms. Miller Boise will be entitled to severance benefits in accordance with the terms and conditions of the Intel Corporation Executive Severance Plan, as previously disclosed, in exchange for a release of claims in favor of Intel.", "9.01": "Item 9.01     Financial Statements and Exhibits.\n\n(d)     Exhibits.\n\nThe following exhibits are provided as part of this report:\n\n| | | | | | |\n| --- | --- | --- | --- | --- | --- |\n| | | | | | |\n| Exhibit Number | | | Description | | |\n| 104 | | | Cover Page Interactive Data File, formatted in Inline XBRL and included as Exhibit 101. | | |\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/INTU.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/INTU.jsonl new file mode 100644 index 0000000..487814f --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/INTU.jsonl @@ -0,0 +1,6 @@ +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023706", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023706/xslF345X06/wk-form4_1775249487.xml", "ingested_at": "2026-04-09T14:35:25.927869"}, "parsed_data": {"reporting_owner": "Goodarzi Sasan K", "role": "CEO, President and Director", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 653.529, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 14264.957, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 893.612, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 15158.569, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 802.006, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 15960.575, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 863.013, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 16823.588, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 30.832, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 16854.42, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 1277.861, "price": 432.38, "total_value": 552521.5391800001, "post_transaction_shares": 15576.559, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023704", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023704/xslF345X06/wk-form4_1775249417.xml", "ingested_at": "2026-04-09T14:35:26.123455"}, "parsed_data": {"reporting_owner": "McLean Kerry J", "role": "EVP, Gen. Counsel & Corp. Sec.", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 244.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 28657.7666, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 236.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 28893.7666, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 199.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 29092.7666, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 170.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 29262.7666, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 301.627, "price": 432.38, "total_value": 130417.48226, "post_transaction_shares": 28961.1396, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023701", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023701/xslF345X06/wk-form4_1775249278.xml", "ingested_at": "2026-04-09T14:35:26.302636"}, "parsed_data": {"reporting_owner": "Hotz Lauren D", "role": "SVP, Chief Accounting Officer", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 41.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 2055.7352, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 104.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 2159.7352, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 97.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 2256.7352, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 88.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 2344.7352, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 120.548, "price": 432.38, "total_value": 52122.54424, "post_transaction_shares": 2224.1872, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023698", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023698/xslF345X06/wk-form4_1775249186.xml", "ingested_at": "2026-04-09T14:35:26.503339"}, "parsed_data": {"reporting_owner": "Hilliard Caryl Lyn", "role": "EVP, People and Places", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 122.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 23018.008, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 110.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 23128.008, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 87.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 23215.008, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 150.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 23365.008, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 212.093, "price": 432.38, "total_value": 91704.77133999999, "post_transaction_shares": 23152.915, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023696", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023696/xslF345X06/wk-form4_1775249122.xml", "ingested_at": "2026-04-09T14:35:26.683379"}, "parsed_data": {"reporting_owner": "Hanebrink Anton", "role": "EVP, Corp Strategy and Dev", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 348.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 29953.249, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 252.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 30205.249, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 224.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 30429.249, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 418.253, "price": 432.38, "total_value": 180844.23213999998, "post_transaction_shares": 30010.996, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023690", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023690/xslF345X06/wk-form4_1775248743.xml", "ingested_at": "2026-04-09T14:35:26.860677"}, "parsed_data": {"reporting_owner": "Aujla Sandeep", "role": "EVP and CFO", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 2665.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 3239.1366, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 346.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 3585.1366, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 349.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 3934.1366, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 1725.362, "price": 432.38, "total_value": 746012.02156, "post_transaction_shares": 2208.7746, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/MDLZ.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/MDLZ.jsonl new file mode 100644 index 0000000..e391ee7 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/MDLZ.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "MDLZ", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023648", "url": "https://www.sec.gov/Archives/edgar/data/1103982/000162828026023648/xslF345X06/wk-form4_1775247097.xml", "ingested_at": "2026-04-09T14:35:34.436405"}, "parsed_data": {"reporting_owner": "Lilak Stephanie", "role": "EVP and Chief People Officer", "transactions": [{"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 3218.0, "price": 57.07, "total_value": 183651.26, "post_transaction_shares": 24118.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "MDLZ", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023646", "url": "https://www.sec.gov/Archives/edgar/data/1103982/000162828026023646/xslF345X06/wk-form4_1775247057.xml", "ingested_at": "2026-04-09T14:35:34.616247"}, "parsed_data": {"reporting_owner": "Kuhn Volker", "role": "EVP and President, Europe", "transactions": [{"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 90.0, "price": 57.07, "total_value": 5136.3, "post_transaction_shares": 25820.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/MELI.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/MELI.jsonl new file mode 100644 index 0000000..1b072ed --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/MELI.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "MELI", "form_type": "8-K", "filed_at": "2026-04-03", "accession_no": "0001999371-26-007656", "url": "https://www.sec.gov/Archives/edgar/data/1099590/000199937126007656/meli_8k-033126.htm", "ingested_at": "2026-04-09T14:35:38.947891"}, "parsed_data": {"is_chunked": true, "item_chunks": {"5.02": "Item 5.02** | **Departure of Directors or Certain Officers; Election of Directors; Appointment of Certain Officers; Compensatory Arrangements of Certain Officers.** |\n\n**Establishment of Performance Goals under the 2026 Bonus Program**\n\nOn March 31, 2026, the Board of Directors (the “Board”) of\nMercadoLibre, Inc. (the “Company”) established the performance goals for the Company’s bonus program for the 2026 fiscal\nyear (the “2026 Bonus Program”). Under the 2026 Bonus Program, the bonus payout for each of Ariel Szarfsztejn (Chief Executive\nOfficer), Marcos Galperin (Executive Chairman), Osvaldo Giménez (Fintech President), Daniel Rabinovich (Technology & Operations\nPresident), and Martin de los Santos (EVP and Chief Financial Officer) (referred to below as “NEOs”) is based on achievement\nof Net revenues and financial income (in constant dollars), Income from operations (in constant dollars), Total payment volume - adjusted\n(the total sum of all transactions paid for using Mercado Pago, including marketplace and non-marketplace transactions, excluding peer-to-peer\ntransactions) (in constant dollars) and the Company’s Competitive Net Promoter Score. The Board has determined a target bonus for\neach NEO and applies an adjustment of up to + 50% or -50% to each bonus based upon the individual performance of each NEO.\n\nThe Board set each NEO’s target bonus under the 2026 Bonus Program\nas four months of base salary (33.33% of each NEO’s annual base salary).\n\n**Adoption of the 2026 Long Term Retention Program**\n\nOn March 31, 2026, the Board approved the adoption of the 2026 Long\nTerm Retention Program (the “2026 LTRP”) and, after taking into account a compensation competitiveness analysis carried out\nby the Company’s independent third-party compensation consultant, established the target award for each NEO under the 2026 LTRP.\nThe 2026 LTRP provides the NEOs, along with other members of senior management, with the opportunity to receive cash payments annually\nfor a period of six years (with the first payment occurring between January 1, 2027 and April 30, 2027, as determined by the Company),\nsubject to continued employment on each payment date (other than in specified circumstances). Each award to an NEO under the 2026 LTRP is deemed to have a Grant Date\n(as defined in the 2026 LTRP) of January 1, 2026. Under the 2026 LTRP, each NEO shall receive:\n\n| | | | |\n| --- | --- | --- | --- |\n| | ● | | 16.66% of half of his or her target 2026 LTRP award annually for a period of six years (with the first payment occurring between January 1, 2027 and April 30, 2027) (the “Annual Fixed Payment”); and |\n\n| | | | |\n| --- | --- | --- | --- |\n| | ● | | on each date the Company pays the Annual Fixed Payment, each NEO will also receive a payment equal to the product of (i) 16.66% of half of the NEO’s target 2026 LTRP award and (ii) the quotient of (a) the Applicable Year Stock Price (as defined below) over (b) the average closing price of the Company’s common stock on NASDAQ during the final 60 trading days of 2025. For purposes of the 2026 LTRP, the “Applicable Year Stock Price” is the average closing price of the Company’s common stock on NASDAQ during the final 60 trading days of the fiscal year preceding the fiscal year in which the applicable payment date occurs, for so long as our common stock is listed on NASDAQ. |\n\nThe target 2026 LTRP awards for our NEOs are set forth below.\n\n| | | | | | | |\n| --- | --- | --- | --- | --- | --- | --- |\n| Name | | Title | | Target 2026 LTRP Award (nominal) | | |\n| Ariel Szarfsztejn | | Chief Executive Officer | | $ | 14,000,000 | |\n| Osvaldo Giménez | | Fintech President | | $ | 10,000,000 | |\n| Daniel Rabinovich | | Technology & Operations President | | $ | 10,000,000 | |\n| Martin de los Santos | | Executive Vice President & Chief Financial Officer | | $ | 4,000,000 | |\n| Marcos Galperin | | Executive Chairman | | $ | 3,500,000 | |\n\n| |\n| --- |\n| |\n\nThe foregoing description of the 2026 LTRP does not purport to be complete\nand is qualified in its entirety by reference to the full text of the 2026 LTRP, which is filed as Exhibit 10.1 to this Current Report\non Form 8-K and is incorporated herein by reference.\n\n| | |\n| --- | --- |\n| **Item 9.01** | **Financial Statements and Exhibits.** |\n\n| | |\n| --- | --- |\n| (d) | *Exhibits.* |\n\nThe following exhibits are filed herewith.\n\n| | | | |\n| --- | --- | --- | --- |\n| **Exhibit** **Number** | | | **Description** |\n| | | | |\n| 10.1 | | | MercadoLibre, Inc. 2026 Long Term Retention Program |\n\n| |\n| --- |\n| |\n\n**EXHIBIT INDEX**\n\n| | | |\n| --- | --- | --- |\n| **Exhibit** **Number** | | **Description** |\n| | | |\n| 10.1 | | MercadoLibre, Inc. 2026 Long Term Retention Program |\n\n| |\n| --- |\n| |\n\n**SIGNATURES**\n\nPursuant to the requirements of the Securities Exchange\nAct of 1934, the registrant has duly caused this report to be signed on its behalf by the undersigned hereunto duly authorized.\n\n| | | | |\n| --- | --- | --- | --- |\n| | MercadoLibre, Inc. | | |\n| | | | |\n| Dated: April 3, 2026 | By: | /s/ Martin de los Santos | |\n| | Name: | Martin de los Santos | |\n| | Title: | Executive Vice President and Chief Financial Officer | |\n| | | | |\n\n \n\n| |\n| --- |\n| |"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/MU.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/MU.jsonl new file mode 100644 index 0000000..aea898c --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/MU.jsonl @@ -0,0 +1,3 @@ +{"metadata": {"ticker": "MU", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001632063-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/723125/000163206326000002/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-09T14:35:37.247639"}, "parsed_data": {"reporting_owner": "ARNZEN APRIL S", "role": "EVP and Chief People Officer", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 8630.0, "price": 345.13, "total_value": 2978471.9, "post_transaction_shares": 157107.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 5766.0, "price": 346.22, "total_value": 1996304.5200000003, "post_transaction_shares": 151341.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 604.0, "price": 346.83, "total_value": 209485.31999999998, "post_transaction_shares": 150737.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 25000.0, "price": 348.46, "total_value": 8711500.0, "post_transaction_shares": 125737.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "MU", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0002058769-26-000003", "url": "https://www.sec.gov/Archives/edgar/data/723125/000205876926000003/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-09T14:35:37.436214"}, "parsed_data": {"reporting_owner": "Liu Teyin M", "role": "Director", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 97.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 26007.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "MU", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001218363-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/723125/000121836326000002/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-09T14:35:37.631316"}, "parsed_data": {"reporting_owner": "SWAN ROBERT HOLMES", "role": "Director", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/NFLX.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/NFLX.jsonl new file mode 100644 index 0000000..5e30f63 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/NFLX.jsonl @@ -0,0 +1,13 @@ +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001543133-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000154313326000002/xslF345X06/wk-form4_1775246849.xml", "ingested_at": "2026-04-09T14:35:20.179845"}, "parsed_data": {"reporting_owner": "Neumann Spencer Adam", "role": "Chief Financial Officer", "transactions": [{"date": "2026-04-02", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 7770.0, "price": 38.105, "total_value": 296075.85, "post_transaction_shares": 81557.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 20860.0, "price": 36.408, "total_value": 759470.88, "post_transaction_shares": 102417.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 28630.0, "price": 98.0, "total_value": 2805740.0, "post_transaction_shares": 73787.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001065280-26-000136", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000136/xslF345X06/wk-form4_1775167371.xml", "ingested_at": "2026-04-09T14:35:20.363391"}, "parsed_data": {"reporting_owner": "KILGORE LESLIE J", "role": "Other", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001065280-26-000135", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000135/xslF345X06/wk-form4_1775167364.xml", "ingested_at": "2026-04-09T14:35:20.558314"}, "parsed_data": {"reporting_owner": "Masiyiwa Strive", "role": "Other", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001065280-26-000134", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000134/xslF345X06/wk-form4_1775167354.xml", "ingested_at": "2026-04-09T14:35:20.736570"}, "parsed_data": {"reporting_owner": "HASTINGS REED", "role": "Other", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 420550.0, "price": 9.437, "total_value": 3968730.3499999996, "post_transaction_shares": 424490.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 152047.0, "price": 95.015, "total_value": 14446745.705, "post_transaction_shares": 272443.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 247923.0, "price": 95.6767, "total_value": 23720454.4941, "post_transaction_shares": 24520.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 20580.0, "price": 96.6601, "total_value": 1989264.858, "post_transaction_shares": 3940.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001065280-26-000133", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000133/xslF345X06/wk-form4_1775167345.xml", "ingested_at": "2026-04-09T14:35:20.920087"}, "parsed_data": {"reporting_owner": "Sweeney Anne M", "role": "Other", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001065280-26-000132", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000132/xslF345X06/wk-form4_1775167337.xml", "ingested_at": "2026-04-09T14:35:21.097069"}, "parsed_data": {"reporting_owner": "MATHER ANN", "role": "Other", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001065280-26-000131", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000131/xslF345X06/wk-form4_1775167309.xml", "ingested_at": "2026-04-09T14:35:21.299072"}, "parsed_data": {"reporting_owner": "Dopfner Mathias", "role": "Other", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001065280-26-000130", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000130/xslF345X06/wk-form4_1775167302.xml", "ingested_at": "2026-04-09T14:35:21.484003"}, "parsed_data": {"reporting_owner": "Karbowski Jeffrey William", "role": "Chief Accounting Officer", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001065280-26-000129", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000129/xslF345X06/wk-form4_1775167293.xml", "ingested_at": "2026-04-09T14:35:21.680015"}, "parsed_data": {"reporting_owner": "SMITH BRADFORD L", "role": "Other", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001065280-26-000128", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000128/xslF345X06/wk-form4_1775167286.xml", "ingested_at": "2026-04-09T14:35:21.886292"}, "parsed_data": {"reporting_owner": "RICE SUSAN E", "role": "Other", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001065280-26-000127", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000127/xslF345X06/wk-form4_1775167280.xml", "ingested_at": "2026-04-09T14:35:22.063677"}, "parsed_data": {"reporting_owner": "BARTON RICHARD N", "role": "Other", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001065280-26-000126", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000126/xslF345X06/wk-form4_1775167264.xml", "ingested_at": "2026-04-09T14:35:22.240648"}, "parsed_data": {"reporting_owner": "Mertz Elinor", "role": "Other", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001082906-26-000012", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000108290626000012/xslF345X06/form4.xml", "ingested_at": "2026-04-09T14:35:22.436192"}, "parsed_data": {"reporting_owner": "Hoag Jay C", "role": "Other", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/PANW.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/PANW.jsonl new file mode 100644 index 0000000..583fa73 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/PANW.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "PANW", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001882285-26-000007", "url": "https://www.sec.gov/Archives/edgar/data/1327567/000188228526000007/xslF345X06/ownership.xml", "ingested_at": "2026-04-09T14:35:33.668336"}, "parsed_data": {"reporting_owner": "Paul Josh D.", "role": "Chief Accounting Officer", "transactions": [{"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 947.0, "price": 160.32, "total_value": 151823.03999999998, "post_transaction_shares": 84236.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1100.0, "price": 161.4, "total_value": 177540.0, "post_transaction_shares": 83136.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "PANW", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001852540-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/1327567/000185254026000002/xslF345X06/ownership.xml", "ingested_at": "2026-04-09T14:35:33.898298"}, "parsed_data": {"reporting_owner": "Golechha Dipak", "role": "EVP, Chief Financial Officer", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 200.0, "price": 157.81, "total_value": 31562.0, "post_transaction_shares": 155050.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1300.0, "price": 160.039, "total_value": 208050.69999999998, "post_transaction_shares": 153750.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 3500.0, "price": 160.704, "total_value": 562464.0, "post_transaction_shares": 150250.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/QCOM.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/QCOM.jsonl new file mode 100644 index 0000000..c1abbed --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/QCOM.jsonl @@ -0,0 +1,3 @@ +{"metadata": {"ticker": "QCOM", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0000804328-26-000051", "url": "https://www.sec.gov/Archives/edgar/data/804328/000080432826000051/xslF345X06/edgardoc.xml", "ingested_at": "2026-04-09T14:35:24.838654"}, "parsed_data": {"reporting_owner": "Grech Patricia Y", "role": "SVP, Chief Accounting Officer", "transactions": [{"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 85.0, "price": 125.5, "total_value": 10667.5, "post_transaction_shares": 192.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "QCOM", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0000804328-26-000049", "url": "https://www.sec.gov/Archives/edgar/data/804328/000080432826000049/xslF345X06/edgardoc.xml", "ingested_at": "2026-04-09T14:35:25.016213"}, "parsed_data": {"reporting_owner": "MCLAUGHLIN MARK D", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 538.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 12849.8312, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "QCOM", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0000804328-26-000048", "url": "https://www.sec.gov/Archives/edgar/data/804328/000080432826000048/xslF345X06/edgardoc.xml", "ingested_at": "2026-04-09T14:35:25.193502"}, "parsed_data": {"reporting_owner": "TRICOIRE JEAN-PASCAL", "role": "Other", "transactions": [{"date": "2026-03-31", "code": "A", "direction": "OTHER (A)", "shares": 262.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 13481.4716, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/REGN.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/REGN.jsonl new file mode 100644 index 0000000..f48c607 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/REGN.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "REGN", "form_type": "8-K", "filed_at": "2026-04-08", "accession_no": "0001104659-26-040661", "url": "https://www.sec.gov/Archives/edgar/data/872589/000110465926040661/tm2611354d1_8k.htm", "ingested_at": "2026-04-09T14:35:35.330815"}, "parsed_data": {"is_chunked": true, "item_chunks": {"2.02": "Item 2.02.** | **Results of Operations and Financial Condition.** |\n\nRegeneron Pharmaceuticals, Inc. (“Regeneron”\nor the “Company”) currently expects that its financial results calculated in accordance with U.S. generally accepted\naccounting principles (“GAAP”) and its non-GAAP financial results for the first quarter 2026 will include an acquired\nin-process research and development (“IPR&D”) charge of approximately $102 million on a pre-tax basis. This charge\nprimarily relates to premium on equity securities purchased, as well as development milestone and up-front payments, in connection with\ncollaboration and licensing agreements. The acquired IPR&D charge is expected to negatively impact each of GAAP and non-GAAP net income\nper diluted share for the first quarter 2026 by approximately $0.81.\n\nAcquired IPR&D charges may include IPR&D\nacquired in connection with asset acquisitions as well as up-front, opt-in, certain development milestone payments, and premiums paid\non equity securities related to collaboration and licensing agreements. Regeneron does not forecast such acquired IPR&D charges due\nto the uncertainty of the future occurrence, magnitude, and timing of these transactions in any given period.\n\nRegeneron’s results for the first quarter\n2026 have not been finalized and are subject to Regeneron’s financial statement closing procedures. There can be no assurance that\nactual results will not differ from the preliminary (unaudited) estimates described herein.\n\nThe information included in this Current Report\non Form 8-K shall not be deemed “filed” for purposes of Section 18 of the Securities Exchange Act of 1934, as amended,\nnor shall such information be deemed incorporated by reference in any filing under the Securities Act of 1933, as amended, except as shall\nbe expressly set forth by specific reference in such a filing.\n\n***Note\nRegarding Forward-Looking Statements***\n\n*This Current Report\non Form 8-K (this “Report”) includes forward-looking statements that involve risks and uncertainties relating\nto future events and the future performance of Regeneron Pharmaceuticals, Inc. (“Regeneron” or the “Company”),\nand actual events or results may differ materially from these forward-looking statements. Words such as “anticipate,” “expect,”\n“intend,” “plan,” “believe,” “seek,” “estimate,” variations of such words,\nand similar expressions are intended to identify such forward-looking statements, although not all forward-looking statements contain\nthese identifying words. These statements concern, and these risks and uncertainties include, among others, Regeneron’s expected\nacquired in-process research and development charge for the quarterly period ended March 31, 2026 and its expected impact on GAAP\nand non-GAAP net income per diluted share for this period as discussed in this Report. A more complete description of these and other\nmaterial risks can be found in Regeneron’s filings with the U.S. Securities and Exchange Commission. Any forward-looking statements\nare made based on management’s current beliefs and judgment, and the reader is cautioned not to rely on any forward-looking statements\nmade by Regeneron. Regeneron does not undertake any obligation to update (publicly or otherwise) any forward-looking statement, including\nwithout limitation any financial projection or guidance, whether as a result of new information, future events, or otherwise.*\n\n***Note Regarding Non-GAAP Financial Measures***\n\n*This Report references non-GAAP net income\nper diluted share, which is a financial measure that is not calculated in accordance with U.S. Generally Accepted Accounting Principles\n(“GAAP”). This non-GAAP financial measure is computed by excluding certain non-cash and/or other items from the related\nGAAP financial measure. The Company also includes a non-GAAP adjustment for the estimated income tax effect of reconciling items. The\nCompany makes such adjustments for items the Company does not view as useful in evaluating its operating performance. Management uses\nthis and other non-GAAP measures for planning, budgeting, forecasting, assessing historical performance, and making financial and operational\ndecisions, and also provides forecasts to investors on this basis. Additionally, such non-GAAP measures provide investors with an enhanced\nunderstanding of the financial performance of the Company's core business operations. However, there are limitations in the use of such\nnon-GAAP financial measures as they exclude certain expenses that are recurring in nature. Furthermore, the Company's non-GAAP financial\nmeasures may not be comparable with non-GAAP information provided by other companies. Any non-GAAP financial measure presented by Regeneron\nshould be considered supplemental to, and not a substitute for, measures of financial performance prepared in accordance with GAAP.*\n\n**SIGNATURES**\n\nPursuant to the requirements of the Securities\nExchange Act of 1934, the registrant has duly caused this report to be signed on its behalf by the undersigned thereunto duly authorized.\n\n| | |\n| --- | --- |\n| | **REGENERON PHARMACEUTICALS, INC.** |\n| | |\n| | /s/ Joseph J. LaRosa |\n| | Joseph J. LaRosa |\n| | Executive Vice President, General Counsel and Secretary |\n\nDate: April 8, 2026"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} +{"metadata": {"ticker": "REGN", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001104659-26-039613", "url": "https://www.sec.gov/Archives/edgar/data/872589/000110465926039613/xslF345X06/tm2611142-1_4seq1.xml", "ingested_at": "2026-04-09T14:35:35.555547"}, "parsed_data": {"reporting_owner": "RYAN ARTHUR F", "role": "Other", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1.0, "price": 771.32, "total_value": 771.32, "post_transaction_shares": 17702.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 3.0, "price": 772.76, "total_value": 2318.2799999999997, "post_transaction_shares": 17699.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 8.0, "price": 773.59, "total_value": 6188.72, "post_transaction_shares": 17691.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 8.0, "price": 774.58, "total_value": 6196.64, "post_transaction_shares": 17683.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 14.0, "price": 775.58, "total_value": 10858.12, "post_transaction_shares": 17669.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 13.0, "price": 776.62, "total_value": 10096.06, "post_transaction_shares": 17656.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 9.0, "price": 777.42, "total_value": 6996.78, "post_transaction_shares": 17647.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 4.0, "price": 778.24, "total_value": 3112.96, "post_transaction_shares": 17643.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 40.0, "price": 779.71, "total_value": 31188.4, "post_transaction_shares": 17603.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/SBUX.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/SBUX.jsonl new file mode 100644 index 0000000..19345b9 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/SBUX.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "SBUX", "form_type": "4", "filed_at": "2026-04-08", "accession_no": "0000829224-26-000066", "url": "https://www.sec.gov/Archives/edgar/data/829224/000082922426000066/xslF345X06/form4.xml", "ingested_at": "2026-04-09T14:35:32.974848"}, "parsed_data": {"reporting_owner": "BREWER BRADY", "role": "ceo, International", "transactions": [{"date": "2026-04-06", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1641.0, "price": 90.0, "total_value": 147690.0, "post_transaction_shares": 84375.502, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "SBUX", "form_type": "8-K", "filed_at": "2026-04-02", "accession_no": "0000829224-26-000064", "url": "https://www.sec.gov/Archives/edgar/data/829224/000082922426000064/sbux-20260402.htm", "ingested_at": "2026-04-09T14:35:33.155022"}, "parsed_data": {"is_chunked": true, "item_chunks": {"7.01": "Item 7.01    Regulation FD Disclosure.\n\nAs previously disclosed on November 3, 2025, Starbucks entered an agreement to form a joint venture with Boyu Capital. On April 2, 2026, Starbucks announced that, following the satisfaction of all necessary closing conditions, it completed the transaction. Pursuant to the transaction, funds managed by Boyu Capital have acquired a 60% interest in Starbucks retail operations in China. Starbucks retains a 40% interest and will serve as the owner and licensor of the Starbucks global brand.\n\nA copy of the press release issued is furnished as Exhibit 99.1 to this Form 8-K.\n\nThe information contained in Item 7.01 of this report, including the information in Exhibit 99.1, is furnished pursuant to Item 7.01 of Form 8-K and shall not be deemed “filed” for the purposes of Section 18 of the Securities Exchange Act of 1934, as amended, or otherwise subject to the liabilities of that section. Furthermore, the information in Item 7.01 of this report, including the information in Exhibit 99.1 attached to this report, shall not be deemed to be incorporated by reference in the filings of Starbucks Corporation under the Securities Act of 1933, as amended.", "9.01": "Item 9.01Financial Statements and Exhibits.\n\n(d) Exhibits.\n\n| | | | | | | | | |\n| --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| | | | | | | | | |\n| Exhibit No. | | | | | | Description | | |\n| 99.1 | | | | | | Press Release, dated April 2, 2026 | | |\n| 104 | | | | | | Cover Page Interactive Data File (formatted as inline XBRL) | | |\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/TSLA.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/TSLA.jsonl new file mode 100644 index 0000000..4e78e85 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/TSLA.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "TSLA", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001972928-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/1318605/000197292826000002/xslF345X06/edgardoc.xml", "ingested_at": "2026-04-09T14:35:18.193427"}, "parsed_data": {"reporting_owner": "Zhu Xiaotong", "role": "SVP", "transactions": [{"date": "2026-03-31", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 20000.0, "price": 20.57, "total_value": 411400.0, "post_transaction_shares": 20000.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "TSLA", "form_type": "8-K", "filed_at": "2026-04-02", "accession_no": "0001628280-26-022956", "url": "https://www.sec.gov/Archives/edgar/data/1318605/000162828026022956/tsla-20260402.htm", "ingested_at": "2026-04-09T14:35:18.370698"}, "parsed_data": {"is_chunked": true, "item_chunks": {"2.02": "Item 2.02    Results of Operations and Financial Condition.\n\nOn April 2, 2026, Tesla, Inc. published the press release which is attached hereto as Exhibit 99.1 and is incorporated herein by reference.\n\nThis information is intended to be furnished under Item 2.02 of Form 8-K and shall not be deemed “filed” for purposes of Section 18 of the Securities Exchange Act of 1934, as amended (the “Exchange Act”), or incorporated by reference in any filing under the Securities Act of 1933, as amended, or the Exchange Act as shall be expressly set forth by specific reference in such a filing.", "9.01": "Item 9.01    Financial Statements and Exhibits.\n\n(d)Exhibits.\n\n| | | | | | | | | |\n| --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| | | | | | | | | |\n| Exhibit No. | | | | | | Description | | |\n| | | | | | | | | |\n| 99.1 | | | | | | Press release of Tesla, Inc., dated April 2, 2026. | | |\n| 104 | | | | | | Cover Page Interactive Data File (embedded within the Inline XBRL document). | | |\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/VRTX.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/VRTX.jsonl new file mode 100644 index 0000000..83f48e0 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/VRTX.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "VRTX", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0000875320-26-000157", "url": "https://www.sec.gov/Archives/edgar/data/875320/000087532026000157/xslF345X06/wk-form4_1775249628.xml", "ingested_at": "2026-04-09T14:35:32.500592"}, "parsed_data": {"reporting_owner": "Liu Joy", "role": "EVP and Chief Legal Officer", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 978.0, "price": 449.17, "total_value": 439288.26, "post_transaction_shares": 21833.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/_SUMMARY.json b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/_SUMMARY.json new file mode 100644 index 0000000..548c78e --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-09/_SUMMARY.json @@ -0,0 +1,110 @@ +{ + "date": "2026-04-09", + "total_filings": 66, + "ticker_breakdown": { + "QCOM": { + "4": 3, + "8-K": 0 + }, + "MELI": { + "4": 0, + "8-K": 1 + }, + "CRWD": { + "4": 0, + "8-K": 1 + }, + "AMZN": { + "4": 1, + "8-K": 1 + }, + "VRTX": { + "4": 1, + "8-K": 0 + }, + "ADI": { + "4": 1, + "8-K": 0 + }, + "PANW": { + "4": 2, + "8-K": 0 + }, + "AMAT": { + "4": 1, + "8-K": 0 + }, + "MU": { + "4": 3, + "8-K": 0 + }, + "CSX": { + "4": 1, + "8-K": 0 + }, + "AMD": { + "4": 1, + "8-K": 0 + }, + "INTU": { + "4": 6, + "8-K": 0 + }, + "AAPL": { + "4": 3, + "8-K": 0 + }, + "CDNS": { + "4": 1, + "8-K": 0 + }, + "CMCSA": { + "4": 6, + "8-K": 0 + }, + "NFLX": { + "4": 13, + "8-K": 0 + }, + "INTC": { + "4": 0, + "8-K": 2 + }, + "GOOGL": { + "4": 1, + "8-K": 1 + }, + "TSLA": { + "4": 1, + "8-K": 1 + }, + "BKNG": { + "4": 0, + "8-K": 2 + }, + "CSCO": { + "4": 1, + "8-K": 1 + }, + "MDLZ": { + "4": 2, + "8-K": 0 + }, + "REGN": { + "4": 1, + "8-K": 1 + }, + "AVGO": { + "4": 0, + "8-K": 2 + }, + "SBUX": { + "4": 1, + "8-K": 1 + }, + "HON": { + "4": 2, + "8-K": 0 + } + } +} \ No newline at end of file diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/AAPL.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/AAPL.jsonl new file mode 100644 index 0000000..1d8b743 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/AAPL.jsonl @@ -0,0 +1,3 @@ +{"metadata": {"ticker": "AAPL", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001140361-26-013192", "url": "https://www.sec.gov/Archives/edgar/data/320193/000114036126013192/xslF345X06/form4.xml", "ingested_at": "2026-04-10T16:08:57.435020"}, "parsed_data": {"reporting_owner": "O'BRIEN DEIRDRE", "role": "Senior Vice President", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 64317.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 201127.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 34315.0, "price": 255.63, "total_value": 8771943.45, "post_transaction_shares": 166812.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 20338.0, "price": 255.12, "total_value": 5188630.5600000005, "post_transaction_shares": 146474.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 9664.0, "price": 255.82, "total_value": 2472244.48, "post_transaction_shares": 136810.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "AAPL", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001140361-26-013191", "url": "https://www.sec.gov/Archives/edgar/data/320193/000114036126013191/xslF345X06/form4.xml", "ingested_at": "2026-04-10T16:08:57.674348"}, "parsed_data": {"reporting_owner": "Khan Sabih", "role": "COO", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 64317.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 1107212.0, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 33317.0, "price": 255.63, "total_value": 8516824.709999999, "post_transaction_shares": 1073895.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "AAPL", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001140361-26-013190", "url": "https://www.sec.gov/Archives/edgar/data/320193/000114036126013190/xslF345X06/form4.xml", "ingested_at": "2026-04-10T16:08:57.855148"}, "parsed_data": {"reporting_owner": "COOK TIMOTHY D", "role": "Chief Executive Officer", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 131576.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 3411994.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 66627.0, "price": 255.63, "total_value": 17031860.009999998, "post_transaction_shares": 3345367.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 5087.0, "price": 251.25, "total_value": 1278108.75, "post_transaction_shares": 3340280.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 9147.0, "price": 252.11, "total_value": 2306050.17, "post_transaction_shares": 3331133.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1878.0, "price": 253.13, "total_value": 475378.14, "post_transaction_shares": 3329255.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 16083.0, "price": 254.37, "total_value": 4091032.71, "post_transaction_shares": 3313172.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 28188.0, "price": 255.17, "total_value": 7192731.96, "post_transaction_shares": 3284984.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 4566.0, "price": 256.0, "total_value": 1168896.0, "post_transaction_shares": 3280418.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/ADI.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/ADI.jsonl new file mode 100644 index 0000000..c7ac912 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/ADI.jsonl @@ -0,0 +1,7 @@ +{"metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-09", "accession_no": "0000006281-26-000043", "url": "https://www.sec.gov/Archives/edgar/data/6281/000000628126000043/xslF345X06/wk-form4_1775768645.xml", "ingested_at": "2026-04-10T16:09:14.401049"}, "parsed_data": {"reporting_owner": "Sondel Michael", "role": "CAO (principal acct. officer)", "transactions": [{"date": "2026-04-07", "code": "A", "direction": "OTHER (A)", "shares": 1341.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 15854.578, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-09", "accession_no": "0000006281-26-000042", "url": "https://www.sec.gov/Archives/edgar/data/6281/000000628126000042/xslF345X06/wk-form4_1775768622.xml", "ingested_at": "2026-04-10T16:09:14.605836"}, "parsed_data": {"reporting_owner": "ROCHE VINCENT", "role": "Chair & CEO", "transactions": [{"date": "2026-04-07", "code": "A", "direction": "OTHER (A)", "shares": 19712.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 187537.875, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-09", "accession_no": "0000006281-26-000041", "url": "https://www.sec.gov/Archives/edgar/data/6281/000000628126000041/xslF345X06/wk-form4_1775768603.xml", "ingested_at": "2026-04-10T16:09:14.817000"}, "parsed_data": {"reporting_owner": "Puccio Richard C Jr", "role": "EVP and CFO", "transactions": [{"date": "2026-04-07", "code": "A", "direction": "OTHER (A)", "shares": 6513.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 57968.559, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-09", "accession_no": "0000006281-26-000040", "url": "https://www.sec.gov/Archives/edgar/data/6281/000000628126000040/xslF345X06/wk-form4_1775768583.xml", "ingested_at": "2026-04-10T16:09:15.042283"}, "parsed_data": {"reporting_owner": "Nakamura Katsufumi", "role": "SVP, Chief Customer Officer", "transactions": [{"date": "2026-04-07", "code": "A", "direction": "OTHER (A)", "shares": 4085.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 16230.04, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-09", "accession_no": "0000006281-26-000039", "url": "https://www.sec.gov/Archives/edgar/data/6281/000000628126000039/xslF345X06/wk-form4_1775768561.xml", "ingested_at": "2026-04-10T16:09:15.241550"}, "parsed_data": {"reporting_owner": "Jain Vivek", "role": "EVP, Global Operations", "transactions": [{"date": "2026-04-07", "code": "A", "direction": "OTHER (A)", "shares": 6734.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 48823.474, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-09", "accession_no": "0000006281-26-000038", "url": "https://www.sec.gov/Archives/edgar/data/6281/000000628126000038/xslF345X06/wk-form4_1775768544.xml", "ingested_at": "2026-04-10T16:09:15.424624"}, "parsed_data": {"reporting_owner": "Cotter Martin", "role": "SVP, Vertical Business Units", "transactions": [{"date": "2026-04-07", "code": "A", "direction": "OTHER (A)", "shares": 5807.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 56331.884, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001201872-26-000008", "url": "https://www.sec.gov/Archives/edgar/data/6281/000120187226000008/xslF345X06/wk-form4_1775247205.xml", "ingested_at": "2026-04-10T16:09:15.632149"}, "parsed_data": {"reporting_owner": "ROCHE VINCENT", "role": "Chair & CEO", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 10000.0, "price": 94.41, "total_value": 944100.0, "post_transaction_shares": 177825.875, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 10000.0, "price": 318.14, "total_value": 3181400.0, "post_transaction_shares": 167825.875, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/AMD.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/AMD.jsonl new file mode 100644 index 0000000..7050ea7 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/AMD.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "AMD", "form_type": "4", "filed_at": "2026-04-08", "accession_no": "0000002488-26-000064", "url": "https://www.sec.gov/Archives/edgar/data/2488/000000248826000064/xslF345X06/wk-form4_1775679123.xml", "ingested_at": "2026-04-10T16:09:03.314151"}, "parsed_data": {"reporting_owner": "Papermaster Mark D", "role": "Chief Technology Officer & EVP", "transactions": [{"date": "2026-04-06", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 3293.0, "price": 225.0, "total_value": 740925.0, "post_transaction_shares": 1294466.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/AMZN.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/AMZN.jsonl new file mode 100644 index 0000000..6aa0b15 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/AMZN.jsonl @@ -0,0 +1,7 @@ +{"metadata": {"ticker": "AMZN", "form_type": "4", "filed_at": "2026-04-09", "accession_no": "0002024813-26-000004", "url": "https://www.sec.gov/Archives/edgar/data/1018724/000202481326000004/xslF345X06/wk-form4_1775768551.xml", "ingested_at": "2026-04-10T16:08:58.892947"}, "parsed_data": {"reporting_owner": "Garman Matthew S", "role": "CEO Amazon Web Services", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "AMZN", "form_type": "4", "filed_at": "2026-04-09", "accession_no": "0001936006-26-000010", "url": "https://www.sec.gov/Archives/edgar/data/1018724/000193600626000010/xslF345X06/wk-form4_1775768277.xml", "ingested_at": "2026-04-10T16:08:59.135303"}, "parsed_data": {"reporting_owner": "Herrington Douglas J", "role": "CEO Worldwide Amazon Stores", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "AMZN", "form_type": "4", "filed_at": "2026-04-09", "accession_no": "0001557979-26-000004", "url": "https://www.sec.gov/Archives/edgar/data/1018724/000155797926000004/xslF345X06/wk-form4_1775767969.xml", "ingested_at": "2026-04-10T16:08:59.345422"}, "parsed_data": {"reporting_owner": "Zapolsky David", "role": "Senior Vice President", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "AMZN", "form_type": "4", "filed_at": "2026-04-09", "accession_no": "0001639902-26-000004", "url": "https://www.sec.gov/Archives/edgar/data/1018724/000163990226000004/xslF345X06/wk-form4_1775767715.xml", "ingested_at": "2026-04-10T16:08:59.550965"}, "parsed_data": {"reporting_owner": "Olsavsky Brian T", "role": "Senior Vice President and CFO", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "AMZN", "form_type": "4", "filed_at": "2026-04-09", "accession_no": "0001397333-26-000004", "url": "https://www.sec.gov/Archives/edgar/data/1018724/000139733326000004/xslF345X06/wk-form4_1775767487.xml", "ingested_at": "2026-04-10T16:08:59.756142"}, "parsed_data": {"reporting_owner": "Reynolds Shelley", "role": "Vice President", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "AMZN", "form_type": "8-K", "filed_at": "2026-04-09", "accession_no": "0001104659-26-041034", "url": "https://www.sec.gov/Archives/edgar/data/1018724/000110465926041034/tm263815d2_8k.htm", "ingested_at": "2026-04-10T16:08:59.935246"}, "parsed_data": {"is_chunked": true, "item_chunks": {"7.01": "ITEM 7.01.  REGULATION FD DISCLOSURE.** | **3** |\n| | |\n| **ITEM 9.01.  FINANCIAL STATEMENTS AND EXHIBITS.** | **3** |\n| | |\n| **SIGNATURES** | **4** |\n| | |\n| EXHIBIT 99.1 | |\n| | |\n| EXHIBIT 99.2 | |\n\n2\n\nTable of Contents\n\n**ITEM 7.01.****REGULATION\nFD DISCLOSURE.**\n\nThe Company’s\nLetter to Shareholders, which accompanies its Annual Report for the Year Ended December 31, 2025, is attached as Exhibit 99.1, and a\nreconciliation of a non-GAAP financial measure included in the Letter to Shareholders to the most directly comparable financial\nmeasure calculated and presented in accordance with GAAP is included as Exhibit 99.2.\n\n**ITEM 9.01.  FINANCIAL STATEMENTS AND EXHIBITS.**\n\n***(d) Exhibits.***\n\n| | |\n| --- | --- |\n| **Exhibit** **Number** | **Description** |\n| | |\n| 99.1 | 2025 Letter to Shareholders. |\n| 99.2 | Reconciliation of Non-GAAP Financial Measure. |\n| 104 | The cover page from this Current Report on Form 8-K, formatted in Inline XBRL (included as Exhibit 101). |\n\n3\n\nTable of Contents\n\n**SIGNATURES**\n\nPursuant to the requirements of the Securities Exchange Act of 1934, the registrant has duly caused this report to be signed on its behalf by the\nundersigned hereunto duly authorized.\n\n| | | |\n| --- | --- | --- |\n| | AMAZON.COM, INC. (REGISTRANT) | |\n| | | |\n| | By: | /s/ Susan K. Jong |\n| | | **Susan K. Jong** |\n| | | **Vice President and Secretary** |\n\nDated: April 9, 2026\n\n4"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} +{"metadata": {"ticker": "AMZN", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001018724-26-000010", "url": "https://www.sec.gov/Archives/edgar/data/1018724/000101872426000010/xslF345X06/wk-form4_1775248886.xml", "ingested_at": "2026-04-10T16:09:00.178284"}, "parsed_data": {"reporting_owner": "Herrington Douglas J", "role": "CEO Worldwide Amazon Stores", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1000.0, "price": 210.5, "total_value": 210500.0, "post_transaction_shares": 520361.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/AVGO.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/AVGO.jsonl new file mode 100644 index 0000000..e767b94 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/AVGO.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "AVGO", "form_type": "8-K", "filed_at": "2026-04-06", "accession_no": "0001193125-26-144028", "url": "https://www.sec.gov/Archives/edgar/data/1730168/000119312526144028/d87999d8k.htm", "ingested_at": "2026-04-10T16:09:01.801626"}, "parsed_data": {"is_chunked": true, "item_chunks": {"8.01": "Item 8.01 | Other Events. |\n\nBroadcom Inc. (“Broadcom”) and Google LLC (“Google”) have entered into a Long Term Agreement for Broadcom to develop and supply custom Tensor Processing Units (“TPUs”) for Google’s future generations of TPUs and a Supply Assurance Agreement for Broadcom to supply networking and other components to be used in Google’s next-generation AI racks through up to 2031.\n\nSeparately, Broadcom, Google and Anthropic PBC (“Anthropic”) have expanded their current strategic collaboration under which Anthropic, beginning in 2027, will access through Broadcom approximately 3.5 gigawatts as part of the multiple gigawatts of next generation TPU-based AI compute capacity committed by Anthropic. The consumption of such expanded AI compute capacity by Anthropic is dependent on Anthropic’s continued commercial success. In connection with this deployment, the parties are in discussions with certain operational and financial partners.\n\nCautionary Note Regarding Forward-Looking Statements\n\nThis Current Report on Form 8-K contains forward-looking statements (including within the meaning of Section 21E of the Securities Exchange Act of 1934, as amended, and Section 27A of the Securities Act of 1933, as amended). These forward-looking statements are based on current expectations and beliefs of Broadcom’s management, current information available to Broadcom’s management, and current market trends and market conditions, and involve risks and uncertainties that may cause actual results to differ materially from those contained in the forward-looking statements. Accordingly, undue reliance should not be placed on such statements. All forward-looking statements are qualified in their entirety by reference to the risk factors discussed under the heading “Risk Factors” in Broadcom’s Annual Report on Form 10-K for the year ended November 2, 2025, Quarterly Report on Form 10-Q for the period ended February 1, 2026 and any subsequent reports that are filed with the Securities and Exchange Commission and include some important risk factors that may affect future results. Broadcom undertakes no intent or obligation to publicly update or revise the forward-looking statements made in this Current Report on Form 8-K, except as required by law.\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/CDNS.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/CDNS.jsonl new file mode 100644 index 0000000..dc5d968 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/CDNS.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "CDNS", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0000813672-26-000040", "url": "https://www.sec.gov/Archives/edgar/data/813672/000081367226000040/xslF345X06/wk-form4_1775243708.xml", "ingested_at": "2026-04-10T16:09:16.926489"}, "parsed_data": {"reporting_owner": "Cunningham Paul", "role": "Sr. Vice President", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1000.0, "price": 280.19, "total_value": 280190.0, "post_transaction_shares": 128586.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/CMCSA.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/CMCSA.jsonl new file mode 100644 index 0000000..77d948f --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/CMCSA.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001225208-26-004342", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004342/xslF345X06/doc4.xml", "ingested_at": "2026-04-10T16:09:08.183968"}, "parsed_data": {"reporting_owner": "Murdock Daniel C.", "role": "EVP & Chief Accounting Officer", "transactions": [{"date": "2026-04-03", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 5268.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 64435.0497, "is_10b5_1_planned": false}, {"date": "2026-04-03", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 2073.0, "price": 27.93, "total_value": 57898.89, "post_transaction_shares": 62362.0497, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/CRWD.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/CRWD.jsonl new file mode 100644 index 0000000..87df656 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/CRWD.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "CRWD", "form_type": "8-K", "filed_at": "2026-04-06", "accession_no": "0001535527-26-000013", "url": "https://www.sec.gov/Archives/edgar/data/1535527/000153552726000013/crwd-20260406.htm", "ingested_at": "2026-04-10T16:09:19.096046"}, "parsed_data": {"is_chunked": true, "item_chunks": {"8.01": "Item 8.01 Other Events.\n\nOn April 6, 2026, the Company announced that its Board of Directors has approved the repurchase of up to an additional $500 million of the Company’s common stock, bringing the Company’s total repurchase authorization to $1.5 billion (together, the “Share Repurchase Program”). Under the Share Repurchase Program, the Company has repurchased 413,130 shares of its outstanding Class A common stock at an average price of $364.57 per share, for an aggregate purchase price of $150.6 million.\n\nThe Share Repurchase Program does not have a fixed expiration date and does not obligate the Company to acquire any specific number of shares. Repurchases may be made from time to time using a variety of methods, including open market purchases, privately negotiated transactions, Rule 10b5-1 trading plans and other means. The timing, manner, price and amount of any repurchases will be determined by the Company in its discretion and will depend on a variety of factors, including legal requirements, price and economic and market conditions. The Company currently expects to use the Share Repurchase Program opportunistically depending on the market price of the common stock and other factors, and there can be no assurance that any shares will be repurchased under the Share Repurchase Program.\n\nForward-Looking Statements\n\nThis Form 8-K contains forward-looking statements that involve risks and uncertainties, including statements regarding the Share Repurchase Program and the factors that will impact the amount and timing of purchases, if any, thereunder. A number of factors could cause outcomes to differ materially from our statements, including the risks and uncertainties included in our filings with the Securities and Exchange Commission, particularly under the caption “Risk Factors” in our most recently filed Annual Report on Form 10-K. Accordingly, you should not place undue reliance on these forward-looking statements. All forward-looking statements are based on information currently available to us, and we do not assume any obligation to update any statement to reflect changes in circumstances or our expectations.\n\n2\n\n---", "9.01": "Item 9.01    Financial Statements and Exhibits.\n\n(d) Exhibits\n\n| | | | | | | | | |\n| --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| | | | | | | | | |\n| Exhibit Number | | | | | | Description of Exhibit | | |\n| 99.1 | | | | | | Press release dated April 6, 2026 | | |\n| 104 | | | | | | Cover Page Interactive Data File - the cover page XBRL tags are embedded within the Inline XBRL document | | |\n\n3\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/CSCO.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/CSCO.jsonl new file mode 100644 index 0000000..25183ba --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/CSCO.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "CSCO", "form_type": "4", "filed_at": "2026-04-07", "accession_no": "0000858877-26-000052", "url": "https://www.sec.gov/Archives/edgar/data/858877/000085887726000052/xslF345X06/wk-form4_1775592372.xml", "ingested_at": "2026-04-10T16:09:03.851425"}, "parsed_data": {"reporting_owner": "Shimer Peter A", "role": "Other", "transactions": [{"date": "2026-04-06", "code": "A", "direction": "OTHER (A)", "shares": 2333.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 2333.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "CSCO", "form_type": "8-K", "filed_at": "2026-04-06", "accession_no": "0000858877-26-000048", "url": "https://www.sec.gov/Archives/edgar/data/858877/000085887726000048/csco-20260331.htm", "ingested_at": "2026-04-10T16:09:04.051957"}, "parsed_data": {"is_chunked": true, "item_chunks": {"5.02": "Item 5.02. | | | Departure of Directors or Certain Officers; Election of Directors; Appointment of Certain Officers; Compensatory Arrangements of Certain Officers. | | |\n\nDeparture of Director\n\nOn March 31, 2026, in light of the increased time and focus required of his new role as Chief Executive Officer of Verizon Communications Inc., Daniel H. Schulman notified Cisco Systems, Inc. (“Cisco”) of his decision to resign from the Board of Directors (\"Board\") of Cisco effective May 21, 2026.\n\nAppointment of Director\n\nOn April 4, 2026, the Board of Cisco appointed Peter A. Shimer as a member of the Board effective April 6, 2026. In connection with his appointment, the Board determined that Mr. Shimer is “independent” under the applicable listing standards of The Nasdaq Stock Market LLC. The Board has also appointed Mr. Shimer to serve as a member of the Audit Committee of the Board.\n\nIn connection with his service as a director, Mr. Shimer will receive Cisco’s standard non-employee director cash and equity compensation. Mr. Shimer will receive a pro rata portion of the $105,000 annual cash retainer, paid quarterly in arrears, for his service through the remaining portion of the year ending at Cisco's 2026 annual meeting of stockholders (the \"2026 Annual Meeting\"). Mr. Shimer will also receive a pro rata portion of the Audit Committee member annual cash retainer fees, paid quarterly in arrears, for service on such committee through the remaining portion of the year ending at the 2026 Annual Meeting. Non-employee directors may instead elect to receive the annual cash retainer, committee cash retainer fees or other cash fees in fully vested shares of Cisco common stock, fully vested deferred stock units that would be settled in shares after the non-employee director leaves the Board, or a deferred cash payment under the Cisco Systems, Inc. Deferred Compensation Plan. Upon his appointment, pursuant to the Board’s equity grant policy for non-employee directors, Mr. Shimer automatically received a fully vested initial non-employee director equity award under Cisco’s 2005 Stock Incentive Plan with a grant date fair value equal to a pro rata portion of $270,000 based on the portion of the year of his board service. Non-employee directors may elect to defer receipt of the equity award such that the award would be settled in shares after the non-employee director leaves the Board. Non-employee directors are also eligible to participate in Cisco’s charitable matching gifts program (for calendar year 2026, the maximum match amount is $25,000 for Cisco's non-employee directors).\n\nIn connection with his appointment, Mr. Shimer has entered into Cisco’s standard form of Indemnity Agreement with Cisco which provides for indemnification of an indemnitee to the fullest extent permitted by law. The foregoing description of the Indemnity Agreement does not purport to be complete and is qualified in its entirety by the full text of the form of Indemnity Agreement, which was filed with the Securities and Exchange Commission on January 25, 2021 as Exhibit 10.1 to Cisco’s Current Report on Form 8-K.\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/GOOGL.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/GOOGL.jsonl new file mode 100644 index 0000000..24ce86b --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/GOOGL.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "GOOGL", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001193125-26-142372", "url": "https://www.sec.gov/Archives/edgar/data/1652044/000119312526142372/xslF345X06/ownership.xml", "ingested_at": "2026-04-10T16:09:00.921701"}, "parsed_data": {"reporting_owner": "O'Toole Amie Thuener", "role": "VP, Chief Accounting Officer", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 617.0, "price": 289.63, "total_value": 178701.71, "post_transaction_shares": 10093.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/INTC.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/INTC.jsonl new file mode 100644 index 0000000..f7ed8ea --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/INTC.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "INTC", "form_type": "8-K", "filed_at": "2026-04-08", "accession_no": "0000050863-26-000072", "url": "https://www.sec.gov/Archives/edgar/data/50863/000005086326000072/intc-20260408.htm", "ingested_at": "2026-04-10T16:09:08.780962"}, "parsed_data": {"is_chunked": true, "item_chunks": {"8.01": "Item 8.01    Other Events\n\nOn April 8, 2026, Intel Corporation (“Intel”) repurchased from Apollo-managed funds and affiliates their 49% equity interest in the parties’ joint venture related to Intel’s Fab 34 in Ireland. The $14.2 billion repurchase price was financed by Intel with cash on hand and a bridge loan of $6.5 billion, which Intel intends to refinance, subject to market conditions. Intel owns 100% of the joint venture following the repurchase.\n\nThe joint venture was created and operated pursuant to agreements entered into by the parties in June 2024. At that time, Apollo-managed funds and affiliates acquired their 49% ownership interest in the joint venture and the parties entered into ancillary agreements with respect to Intel’s construction, commissioning, operation, management, maintenance, utilization and purchase of wafers produced in Fab 34. The repurchase of the joint venture interest by Intel was completed pursuant to an April 1, 2026 agreement between the parties, and Intel expects to terminate the various ancillary agreements that had governed the arrangement and wind up the joint venture.", "9.01": "Item 9.01     Financial Statements and Exhibits.\n\n(d)     Exhibits.\n\nThe following exhibits are provided as part of this report:\n\n| | | | | | |\n| --- | --- | --- | --- | --- | --- |\n| | | | | | |\n| Exhibit Number | | | Description | | |\n| 104 | | | Cover Page Interactive Data File, formatted in Inline XBRL and included as Exhibit 101. | | |\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} +{"metadata": {"ticker": "INTC", "form_type": "8-K", "filed_at": "2026-04-03", "accession_no": "0000050863-26-000069", "url": "https://www.sec.gov/Archives/edgar/data/50863/000005086326000069/intc-20260330.htm", "ingested_at": "2026-04-10T16:09:09.012008"}, "parsed_data": {"is_chunked": true, "item_chunks": {"5.02": "Item 5.02    Departure of Directors or Certain Officers; Election of Directors; Appointment of Certain Officers; Compensatory Arrangements of Certain Officers.\n\nOn March 30,2026, Intel Corporation determined that April Miller Boise, Intel’s Executive Vice President and Chief Legal Officer, will separate from Intel effective as of June 1, 2026. Upon her departure on June 1, 2026, Ms. Miller Boise will be entitled to severance benefits in accordance with the terms and conditions of the Intel Corporation Executive Severance Plan, as previously disclosed, in exchange for a release of claims in favor of Intel.", "9.01": "Item 9.01     Financial Statements and Exhibits.\n\n(d)     Exhibits.\n\nThe following exhibits are provided as part of this report:\n\n| | | | | | |\n| --- | --- | --- | --- | --- | --- |\n| | | | | | |\n| Exhibit Number | | | Description | | |\n| 104 | | | Cover Page Interactive Data File, formatted in Inline XBRL and included as Exhibit 101. | | |\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/INTU.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/INTU.jsonl new file mode 100644 index 0000000..89260f9 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/INTU.jsonl @@ -0,0 +1,6 @@ +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023706", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023706/xslF345X06/wk-form4_1775249487.xml", "ingested_at": "2026-04-10T16:09:05.812311"}, "parsed_data": {"reporting_owner": "Goodarzi Sasan K", "role": "CEO, President and Director", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 653.529, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 14264.957, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 893.612, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 15158.569, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 802.006, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 15960.575, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 863.013, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 16823.588, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 30.832, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 16854.42, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 1277.861, "price": 432.38, "total_value": 552521.5391800001, "post_transaction_shares": 15576.559, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023704", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023704/xslF345X06/wk-form4_1775249417.xml", "ingested_at": "2026-04-10T16:09:05.991327"}, "parsed_data": {"reporting_owner": "McLean Kerry J", "role": "EVP, Gen. Counsel & Corp. Sec.", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 244.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 28657.7666, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 236.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 28893.7666, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 199.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 29092.7666, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 170.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 29262.7666, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 301.627, "price": 432.38, "total_value": 130417.48226, "post_transaction_shares": 28961.1396, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023701", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023701/xslF345X06/wk-form4_1775249278.xml", "ingested_at": "2026-04-10T16:09:06.198532"}, "parsed_data": {"reporting_owner": "Hotz Lauren D", "role": "SVP, Chief Accounting Officer", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 41.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 2055.7352, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 104.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 2159.7352, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 97.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 2256.7352, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 88.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 2344.7352, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 120.548, "price": 432.38, "total_value": 52122.54424, "post_transaction_shares": 2224.1872, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023698", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023698/xslF345X06/wk-form4_1775249186.xml", "ingested_at": "2026-04-10T16:09:06.376791"}, "parsed_data": {"reporting_owner": "Hilliard Caryl Lyn", "role": "EVP, People and Places", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 122.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 23018.008, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 110.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 23128.008, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 87.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 23215.008, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 150.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 23365.008, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 212.093, "price": 432.38, "total_value": 91704.77133999999, "post_transaction_shares": 23152.915, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023696", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023696/xslF345X06/wk-form4_1775249122.xml", "ingested_at": "2026-04-10T16:09:06.564175"}, "parsed_data": {"reporting_owner": "Hanebrink Anton", "role": "EVP, Corp Strategy and Dev", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 348.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 29953.249, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 252.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 30205.249, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 224.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 30429.249, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 418.253, "price": 432.38, "total_value": 180844.23213999998, "post_transaction_shares": 30010.996, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023690", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023690/xslF345X06/wk-form4_1775248743.xml", "ingested_at": "2026-04-10T16:09:06.783184"}, "parsed_data": {"reporting_owner": "Aujla Sandeep", "role": "EVP and CFO", "transactions": [{"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 2665.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 3239.1366, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 346.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 3585.1366, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 349.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 3934.1366, "is_10b5_1_planned": false}, {"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 1725.362, "price": 432.38, "total_value": 746012.02156, "post_transaction_shares": 2208.7746, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/MDLZ.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/MDLZ.jsonl new file mode 100644 index 0000000..0ff4587 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/MDLZ.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "MDLZ", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023648", "url": "https://www.sec.gov/Archives/edgar/data/1103982/000162828026023648/xslF345X06/wk-form4_1775247097.xml", "ingested_at": "2026-04-10T16:09:12.119717"}, "parsed_data": {"reporting_owner": "Lilak Stephanie", "role": "EVP and Chief People Officer", "transactions": [{"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 3218.0, "price": 57.07, "total_value": 183651.26, "post_transaction_shares": 24118.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "MDLZ", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023646", "url": "https://www.sec.gov/Archives/edgar/data/1103982/000162828026023646/xslF345X06/wk-form4_1775247057.xml", "ingested_at": "2026-04-10T16:09:12.334151"}, "parsed_data": {"reporting_owner": "Kuhn Volker", "role": "EVP and President, Europe", "transactions": [{"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 90.0, "price": 57.07, "total_value": 5136.3, "post_transaction_shares": 25820.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/MELI.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/MELI.jsonl new file mode 100644 index 0000000..6ba2edc --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/MELI.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "MELI", "form_type": "8-K", "filed_at": "2026-04-03", "accession_no": "0001999371-26-007656", "url": "https://www.sec.gov/Archives/edgar/data/1099590/000199937126007656/meli_8k-033126.htm", "ingested_at": "2026-04-10T16:09:17.516410"}, "parsed_data": {"is_chunked": true, "item_chunks": {"5.02": "Item 5.02** | **Departure of Directors or Certain Officers; Election of Directors; Appointment of Certain Officers; Compensatory Arrangements of Certain Officers.** |\n\n**Establishment of Performance Goals under the 2026 Bonus Program**\n\nOn March 31, 2026, the Board of Directors (the “Board”) of\nMercadoLibre, Inc. (the “Company”) established the performance goals for the Company’s bonus program for the 2026 fiscal\nyear (the “2026 Bonus Program”). Under the 2026 Bonus Program, the bonus payout for each of Ariel Szarfsztejn (Chief Executive\nOfficer), Marcos Galperin (Executive Chairman), Osvaldo Giménez (Fintech President), Daniel Rabinovich (Technology & Operations\nPresident), and Martin de los Santos (EVP and Chief Financial Officer) (referred to below as “NEOs”) is based on achievement\nof Net revenues and financial income (in constant dollars), Income from operations (in constant dollars), Total payment volume - adjusted\n(the total sum of all transactions paid for using Mercado Pago, including marketplace and non-marketplace transactions, excluding peer-to-peer\ntransactions) (in constant dollars) and the Company’s Competitive Net Promoter Score. The Board has determined a target bonus for\neach NEO and applies an adjustment of up to + 50% or -50% to each bonus based upon the individual performance of each NEO.\n\nThe Board set each NEO’s target bonus under the 2026 Bonus Program\nas four months of base salary (33.33% of each NEO’s annual base salary).\n\n**Adoption of the 2026 Long Term Retention Program**\n\nOn March 31, 2026, the Board approved the adoption of the 2026 Long\nTerm Retention Program (the “2026 LTRP”) and, after taking into account a compensation competitiveness analysis carried out\nby the Company’s independent third-party compensation consultant, established the target award for each NEO under the 2026 LTRP.\nThe 2026 LTRP provides the NEOs, along with other members of senior management, with the opportunity to receive cash payments annually\nfor a period of six years (with the first payment occurring between January 1, 2027 and April 30, 2027, as determined by the Company),\nsubject to continued employment on each payment date (other than in specified circumstances). Each award to an NEO under the 2026 LTRP is deemed to have a Grant Date\n(as defined in the 2026 LTRP) of January 1, 2026. Under the 2026 LTRP, each NEO shall receive:\n\n| | | | |\n| --- | --- | --- | --- |\n| | ● | | 16.66% of half of his or her target 2026 LTRP award annually for a period of six years (with the first payment occurring between January 1, 2027 and April 30, 2027) (the “Annual Fixed Payment”); and |\n\n| | | | |\n| --- | --- | --- | --- |\n| | ● | | on each date the Company pays the Annual Fixed Payment, each NEO will also receive a payment equal to the product of (i) 16.66% of half of the NEO’s target 2026 LTRP award and (ii) the quotient of (a) the Applicable Year Stock Price (as defined below) over (b) the average closing price of the Company’s common stock on NASDAQ during the final 60 trading days of 2025. For purposes of the 2026 LTRP, the “Applicable Year Stock Price” is the average closing price of the Company’s common stock on NASDAQ during the final 60 trading days of the fiscal year preceding the fiscal year in which the applicable payment date occurs, for so long as our common stock is listed on NASDAQ. |\n\nThe target 2026 LTRP awards for our NEOs are set forth below.\n\n| | | | | | | |\n| --- | --- | --- | --- | --- | --- | --- |\n| Name | | Title | | Target 2026 LTRP Award (nominal) | | |\n| Ariel Szarfsztejn | | Chief Executive Officer | | $ | 14,000,000 | |\n| Osvaldo Giménez | | Fintech President | | $ | 10,000,000 | |\n| Daniel Rabinovich | | Technology & Operations President | | $ | 10,000,000 | |\n| Martin de los Santos | | Executive Vice President & Chief Financial Officer | | $ | 4,000,000 | |\n| Marcos Galperin | | Executive Chairman | | $ | 3,500,000 | |\n\n| |\n| --- |\n| |\n\nThe foregoing description of the 2026 LTRP does not purport to be complete\nand is qualified in its entirety by reference to the full text of the 2026 LTRP, which is filed as Exhibit 10.1 to this Current Report\non Form 8-K and is incorporated herein by reference.\n\n| | |\n| --- | --- |\n| **Item 9.01** | **Financial Statements and Exhibits.** |\n\n| | |\n| --- | --- |\n| (d) | *Exhibits.* |\n\nThe following exhibits are filed herewith.\n\n| | | | |\n| --- | --- | --- | --- |\n| **Exhibit** **Number** | | | **Description** |\n| | | | |\n| 10.1 | | | MercadoLibre, Inc. 2026 Long Term Retention Program |\n\n| |\n| --- |\n| |\n\n**EXHIBIT INDEX**\n\n| | | |\n| --- | --- | --- |\n| **Exhibit** **Number** | | **Description** |\n| | | |\n| 10.1 | | MercadoLibre, Inc. 2026 Long Term Retention Program |\n\n| |\n| --- |\n| |\n\n**SIGNATURES**\n\nPursuant to the requirements of the Securities Exchange\nAct of 1934, the registrant has duly caused this report to be signed on its behalf by the undersigned hereunto duly authorized.\n\n| | | | |\n| --- | --- | --- | --- |\n| | MercadoLibre, Inc. | | |\n| | | | |\n| Dated: April 3, 2026 | By: | /s/ Martin de los Santos | |\n| | Name: | Martin de los Santos | |\n| | Title: | Executive Vice President and Chief Financial Officer | |\n| | | | |\n\n \n\n| |\n| --- |\n| |"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/MU.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/MU.jsonl new file mode 100644 index 0000000..d1f5307 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/MU.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "MU", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001632063-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/723125/000163206326000002/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-10T16:09:16.111989"}, "parsed_data": {"reporting_owner": "ARNZEN APRIL S", "role": "EVP and Chief People Officer", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 8630.0, "price": 345.13, "total_value": 2978471.9, "post_transaction_shares": 157107.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 5766.0, "price": 346.22, "total_value": 1996304.5200000003, "post_transaction_shares": 151341.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 604.0, "price": 346.83, "total_value": 209485.31999999998, "post_transaction_shares": 150737.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 25000.0, "price": 348.46, "total_value": 8711500.0, "post_transaction_shares": 125737.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/NFLX.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/NFLX.jsonl new file mode 100644 index 0000000..2a06ef4 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/NFLX.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001543133-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000154313326000002/xslF345X06/wk-form4_1775246849.xml", "ingested_at": "2026-04-10T16:09:02.841105"}, "parsed_data": {"reporting_owner": "Neumann Spencer Adam", "role": "Chief Financial Officer", "transactions": [{"date": "2026-04-02", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 7770.0, "price": 38.105, "total_value": 296075.85, "post_transaction_shares": 81557.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "M", "direction": "VESTING (Options/RSU)", "shares": 20860.0, "price": 36.408, "total_value": 759470.88, "post_transaction_shares": 102417.0, "is_10b5_1_planned": true}, {"date": "2026-04-02", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 28630.0, "price": 98.0, "total_value": 2805740.0, "post_transaction_shares": 73787.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/PANW.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/PANW.jsonl new file mode 100644 index 0000000..ab806ab --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/PANW.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "PANW", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001882285-26-000007", "url": "https://www.sec.gov/Archives/edgar/data/1327567/000188228526000007/xslF345X06/ownership.xml", "ingested_at": "2026-04-10T16:09:11.401119"}, "parsed_data": {"reporting_owner": "Paul Josh D.", "role": "Chief Accounting Officer", "transactions": [{"date": "2026-04-01", "code": "F", "direction": "TAX_WITHHOLDING", "shares": 947.0, "price": 160.32, "total_value": 151823.03999999998, "post_transaction_shares": 84236.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1100.0, "price": 161.4, "total_value": 177540.0, "post_transaction_shares": 83136.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "PANW", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001852540-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/1327567/000185254026000002/xslF345X06/ownership.xml", "ingested_at": "2026-04-10T16:09:11.579845"}, "parsed_data": {"reporting_owner": "Golechha Dipak", "role": "EVP, Chief Financial Officer", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 200.0, "price": 157.81, "total_value": 31562.0, "post_transaction_shares": 155050.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1300.0, "price": 160.039, "total_value": 208050.69999999998, "post_transaction_shares": 153750.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 3500.0, "price": 160.704, "total_value": 562464.0, "post_transaction_shares": 150250.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/REGN.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/REGN.jsonl new file mode 100644 index 0000000..4a395de --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/REGN.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "REGN", "form_type": "8-K", "filed_at": "2026-04-08", "accession_no": "0001104659-26-040661", "url": "https://www.sec.gov/Archives/edgar/data/872589/000110465926040661/tm2611354d1_8k.htm", "ingested_at": "2026-04-10T16:09:13.124043"}, "parsed_data": {"is_chunked": true, "item_chunks": {"2.02": "Item 2.02.** | **Results of Operations and Financial Condition.** |\n\nRegeneron Pharmaceuticals, Inc. (“Regeneron”\nor the “Company”) currently expects that its financial results calculated in accordance with U.S. generally accepted\naccounting principles (“GAAP”) and its non-GAAP financial results for the first quarter 2026 will include an acquired\nin-process research and development (“IPR&D”) charge of approximately $102 million on a pre-tax basis. This charge\nprimarily relates to premium on equity securities purchased, as well as development milestone and up-front payments, in connection with\ncollaboration and licensing agreements. The acquired IPR&D charge is expected to negatively impact each of GAAP and non-GAAP net income\nper diluted share for the first quarter 2026 by approximately $0.81.\n\nAcquired IPR&D charges may include IPR&D\nacquired in connection with asset acquisitions as well as up-front, opt-in, certain development milestone payments, and premiums paid\non equity securities related to collaboration and licensing agreements. Regeneron does not forecast such acquired IPR&D charges due\nto the uncertainty of the future occurrence, magnitude, and timing of these transactions in any given period.\n\nRegeneron’s results for the first quarter\n2026 have not been finalized and are subject to Regeneron’s financial statement closing procedures. There can be no assurance that\nactual results will not differ from the preliminary (unaudited) estimates described herein.\n\nThe information included in this Current Report\non Form 8-K shall not be deemed “filed” for purposes of Section 18 of the Securities Exchange Act of 1934, as amended,\nnor shall such information be deemed incorporated by reference in any filing under the Securities Act of 1933, as amended, except as shall\nbe expressly set forth by specific reference in such a filing.\n\n***Note\nRegarding Forward-Looking Statements***\n\n*This Current Report\non Form 8-K (this “Report”) includes forward-looking statements that involve risks and uncertainties relating\nto future events and the future performance of Regeneron Pharmaceuticals, Inc. (“Regeneron” or the “Company”),\nand actual events or results may differ materially from these forward-looking statements. Words such as “anticipate,” “expect,”\n“intend,” “plan,” “believe,” “seek,” “estimate,” variations of such words,\nand similar expressions are intended to identify such forward-looking statements, although not all forward-looking statements contain\nthese identifying words. These statements concern, and these risks and uncertainties include, among others, Regeneron’s expected\nacquired in-process research and development charge for the quarterly period ended March 31, 2026 and its expected impact on GAAP\nand non-GAAP net income per diluted share for this period as discussed in this Report. A more complete description of these and other\nmaterial risks can be found in Regeneron’s filings with the U.S. Securities and Exchange Commission. Any forward-looking statements\nare made based on management’s current beliefs and judgment, and the reader is cautioned not to rely on any forward-looking statements\nmade by Regeneron. Regeneron does not undertake any obligation to update (publicly or otherwise) any forward-looking statement, including\nwithout limitation any financial projection or guidance, whether as a result of new information, future events, or otherwise.*\n\n***Note Regarding Non-GAAP Financial Measures***\n\n*This Report references non-GAAP net income\nper diluted share, which is a financial measure that is not calculated in accordance with U.S. Generally Accepted Accounting Principles\n(“GAAP”). This non-GAAP financial measure is computed by excluding certain non-cash and/or other items from the related\nGAAP financial measure. The Company also includes a non-GAAP adjustment for the estimated income tax effect of reconciling items. The\nCompany makes such adjustments for items the Company does not view as useful in evaluating its operating performance. Management uses\nthis and other non-GAAP measures for planning, budgeting, forecasting, assessing historical performance, and making financial and operational\ndecisions, and also provides forecasts to investors on this basis. Additionally, such non-GAAP measures provide investors with an enhanced\nunderstanding of the financial performance of the Company's core business operations. However, there are limitations in the use of such\nnon-GAAP financial measures as they exclude certain expenses that are recurring in nature. Furthermore, the Company's non-GAAP financial\nmeasures may not be comparable with non-GAAP information provided by other companies. Any non-GAAP financial measure presented by Regeneron\nshould be considered supplemental to, and not a substitute for, measures of financial performance prepared in accordance with GAAP.*\n\n**SIGNATURES**\n\nPursuant to the requirements of the Securities\nExchange Act of 1934, the registrant has duly caused this report to be signed on its behalf by the undersigned thereunto duly authorized.\n\n| | |\n| --- | --- |\n| | **REGENERON PHARMACEUTICALS, INC.** |\n| | |\n| | /s/ Joseph J. LaRosa |\n| | Joseph J. LaRosa |\n| | Executive Vice President, General Counsel and Secretary |\n\nDate: April 8, 2026"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} +{"metadata": {"ticker": "REGN", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001104659-26-039613", "url": "https://www.sec.gov/Archives/edgar/data/872589/000110465926039613/xslF345X06/tm2611142-1_4seq1.xml", "ingested_at": "2026-04-10T16:09:13.352475"}, "parsed_data": {"reporting_owner": "RYAN ARTHUR F", "role": "Other", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1.0, "price": 771.32, "total_value": 771.32, "post_transaction_shares": 17702.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 3.0, "price": 772.76, "total_value": 2318.2799999999997, "post_transaction_shares": 17699.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 8.0, "price": 773.59, "total_value": 6188.72, "post_transaction_shares": 17691.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 8.0, "price": 774.58, "total_value": 6196.64, "post_transaction_shares": 17683.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 14.0, "price": 775.58, "total_value": 10858.12, "post_transaction_shares": 17669.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 13.0, "price": 776.62, "total_value": 10096.06, "post_transaction_shares": 17656.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 9.0, "price": 777.42, "total_value": 6996.78, "post_transaction_shares": 17647.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 4.0, "price": 778.24, "total_value": 3112.96, "post_transaction_shares": 17643.0, "is_10b5_1_planned": true}, {"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 40.0, "price": 779.71, "total_value": 31188.4, "post_transaction_shares": 17603.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/SBUX.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/SBUX.jsonl new file mode 100644 index 0000000..f6e23fd --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/SBUX.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "SBUX", "form_type": "4", "filed_at": "2026-04-08", "accession_no": "0000829224-26-000066", "url": "https://www.sec.gov/Archives/edgar/data/829224/000082922426000066/xslF345X06/form4.xml", "ingested_at": "2026-04-10T16:09:10.897641"}, "parsed_data": {"reporting_owner": "BREWER BRADY", "role": "ceo, International", "transactions": [{"date": "2026-04-06", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1641.0, "price": 90.0, "total_value": 147690.0, "post_transaction_shares": 84375.502, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/VRTX.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/VRTX.jsonl new file mode 100644 index 0000000..a65b6d6 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/VRTX.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "VRTX", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0000875320-26-000157", "url": "https://www.sec.gov/Archives/edgar/data/875320/000087532026000157/xslF345X06/wk-form4_1775249628.xml", "ingested_at": "2026-04-10T16:09:10.299208"}, "parsed_data": {"reporting_owner": "Liu Joy", "role": "EVP and Chief Legal Officer", "transactions": [{"date": "2026-04-01", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 978.0, "price": 449.17, "total_value": 439288.26, "post_transaction_shares": 21833.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/_SUMMARY.json b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/_SUMMARY.json new file mode 100644 index 0000000..3fef758 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-10/_SUMMARY.json @@ -0,0 +1,86 @@ +{ + "date": "2026-04-10", + "total_filings": 44, + "ticker_breakdown": { + "MELI": { + "4": 0, + "8-K": 1 + }, + "CRWD": { + "4": 0, + "8-K": 1 + }, + "AMZN": { + "4": 6, + "8-K": 1 + }, + "VRTX": { + "4": 1, + "8-K": 0 + }, + "ADI": { + "4": 7, + "8-K": 0 + }, + "PANW": { + "4": 2, + "8-K": 0 + }, + "MU": { + "4": 1, + "8-K": 0 + }, + "AMD": { + "4": 1, + "8-K": 0 + }, + "INTU": { + "4": 6, + "8-K": 0 + }, + "AAPL": { + "4": 3, + "8-K": 0 + }, + "CDNS": { + "4": 1, + "8-K": 0 + }, + "CMCSA": { + "4": 1, + "8-K": 0 + }, + "NFLX": { + "4": 1, + "8-K": 0 + }, + "INTC": { + "4": 0, + "8-K": 2 + }, + "GOOGL": { + "4": 1, + "8-K": 0 + }, + "CSCO": { + "4": 1, + "8-K": 1 + }, + "MDLZ": { + "4": 2, + "8-K": 0 + }, + "REGN": { + "4": 1, + "8-K": 1 + }, + "AVGO": { + "4": 0, + "8-K": 1 + }, + "SBUX": { + "4": 1, + "8-K": 0 + } + } +} \ No newline at end of file diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/ADI.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/ADI.jsonl new file mode 100644 index 0000000..a300f9e --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/ADI.jsonl @@ -0,0 +1,6 @@ +{"metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-09", "accession_no": "0000006281-26-000043", "url": "https://www.sec.gov/Archives/edgar/data/6281/000000628126000043/xslF345X06/wk-form4_1775768645.xml", "ingested_at": "2026-04-12T10:47:22.199483"}, "parsed_data": {"reporting_owner": "Sondel Michael", "role": "CAO (principal acct. officer)", "transactions": [{"date": "2026-04-07", "code": "A", "direction": "OTHER (A)", "shares": 1341.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 15854.578, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-09", "accession_no": "0000006281-26-000042", "url": "https://www.sec.gov/Archives/edgar/data/6281/000000628126000042/xslF345X06/wk-form4_1775768622.xml", "ingested_at": "2026-04-12T10:47:22.379173"}, "parsed_data": {"reporting_owner": "ROCHE VINCENT", "role": "Chair & CEO", "transactions": [{"date": "2026-04-07", "code": "A", "direction": "OTHER (A)", "shares": 19712.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 187537.875, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-09", "accession_no": "0000006281-26-000041", "url": "https://www.sec.gov/Archives/edgar/data/6281/000000628126000041/xslF345X06/wk-form4_1775768603.xml", "ingested_at": "2026-04-12T10:47:22.559658"}, "parsed_data": {"reporting_owner": "Puccio Richard C Jr", "role": "EVP and CFO", "transactions": [{"date": "2026-04-07", "code": "A", "direction": "OTHER (A)", "shares": 6513.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 57968.559, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-09", "accession_no": "0000006281-26-000040", "url": "https://www.sec.gov/Archives/edgar/data/6281/000000628126000040/xslF345X06/wk-form4_1775768583.xml", "ingested_at": "2026-04-12T10:47:22.735092"}, "parsed_data": {"reporting_owner": "Nakamura Katsufumi", "role": "SVP, Chief Customer Officer", "transactions": [{"date": "2026-04-07", "code": "A", "direction": "OTHER (A)", "shares": 4085.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 16230.04, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-09", "accession_no": "0000006281-26-000039", "url": "https://www.sec.gov/Archives/edgar/data/6281/000000628126000039/xslF345X06/wk-form4_1775768561.xml", "ingested_at": "2026-04-12T10:47:22.946237"}, "parsed_data": {"reporting_owner": "Jain Vivek", "role": "EVP, Global Operations", "transactions": [{"date": "2026-04-07", "code": "A", "direction": "OTHER (A)", "shares": 6734.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 48823.474, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-09", "accession_no": "0000006281-26-000038", "url": "https://www.sec.gov/Archives/edgar/data/6281/000000628126000038/xslF345X06/wk-form4_1775768544.xml", "ingested_at": "2026-04-12T10:47:23.137968"}, "parsed_data": {"reporting_owner": "Cotter Martin", "role": "SVP, Vertical Business Units", "transactions": [{"date": "2026-04-07", "code": "A", "direction": "OTHER (A)", "shares": 5807.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 56331.884, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/AMD.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/AMD.jsonl new file mode 100644 index 0000000..16d6108 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/AMD.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "AMD", "form_type": "4", "filed_at": "2026-04-08", "accession_no": "0000002488-26-000064", "url": "https://www.sec.gov/Archives/edgar/data/2488/000000248826000064/xslF345X06/wk-form4_1775679123.xml", "ingested_at": "2026-04-12T10:47:13.348560"}, "parsed_data": {"reporting_owner": "Papermaster Mark D", "role": "Chief Technology Officer & EVP", "transactions": [{"date": "2026-04-06", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 3293.0, "price": 225.0, "total_value": 740925.0, "post_transaction_shares": 1294466.0, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/AMZN.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/AMZN.jsonl new file mode 100644 index 0000000..2f74c2b --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/AMZN.jsonl @@ -0,0 +1,6 @@ +{"metadata": {"ticker": "AMZN", "form_type": "4", "filed_at": "2026-04-09", "accession_no": "0002024813-26-000004", "url": "https://www.sec.gov/Archives/edgar/data/1018724/000202481326000004/xslF345X06/wk-form4_1775768551.xml", "ingested_at": "2026-04-12T10:47:07.694137"}, "parsed_data": {"reporting_owner": "Garman Matthew S", "role": "CEO Amazon Web Services", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "AMZN", "form_type": "4", "filed_at": "2026-04-09", "accession_no": "0001936006-26-000010", "url": "https://www.sec.gov/Archives/edgar/data/1018724/000193600626000010/xslF345X06/wk-form4_1775768277.xml", "ingested_at": "2026-04-12T10:47:07.943528"}, "parsed_data": {"reporting_owner": "Herrington Douglas J", "role": "CEO Worldwide Amazon Stores", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "AMZN", "form_type": "4", "filed_at": "2026-04-09", "accession_no": "0001557979-26-000004", "url": "https://www.sec.gov/Archives/edgar/data/1018724/000155797926000004/xslF345X06/wk-form4_1775767969.xml", "ingested_at": "2026-04-12T10:47:08.130941"}, "parsed_data": {"reporting_owner": "Zapolsky David", "role": "Senior Vice President", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "AMZN", "form_type": "4", "filed_at": "2026-04-09", "accession_no": "0001639902-26-000004", "url": "https://www.sec.gov/Archives/edgar/data/1018724/000163990226000004/xslF345X06/wk-form4_1775767715.xml", "ingested_at": "2026-04-12T10:47:08.309609"}, "parsed_data": {"reporting_owner": "Olsavsky Brian T", "role": "Senior Vice President and CFO", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "AMZN", "form_type": "4", "filed_at": "2026-04-09", "accession_no": "0001397333-26-000004", "url": "https://www.sec.gov/Archives/edgar/data/1018724/000139733326000004/xslF345X06/wk-form4_1775767487.xml", "ingested_at": "2026-04-12T10:47:08.502424"}, "parsed_data": {"reporting_owner": "Reynolds Shelley", "role": "Vice President", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "AMZN", "form_type": "8-K", "filed_at": "2026-04-09", "accession_no": "0001104659-26-041034", "url": "https://www.sec.gov/Archives/edgar/data/1018724/000110465926041034/tm263815d2_8k.htm", "ingested_at": "2026-04-12T10:47:08.706813"}, "parsed_data": {"is_chunked": true, "item_chunks": {"7.01": "ITEM 7.01.  REGULATION FD DISCLOSURE.** | **3** |\n| | |\n| **ITEM 9.01.  FINANCIAL STATEMENTS AND EXHIBITS.** | **3** |\n| | |\n| **SIGNATURES** | **4** |\n| | |\n| EXHIBIT 99.1 | |\n| | |\n| EXHIBIT 99.2 | |\n\n2\n\nTable of Contents\n\n**ITEM 7.01.****REGULATION\nFD DISCLOSURE.**\n\nThe Company’s\nLetter to Shareholders, which accompanies its Annual Report for the Year Ended December 31, 2025, is attached as Exhibit 99.1, and a\nreconciliation of a non-GAAP financial measure included in the Letter to Shareholders to the most directly comparable financial\nmeasure calculated and presented in accordance with GAAP is included as Exhibit 99.2.\n\n**ITEM 9.01.  FINANCIAL STATEMENTS AND EXHIBITS.**\n\n***(d) Exhibits.***\n\n| | |\n| --- | --- |\n| **Exhibit** **Number** | **Description** |\n| | |\n| 99.1 | 2025 Letter to Shareholders. |\n| 99.2 | Reconciliation of Non-GAAP Financial Measure. |\n| 104 | The cover page from this Current Report on Form 8-K, formatted in Inline XBRL (included as Exhibit 101). |\n\n3\n\nTable of Contents\n\n**SIGNATURES**\n\nPursuant to the requirements of the Securities Exchange Act of 1934, the registrant has duly caused this report to be signed on its behalf by the\nundersigned hereunto duly authorized.\n\n| | | |\n| --- | --- | --- |\n| | AMAZON.COM, INC. (REGISTRANT) | |\n| | | |\n| | By: | /s/ Susan K. Jong |\n| | | **Susan K. Jong** |\n| | | **Vice President and Secretary** |\n\nDated: April 9, 2026\n\n4"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/AVGO.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/AVGO.jsonl new file mode 100644 index 0000000..4d322a9 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/AVGO.jsonl @@ -0,0 +1,5 @@ +{"metadata": {"ticker": "AVGO", "form_type": "4", "filed_at": "2026-04-10", "accession_no": "0001730168-26-000030", "url": "https://www.sec.gov/Archives/edgar/data/1730168/000173016826000030/xslF345X06/wk-form4_1775861650.xml", "ingested_at": "2026-04-12T10:47:11.107160"}, "parsed_data": {"reporting_owner": "Velaga S. Ram", "role": "President, ISG", "transactions": [{"date": "2026-04-08", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 12955.0, "price": 352.0223, "total_value": 4560448.8965, "post_transaction_shares": 83192.0, "is_10b5_1_planned": false}, {"date": "2026-04-09", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 17260.0, "price": 352.1184, "total_value": 6077563.584, "post_transaction_shares": 65932.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "AVGO", "form_type": "4", "filed_at": "2026-04-10", "accession_no": "0001730168-26-000028", "url": "https://www.sec.gov/Archives/edgar/data/1730168/000173016826000028/xslF345X06/wk-form4_1775861306.xml", "ingested_at": "2026-04-12T10:47:11.313716"}, "parsed_data": {"reporting_owner": "TAN HOCK E", "role": "President and CEO", "transactions": [{"date": "2026-04-08", "code": "G", "direction": "OTHER (D)", "shares": 22000.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 110836.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "AVGO", "form_type": "4", "filed_at": "2026-04-10", "accession_no": "0001730168-26-000026", "url": "https://www.sec.gov/Archives/edgar/data/1730168/000173016826000026/xslF345X06/wk-form4_1775860888.xml", "ingested_at": "2026-04-12T10:47:11.488943"}, "parsed_data": {"reporting_owner": "PAGE JUSTINE", "role": "Other", "transactions": [{"date": "2026-04-08", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 2018.0, "price": 353.0001, "total_value": 712354.2017999999, "post_transaction_shares": 18164.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "AVGO", "form_type": "4", "filed_at": "2026-04-10", "accession_no": "0001730168-26-000024", "url": "https://www.sec.gov/Archives/edgar/data/1730168/000173016826000024/xslF345X06/wk-form4_1775860497.xml", "ingested_at": "2026-04-12T10:47:11.667556"}, "parsed_data": {"reporting_owner": "Kawwas Charlie B", "role": "President, SSG", "transactions": [{"date": "2026-04-08", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 10000.0, "price": 345.227, "total_value": 3452269.9999999995, "post_transaction_shares": 787184.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "AVGO", "form_type": "8-K", "filed_at": "2026-04-06", "accession_no": "0001193125-26-144028", "url": "https://www.sec.gov/Archives/edgar/data/1730168/000119312526144028/d87999d8k.htm", "ingested_at": "2026-04-12T10:47:11.859849"}, "parsed_data": {"is_chunked": true, "item_chunks": {"8.01": "Item 8.01 | Other Events. |\n\nBroadcom Inc. (“Broadcom”) and Google LLC (“Google”) have entered into a Long Term Agreement for Broadcom to develop and supply custom Tensor Processing Units (“TPUs”) for Google’s future generations of TPUs and a Supply Assurance Agreement for Broadcom to supply networking and other components to be used in Google’s next-generation AI racks through up to 2031.\n\nSeparately, Broadcom, Google and Anthropic PBC (“Anthropic”) have expanded their current strategic collaboration under which Anthropic, beginning in 2027, will access through Broadcom approximately 3.5 gigawatts as part of the multiple gigawatts of next generation TPU-based AI compute capacity committed by Anthropic. The consumption of such expanded AI compute capacity by Anthropic is dependent on Anthropic’s continued commercial success. In connection with this deployment, the parties are in discussions with certain operational and financial partners.\n\nCautionary Note Regarding Forward-Looking Statements\n\nThis Current Report on Form 8-K contains forward-looking statements (including within the meaning of Section 21E of the Securities Exchange Act of 1934, as amended, and Section 27A of the Securities Act of 1933, as amended). These forward-looking statements are based on current expectations and beliefs of Broadcom’s management, current information available to Broadcom’s management, and current market trends and market conditions, and involve risks and uncertainties that may cause actual results to differ materially from those contained in the forward-looking statements. Accordingly, undue reliance should not be placed on such statements. All forward-looking statements are qualified in their entirety by reference to the risk factors discussed under the heading “Risk Factors” in Broadcom’s Annual Report on Form 10-K for the year ended November 2, 2025, Quarterly Report on Form 10-Q for the period ended February 1, 2026 and any subsequent reports that are filed with the Securities and Exchange Commission and include some important risk factors that may affect future results. Broadcom undertakes no intent or obligation to publicly update or revise the forward-looking statements made in this Current Report on Form 8-K, except as required by law.\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/CRWD.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/CRWD.jsonl new file mode 100644 index 0000000..47c0d4a --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/CRWD.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "CRWD", "form_type": "8-K", "filed_at": "2026-04-06", "accession_no": "0001535527-26-000013", "url": "https://www.sec.gov/Archives/edgar/data/1535527/000153552726000013/crwd-20260406.htm", "ingested_at": "2026-04-12T10:47:25.680379"}, "parsed_data": {"is_chunked": true, "item_chunks": {"8.01": "Item 8.01 Other Events.\n\nOn April 6, 2026, the Company announced that its Board of Directors has approved the repurchase of up to an additional $500 million of the Company’s common stock, bringing the Company’s total repurchase authorization to $1.5 billion (together, the “Share Repurchase Program”). Under the Share Repurchase Program, the Company has repurchased 413,130 shares of its outstanding Class A common stock at an average price of $364.57 per share, for an aggregate purchase price of $150.6 million.\n\nThe Share Repurchase Program does not have a fixed expiration date and does not obligate the Company to acquire any specific number of shares. Repurchases may be made from time to time using a variety of methods, including open market purchases, privately negotiated transactions, Rule 10b5-1 trading plans and other means. The timing, manner, price and amount of any repurchases will be determined by the Company in its discretion and will depend on a variety of factors, including legal requirements, price and economic and market conditions. The Company currently expects to use the Share Repurchase Program opportunistically depending on the market price of the common stock and other factors, and there can be no assurance that any shares will be repurchased under the Share Repurchase Program.\n\nForward-Looking Statements\n\nThis Form 8-K contains forward-looking statements that involve risks and uncertainties, including statements regarding the Share Repurchase Program and the factors that will impact the amount and timing of purchases, if any, thereunder. A number of factors could cause outcomes to differ materially from our statements, including the risks and uncertainties included in our filings with the Securities and Exchange Commission, particularly under the caption “Risk Factors” in our most recently filed Annual Report on Form 10-K. Accordingly, you should not place undue reliance on these forward-looking statements. All forward-looking statements are based on information currently available to us, and we do not assume any obligation to update any statement to reflect changes in circumstances or our expectations.\n\n2\n\n---", "9.01": "Item 9.01    Financial Statements and Exhibits.\n\n(d) Exhibits\n\n| | | | | | | | | |\n| --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| | | | | | | | | |\n| Exhibit Number | | | | | | Description of Exhibit | | |\n| 99.1 | | | | | | Press release dated April 6, 2026 | | |\n| 104 | | | | | | Cover Page Interactive Data File - the cover page XBRL tags are embedded within the Inline XBRL document | | |\n\n3\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/CSCO.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/CSCO.jsonl new file mode 100644 index 0000000..9783a5d --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/CSCO.jsonl @@ -0,0 +1,2 @@ +{"metadata": {"ticker": "CSCO", "form_type": "4", "filed_at": "2026-04-07", "accession_no": "0000858877-26-000052", "url": "https://www.sec.gov/Archives/edgar/data/858877/000085887726000052/xslF345X06/wk-form4_1775592372.xml", "ingested_at": "2026-04-12T10:47:13.849625"}, "parsed_data": {"reporting_owner": "Shimer Peter A", "role": "Other", "transactions": [{"date": "2026-04-06", "code": "A", "direction": "OTHER (A)", "shares": 2333.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 2333.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "CSCO", "form_type": "8-K", "filed_at": "2026-04-06", "accession_no": "0000858877-26-000048", "url": "https://www.sec.gov/Archives/edgar/data/858877/000085887726000048/csco-20260331.htm", "ingested_at": "2026-04-12T10:47:14.042073"}, "parsed_data": {"is_chunked": true, "item_chunks": {"5.02": "Item 5.02. | | | Departure of Directors or Certain Officers; Election of Directors; Appointment of Certain Officers; Compensatory Arrangements of Certain Officers. | | |\n\nDeparture of Director\n\nOn March 31, 2026, in light of the increased time and focus required of his new role as Chief Executive Officer of Verizon Communications Inc., Daniel H. Schulman notified Cisco Systems, Inc. (“Cisco”) of his decision to resign from the Board of Directors (\"Board\") of Cisco effective May 21, 2026.\n\nAppointment of Director\n\nOn April 4, 2026, the Board of Cisco appointed Peter A. Shimer as a member of the Board effective April 6, 2026. In connection with his appointment, the Board determined that Mr. Shimer is “independent” under the applicable listing standards of The Nasdaq Stock Market LLC. The Board has also appointed Mr. Shimer to serve as a member of the Audit Committee of the Board.\n\nIn connection with his service as a director, Mr. Shimer will receive Cisco’s standard non-employee director cash and equity compensation. Mr. Shimer will receive a pro rata portion of the $105,000 annual cash retainer, paid quarterly in arrears, for his service through the remaining portion of the year ending at Cisco's 2026 annual meeting of stockholders (the \"2026 Annual Meeting\"). Mr. Shimer will also receive a pro rata portion of the Audit Committee member annual cash retainer fees, paid quarterly in arrears, for service on such committee through the remaining portion of the year ending at the 2026 Annual Meeting. Non-employee directors may instead elect to receive the annual cash retainer, committee cash retainer fees or other cash fees in fully vested shares of Cisco common stock, fully vested deferred stock units that would be settled in shares after the non-employee director leaves the Board, or a deferred cash payment under the Cisco Systems, Inc. Deferred Compensation Plan. Upon his appointment, pursuant to the Board’s equity grant policy for non-employee directors, Mr. Shimer automatically received a fully vested initial non-employee director equity award under Cisco’s 2005 Stock Incentive Plan with a grant date fair value equal to a pro rata portion of $270,000 based on the portion of the year of his board service. Non-employee directors may elect to defer receipt of the equity award such that the award would be settled in shares after the non-employee director leaves the Board. Non-employee directors are also eligible to participate in Cisco’s charitable matching gifts program (for calendar year 2026, the maximum match amount is $25,000 for Cisco's non-employee directors).\n\nIn connection with his appointment, Mr. Shimer has entered into Cisco’s standard form of Indemnity Agreement with Cisco which provides for indemnification of an indemnitee to the fullest extent permitted by law. The foregoing description of the Indemnity Agreement does not purport to be complete and is qualified in its entirety by the full text of the form of Indemnity Agreement, which was filed with the Securities and Exchange Commission on January 25, 2021 as Exhibit 10.1 to Cisco’s Current Report on Form 8-K.\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/GOOGL.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/GOOGL.jsonl new file mode 100644 index 0000000..692927c --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/GOOGL.jsonl @@ -0,0 +1,5 @@ +{"metadata": {"ticker": "GOOGL", "form_type": "4", "filed_at": "2026-04-10", "accession_no": "0001193125-26-151397", "url": "https://www.sec.gov/Archives/edgar/data/1652044/000119312526151397/xslF345X06/ownership.xml", "ingested_at": "2026-04-12T10:47:09.473515"}, "parsed_data": {"reporting_owner": "Porat Ruth", "role": "President and CIO", "transactions": [{"date": "2026-04-08", "code": "A", "direction": "OTHER (A)", "shares": 83899.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 83899.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "GOOGL", "form_type": "4", "filed_at": "2026-04-10", "accession_no": "0001193125-26-151366", "url": "https://www.sec.gov/Archives/edgar/data/1652044/000119312526151366/xslF345X06/ownership.xml", "ingested_at": "2026-04-12T10:47:09.656709"}, "parsed_data": {"reporting_owner": "Schindler Philipp", "role": "SVP, Chief Business Officer", "transactions": [{"date": "2026-04-08", "code": "A", "direction": "OTHER (A)", "shares": 106272.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 106272.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "GOOGL", "form_type": "4", "filed_at": "2026-04-10", "accession_no": "0001193125-26-151343", "url": "https://www.sec.gov/Archives/edgar/data/1652044/000119312526151343/xslF345X06/ownership.xml", "ingested_at": "2026-04-12T10:47:09.853999"}, "parsed_data": {"reporting_owner": "Ashkenazi Anat", "role": "SVP, Chief Financial Officer", "transactions": [{"date": "2026-04-08", "code": "A", "direction": "OTHER (A)", "shares": 87255.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 87255.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "GOOGL", "form_type": "4", "filed_at": "2026-04-10", "accession_no": "0001193125-26-151329", "url": "https://www.sec.gov/Archives/edgar/data/1652044/000119312526151329/xslF345X06/ownership.xml", "ingested_at": "2026-04-12T10:47:10.113043"}, "parsed_data": {"reporting_owner": "WALKER JOHN KENT", "role": "President, Global Affairs, CLO", "transactions": [{"date": "2026-04-08", "code": "A", "direction": "OTHER (A)", "shares": 83899.0, "price": 0.0, "total_value": 0.0, "post_transaction_shares": 83899.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "GOOGL", "form_type": "8-K", "filed_at": "2026-04-10", "accession_no": "0001652044-26-000034", "url": "https://www.sec.gov/Archives/edgar/data/1652044/000165204426000034/goog-20260407.htm", "ingested_at": "2026-04-12T10:47:10.308207"}, "parsed_data": {"is_chunked": true, "item_chunks": {"5.02": "Item 5.02 Departure of Directors or Certain Officers; Election of Directors; Appointment of Certain Officers; Compensatory Arrangements of Certain Officers.\n\nOn April 7, 2026, the Leadership Development, Inclusion and Compensation Committee (“LDICC”) of the Board of Directors of Alphabet Inc. (“Alphabet”) approved equity awards for the following executive officers: Anat Ashkenazi, Senior Vice President, Chief Financial Officer, Alphabet and Google LLC (“Google”); Ruth Porat, President and Chief Investment Officer, Alphabet and Google; Philipp Schindler, Senior Vice President, Chief Business Officer, Google; and Kent Walker, President, Global Affairs, Chief Legal Officer and Secretary, Alphabet and Google.\n\nAlphabet uses a combination of both Alphabet performance stock units (“PSUs”) which vest, if at all, based on long-term company performance, and restricted stock units (“GSUs”), which provide incentive for continued service. This approach benefits Alphabet and is designed to maximize long-term shareholder value. The equity awards, which were granted on April 8, 2026, are as follows:\n\n•Ms. Ashkenazi was granted PSUs with a target value of $10,000,000, and GSUs in the amount of $20,000,000.\n\n•Ms. Porat was granted PSUs with a target value of $9,000,000, and GSUs in the amount of $20,000,000.\n\n•Mr. Schindler was granted PSUs with a target value of $16,000,000, and GSUs in the amount of $26,000,000.\n\n•Mr. Walker was granted PSUs with a target value of $9,000,000, and GSUs in the amount of $20,000,000.\n\nThe GSU awards also include a transitional amount, on top of the annual target value, to maintain target total compensation following the discontinuation of the SVP Bonus program in 2025. 2026 is the second and final year of the SVP bonus transition. The transitional amounts were granted on April 8, 2026 as an addition to the 2026 GSU awards. Each individual’s transitional amount follows: $6,000,000 for Ms. Ashkenazi, $5,000,000 for Ms. Porat and Mr. Walker, and $5,666,667 for Mr. Schindler.\n\nThe target number of PSUs was calculated by dividing the target value of the total PSU grant by the average closing price of Alphabet’s Class C capital stock during the month of March 2026 (the “Average Closing Price”). The PSUs will depend on Alphabet’s total shareholder return (relative to S&P 100 companies) (“relative TSR”), and this performance-based equity may not vest at all. The vest will be based on the relative TSR performance over a 2026-2028 performance period, subject to continued employment. Depending upon Alphabet’s relative TSR performance, the number of PSUs that vest in a tranche will range from 0%-200% of target. Upon vesting, each PSU will entitle the grantee to receive one share of Alphabet’s Class C capital stock.\n\nThe number of GSUs was calculated by dividing the GSU award amount by the Average Closing Price. The total GSU award is composed of the (i) target GSU award, which vests monthly over three years from 2026 through 2028, and (ii) a supplemental (transitional) award, which vests monthly during 2026 - other than:\n\n•a 4-month catch-up vest in April 2026 for both awards, and\n\n•a vesting date shift for all employees (from the 25th to the 1st) in March 2027 resulting in a cumulative 2-month vest.\n\nAll vesting is contingent on the recipient's continued employment on the applicable vesting date(s). Upon vesting, each GSU will entitle the grantee to receive one share of Alphabet’s Class C capital stock.\n\nUpon death, all unvested GSUs will accelerate immediately and all performance-based equity will immediately vest at target (or based on actual performance if the performance period ended prior to death). Upon termination of employment by Alphabet for cause, all unvested equity will be forfeited. Upon termination of employment by Alphabet without cause, the grantee will be eligible to vest in a pro-rata number of all performance-based equity (based on actual performance at the end of the performance period). All Alphabet GSUs and PSUs are subject to the terms and conditions of Alphabet’s Amended and Restated 2021 Stock Plan and the applicable award agreement.\n\nThe foregoing description is only a summary of the terms of the respective awards and is qualified in its entirety by reference to the full text of the applicable award agreements, which will be filed as exhibits to Alphabet’s quarterly report on Form 10-Q.\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/INTC.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/INTC.jsonl new file mode 100644 index 0000000..d2589ff --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/INTC.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "INTC", "form_type": "8-K", "filed_at": "2026-04-08", "accession_no": "0000050863-26-000072", "url": "https://www.sec.gov/Archives/edgar/data/50863/000005086326000072/intc-20260408.htm", "ingested_at": "2026-04-12T10:47:17.228812"}, "parsed_data": {"is_chunked": true, "item_chunks": {"8.01": "Item 8.01    Other Events\n\nOn April 8, 2026, Intel Corporation (“Intel”) repurchased from Apollo-managed funds and affiliates their 49% equity interest in the parties’ joint venture related to Intel’s Fab 34 in Ireland. The $14.2 billion repurchase price was financed by Intel with cash on hand and a bridge loan of $6.5 billion, which Intel intends to refinance, subject to market conditions. Intel owns 100% of the joint venture following the repurchase.\n\nThe joint venture was created and operated pursuant to agreements entered into by the parties in June 2024. At that time, Apollo-managed funds and affiliates acquired their 49% ownership interest in the joint venture and the parties entered into ancillary agreements with respect to Intel’s construction, commissioning, operation, management, maintenance, utilization and purchase of wafers produced in Fab 34. The repurchase of the joint venture interest by Intel was completed pursuant to an April 1, 2026 agreement between the parties, and Intel expects to terminate the various ancillary agreements that had governed the arrangement and wind up the joint venture.", "9.01": "Item 9.01     Financial Statements and Exhibits.\n\n(d)     Exhibits.\n\nThe following exhibits are provided as part of this report:\n\n| | | | | | |\n| --- | --- | --- | --- | --- | --- |\n| | | | | | |\n| Exhibit Number | | | Description | | |\n| 104 | | | Cover Page Interactive Data File, formatted in Inline XBRL and included as Exhibit 101. | | |\n\n---"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/MNST.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/MNST.jsonl new file mode 100644 index 0000000..dfc0211 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/MNST.jsonl @@ -0,0 +1,3 @@ +{"metadata": {"ticker": "MNST", "form_type": "4", "filed_at": "2026-04-10", "accession_no": "0000865752-26-000029", "url": "https://www.sec.gov/Archives/edgar/data/865752/000086575226000029/xslF345X06/form4.xml", "ingested_at": "2026-04-12T10:47:27.126798"}, "parsed_data": {"reporting_owner": "Hall Tiffany M.", "role": "Director", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "MNST", "form_type": "4", "filed_at": "2026-04-10", "accession_no": "0000865752-26-000028", "url": "https://www.sec.gov/Archives/edgar/data/865752/000086575226000028/xslF345X06/form4.xml", "ingested_at": "2026-04-12T10:47:27.385555"}, "parsed_data": {"reporting_owner": "JACKSON JEANNE P", "role": "Director", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} +{"metadata": {"ticker": "MNST", "form_type": "4", "filed_at": "2026-04-10", "accession_no": "0000865752-26-000027", "url": "https://www.sec.gov/Archives/edgar/data/865752/000086575226000027/xslF345X06/form4.xml", "ingested_at": "2026-04-12T10:47:27.603294"}, "parsed_data": {"reporting_owner": "Demel Ana", "role": "Director", "transactions": []}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/PANW.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/PANW.jsonl new file mode 100644 index 0000000..1685310 --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/PANW.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "PANW", "form_type": "4", "filed_at": "2026-04-10", "accession_no": "0001772458-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/1327567/000177245826000002/xslF345X06/ownership.xml", "ingested_at": "2026-04-12T10:47:19.440250"}, "parsed_data": {"reporting_owner": "Key John P.", "role": "Director", "transactions": [{"date": "2026-04-08", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1572.0, "price": 173.32, "total_value": 272459.04, "post_transaction_shares": 20000.0, "is_10b5_1_planned": false}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/REGN.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/REGN.jsonl new file mode 100644 index 0000000..9d25f6d --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/REGN.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "REGN", "form_type": "8-K", "filed_at": "2026-04-08", "accession_no": "0001104659-26-040661", "url": "https://www.sec.gov/Archives/edgar/data/872589/000110465926040661/tm2611354d1_8k.htm", "ingested_at": "2026-04-12T10:47:20.721785"}, "parsed_data": {"is_chunked": true, "item_chunks": {"2.02": "Item 2.02.** | **Results of Operations and Financial Condition.** |\n\nRegeneron Pharmaceuticals, Inc. (“Regeneron”\nor the “Company”) currently expects that its financial results calculated in accordance with U.S. generally accepted\naccounting principles (“GAAP”) and its non-GAAP financial results for the first quarter 2026 will include an acquired\nin-process research and development (“IPR&D”) charge of approximately $102 million on a pre-tax basis. This charge\nprimarily relates to premium on equity securities purchased, as well as development milestone and up-front payments, in connection with\ncollaboration and licensing agreements. The acquired IPR&D charge is expected to negatively impact each of GAAP and non-GAAP net income\nper diluted share for the first quarter 2026 by approximately $0.81.\n\nAcquired IPR&D charges may include IPR&D\nacquired in connection with asset acquisitions as well as up-front, opt-in, certain development milestone payments, and premiums paid\non equity securities related to collaboration and licensing agreements. Regeneron does not forecast such acquired IPR&D charges due\nto the uncertainty of the future occurrence, magnitude, and timing of these transactions in any given period.\n\nRegeneron’s results for the first quarter\n2026 have not been finalized and are subject to Regeneron’s financial statement closing procedures. There can be no assurance that\nactual results will not differ from the preliminary (unaudited) estimates described herein.\n\nThe information included in this Current Report\non Form 8-K shall not be deemed “filed” for purposes of Section 18 of the Securities Exchange Act of 1934, as amended,\nnor shall such information be deemed incorporated by reference in any filing under the Securities Act of 1933, as amended, except as shall\nbe expressly set forth by specific reference in such a filing.\n\n***Note\nRegarding Forward-Looking Statements***\n\n*This Current Report\non Form 8-K (this “Report”) includes forward-looking statements that involve risks and uncertainties relating\nto future events and the future performance of Regeneron Pharmaceuticals, Inc. (“Regeneron” or the “Company”),\nand actual events or results may differ materially from these forward-looking statements. Words such as “anticipate,” “expect,”\n“intend,” “plan,” “believe,” “seek,” “estimate,” variations of such words,\nand similar expressions are intended to identify such forward-looking statements, although not all forward-looking statements contain\nthese identifying words. These statements concern, and these risks and uncertainties include, among others, Regeneron’s expected\nacquired in-process research and development charge for the quarterly period ended March 31, 2026 and its expected impact on GAAP\nand non-GAAP net income per diluted share for this period as discussed in this Report. A more complete description of these and other\nmaterial risks can be found in Regeneron’s filings with the U.S. Securities and Exchange Commission. Any forward-looking statements\nare made based on management’s current beliefs and judgment, and the reader is cautioned not to rely on any forward-looking statements\nmade by Regeneron. Regeneron does not undertake any obligation to update (publicly or otherwise) any forward-looking statement, including\nwithout limitation any financial projection or guidance, whether as a result of new information, future events, or otherwise.*\n\n***Note Regarding Non-GAAP Financial Measures***\n\n*This Report references non-GAAP net income\nper diluted share, which is a financial measure that is not calculated in accordance with U.S. Generally Accepted Accounting Principles\n(“GAAP”). This non-GAAP financial measure is computed by excluding certain non-cash and/or other items from the related\nGAAP financial measure. The Company also includes a non-GAAP adjustment for the estimated income tax effect of reconciling items. The\nCompany makes such adjustments for items the Company does not view as useful in evaluating its operating performance. Management uses\nthis and other non-GAAP measures for planning, budgeting, forecasting, assessing historical performance, and making financial and operational\ndecisions, and also provides forecasts to investors on this basis. Additionally, such non-GAAP measures provide investors with an enhanced\nunderstanding of the financial performance of the Company's core business operations. However, there are limitations in the use of such\nnon-GAAP financial measures as they exclude certain expenses that are recurring in nature. Furthermore, the Company's non-GAAP financial\nmeasures may not be comparable with non-GAAP information provided by other companies. Any non-GAAP financial measure presented by Regeneron\nshould be considered supplemental to, and not a substitute for, measures of financial performance prepared in accordance with GAAP.*\n\n**SIGNATURES**\n\nPursuant to the requirements of the Securities\nExchange Act of 1934, the registrant has duly caused this report to be signed on its behalf by the undersigned thereunto duly authorized.\n\n| | |\n| --- | --- |\n| | **REGENERON PHARMACEUTICALS, INC.** |\n| | |\n| | /s/ Joseph J. LaRosa |\n| | Joseph J. LaRosa |\n| | Executive Vice President, General Counsel and Secretary |\n\nDate: April 8, 2026"}}, "raw_text": "8K_PARSED_INTO_MARKDOWN_CHUNKS"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/SBUX.jsonl b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/SBUX.jsonl new file mode 100644 index 0000000..469eb9f --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/SBUX.jsonl @@ -0,0 +1 @@ +{"metadata": {"ticker": "SBUX", "form_type": "4", "filed_at": "2026-04-08", "accession_no": "0000829224-26-000066", "url": "https://www.sec.gov/Archives/edgar/data/829224/000082922426000066/xslF345X06/form4.xml", "ingested_at": "2026-04-12T10:47:18.846818"}, "parsed_data": {"reporting_owner": "BREWER BRADY", "role": "ceo, International", "transactions": [{"date": "2026-04-06", "code": "S", "direction": "STRONG_SELL (Open Market)", "shares": 1641.0, "price": 90.0, "total_value": 147690.0, "post_transaction_shares": 84375.502, "is_10b5_1_planned": true}]}, "raw_text": "XML_PARSED_SUCCESSFULLY"} diff --git a/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/_SUMMARY.json b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/_SUMMARY.json new file mode 100644 index 0000000..c05279b --- /dev/null +++ b/Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-12/_SUMMARY.json @@ -0,0 +1,54 @@ +{ + "date": "2026-04-12", + "total_filings": 33, + "ticker_breakdown": { + "CRWD": { + "4": 0, + "8-K": 1 + }, + "AMZN": { + "4": 5, + "8-K": 1 + }, + "ADI": { + "4": 6, + "8-K": 0 + }, + "PANW": { + "4": 1, + "8-K": 0 + }, + "AMD": { + "4": 1, + "8-K": 0 + }, + "INTC": { + "4": 0, + "8-K": 1 + }, + "GOOGL": { + "4": 4, + "8-K": 1 + }, + "CSCO": { + "4": 1, + "8-K": 1 + }, + "REGN": { + "4": 0, + "8-K": 1 + }, + "AVGO": { + "4": 4, + "8-K": 1 + }, + "SBUX": { + "4": 1, + "8-K": 0 + }, + "MNST": { + "4": 3, + "8-K": 0 + } + } +} \ No newline at end of file diff --git a/Data/2_Silver_Processed/GPR_index/gpr_monthly_enriched.parquet b/Data/2_Silver_Processed/GPR_index/gpr_monthly_enriched.parquet new file mode 100644 index 0000000..04bcc5b Binary files /dev/null and b/Data/2_Silver_Processed/GPR_index/gpr_monthly_enriched.parquet differ diff --git a/Data/2_Silver_Processed/Macro_History/2026-04-04/macro_snapshot_2026-04-04.parquet b/Data/2_Silver_Processed/Macro_History/2026-04-04/macro_snapshot_2026-04-04.parquet new file mode 100644 index 0000000..2874da2 Binary files /dev/null and b/Data/2_Silver_Processed/Macro_History/2026-04-04/macro_snapshot_2026-04-04.parquet differ diff --git a/Data/2_Silver_Processed/Macro_History/2026-04-06/macro_snapshot_2026-04-06.parquet b/Data/2_Silver_Processed/Macro_History/2026-04-06/macro_snapshot_2026-04-06.parquet new file mode 100644 index 0000000..e4654a9 Binary files /dev/null and b/Data/2_Silver_Processed/Macro_History/2026-04-06/macro_snapshot_2026-04-06.parquet differ diff --git a/Data/2_Silver_Processed/Macro_History/2026-04-08/macro_snapshot_2026-04-08.parquet b/Data/2_Silver_Processed/Macro_History/2026-04-08/macro_snapshot_2026-04-08.parquet new file mode 100644 index 0000000..9baeb95 Binary files /dev/null and b/Data/2_Silver_Processed/Macro_History/2026-04-08/macro_snapshot_2026-04-08.parquet differ diff --git a/Data/2_Silver_Processed/Macro_History/2026-04-09/macro_snapshot_2026-04-09.parquet b/Data/2_Silver_Processed/Macro_History/2026-04-09/macro_snapshot_2026-04-09.parquet new file mode 100644 index 0000000..771c042 Binary files /dev/null and b/Data/2_Silver_Processed/Macro_History/2026-04-09/macro_snapshot_2026-04-09.parquet differ diff --git a/Data/2_Silver_Processed/Macro_History/2026-04-10/macro_snapshot_2026-04-10.parquet b/Data/2_Silver_Processed/Macro_History/2026-04-10/macro_snapshot_2026-04-10.parquet new file mode 100644 index 0000000..75a6e16 Binary files /dev/null and b/Data/2_Silver_Processed/Macro_History/2026-04-10/macro_snapshot_2026-04-10.parquet differ diff --git a/Data/2_Silver_Processed/Macro_History/2026-04-14/macro_snapshot_2026-04-14.parquet b/Data/2_Silver_Processed/Macro_History/2026-04-14/macro_snapshot_2026-04-14.parquet new file mode 100644 index 0000000..0897d1f Binary files /dev/null and b/Data/2_Silver_Processed/Macro_History/2026-04-14/macro_snapshot_2026-04-14.parquet differ diff --git a/Data/2_Silver_Processed/Macro_History/2026-04-16/macro_snapshot_2026-04-16.parquet b/Data/2_Silver_Processed/Macro_History/2026-04-16/macro_snapshot_2026-04-16.parquet new file mode 100644 index 0000000..779c753 Binary files /dev/null and b/Data/2_Silver_Processed/Macro_History/2026-04-16/macro_snapshot_2026-04-16.parquet differ diff --git a/Data/2_Silver_Processed/Macro_History/2026-04-19/macro_snapshot_2026-04-19.parquet b/Data/2_Silver_Processed/Macro_History/2026-04-19/macro_snapshot_2026-04-19.parquet new file mode 100644 index 0000000..39df4b7 Binary files /dev/null and b/Data/2_Silver_Processed/Macro_History/2026-04-19/macro_snapshot_2026-04-19.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-04/GLD_options_2026-04-04.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-04/GLD_options_2026-04-04.parquet new file mode 100644 index 0000000..5722933 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-04/GLD_options_2026-04-04.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-04/IWM_options_2026-04-04.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-04/IWM_options_2026-04-04.parquet new file mode 100644 index 0000000..d1b4928 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-04/IWM_options_2026-04-04.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-04/QQQ_options_2026-04-04.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-04/QQQ_options_2026-04-04.parquet new file mode 100644 index 0000000..04ce9a4 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-04/QQQ_options_2026-04-04.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-04/SLV_options_2026-04-04.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-04/SLV_options_2026-04-04.parquet new file mode 100644 index 0000000..88ee358 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-04/SLV_options_2026-04-04.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-04/SPY_options_2026-04-04.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-04/SPY_options_2026-04-04.parquet new file mode 100644 index 0000000..ad8e4c6 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-04/SPY_options_2026-04-04.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-06/GLD_options_2026-04-06.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-06/GLD_options_2026-04-06.parquet new file mode 100644 index 0000000..3169ab4 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-06/GLD_options_2026-04-06.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-06/IWM_options_2026-04-06.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-06/IWM_options_2026-04-06.parquet new file mode 100644 index 0000000..4703dd0 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-06/IWM_options_2026-04-06.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-06/QQQ_options_2026-04-06.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-06/QQQ_options_2026-04-06.parquet new file mode 100644 index 0000000..7f60563 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-06/QQQ_options_2026-04-06.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-06/SLV_options_2026-04-06.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-06/SLV_options_2026-04-06.parquet new file mode 100644 index 0000000..80c97b7 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-06/SLV_options_2026-04-06.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-06/SPY_options_2026-04-06.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-06/SPY_options_2026-04-06.parquet new file mode 100644 index 0000000..859de09 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-06/SPY_options_2026-04-06.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-08/GLD_options_2026-04-08.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-08/GLD_options_2026-04-08.parquet new file mode 100644 index 0000000..e53aadc Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-08/GLD_options_2026-04-08.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-08/IWM_options_2026-04-08.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-08/IWM_options_2026-04-08.parquet new file mode 100644 index 0000000..948ede0 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-08/IWM_options_2026-04-08.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-08/QQQ_options_2026-04-08.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-08/QQQ_options_2026-04-08.parquet new file mode 100644 index 0000000..572f322 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-08/QQQ_options_2026-04-08.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-08/SLV_options_2026-04-08.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-08/SLV_options_2026-04-08.parquet new file mode 100644 index 0000000..6fc1719 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-08/SLV_options_2026-04-08.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-08/SPY_options_2026-04-08.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-08/SPY_options_2026-04-08.parquet new file mode 100644 index 0000000..9bf926f Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-08/SPY_options_2026-04-08.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-09/GLD_options_2026-04-09.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-09/GLD_options_2026-04-09.parquet new file mode 100644 index 0000000..ff83766 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-09/GLD_options_2026-04-09.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-09/IWM_options_2026-04-09.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-09/IWM_options_2026-04-09.parquet new file mode 100644 index 0000000..0266974 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-09/IWM_options_2026-04-09.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-09/QQQ_options_2026-04-09.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-09/QQQ_options_2026-04-09.parquet new file mode 100644 index 0000000..7ec0eb6 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-09/QQQ_options_2026-04-09.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-09/SLV_options_2026-04-09.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-09/SLV_options_2026-04-09.parquet new file mode 100644 index 0000000..338705c Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-09/SLV_options_2026-04-09.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-09/SPY_options_2026-04-09.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-09/SPY_options_2026-04-09.parquet new file mode 100644 index 0000000..c5ecbe0 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-09/SPY_options_2026-04-09.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-10/GLD_options_2026-04-10.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-10/GLD_options_2026-04-10.parquet new file mode 100644 index 0000000..b4a322d Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-10/GLD_options_2026-04-10.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-10/IWM_options_2026-04-10.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-10/IWM_options_2026-04-10.parquet new file mode 100644 index 0000000..1575f63 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-10/IWM_options_2026-04-10.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-10/QQQ_options_2026-04-10.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-10/QQQ_options_2026-04-10.parquet new file mode 100644 index 0000000..1265b1c Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-10/QQQ_options_2026-04-10.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-10/SLV_options_2026-04-10.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-10/SLV_options_2026-04-10.parquet new file mode 100644 index 0000000..6661d65 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-10/SLV_options_2026-04-10.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-10/SPY_options_2026-04-10.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-10/SPY_options_2026-04-10.parquet new file mode 100644 index 0000000..9cd1952 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-10/SPY_options_2026-04-10.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-12/GLD_options_2026-04-12.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-12/GLD_options_2026-04-12.parquet new file mode 100644 index 0000000..9acbb7c Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-12/GLD_options_2026-04-12.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-12/IWM_options_2026-04-12.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-12/IWM_options_2026-04-12.parquet new file mode 100644 index 0000000..cdfe482 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-12/IWM_options_2026-04-12.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-12/QQQ_options_2026-04-12.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-12/QQQ_options_2026-04-12.parquet new file mode 100644 index 0000000..5ebb7f9 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-12/QQQ_options_2026-04-12.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-12/SLV_options_2026-04-12.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-12/SLV_options_2026-04-12.parquet new file mode 100644 index 0000000..425d7b5 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-12/SLV_options_2026-04-12.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-12/SPY_options_2026-04-12.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-12/SPY_options_2026-04-12.parquet new file mode 100644 index 0000000..ed0d485 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-12/SPY_options_2026-04-12.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-14/GLD_options_2026-04-14.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-14/GLD_options_2026-04-14.parquet new file mode 100644 index 0000000..a197d78 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-14/GLD_options_2026-04-14.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-14/IWM_options_2026-04-14.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-14/IWM_options_2026-04-14.parquet new file mode 100644 index 0000000..511ff57 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-14/IWM_options_2026-04-14.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-14/QQQ_options_2026-04-14.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-14/QQQ_options_2026-04-14.parquet new file mode 100644 index 0000000..a10bd6c Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-14/QQQ_options_2026-04-14.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-14/SLV_options_2026-04-14.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-14/SLV_options_2026-04-14.parquet new file mode 100644 index 0000000..7d43be6 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-14/SLV_options_2026-04-14.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-14/SPY_options_2026-04-14.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-14/SPY_options_2026-04-14.parquet new file mode 100644 index 0000000..f2169ca Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-14/SPY_options_2026-04-14.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-16/GLD_options_2026-04-16.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-16/GLD_options_2026-04-16.parquet new file mode 100644 index 0000000..79edea9 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-16/GLD_options_2026-04-16.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-16/IWM_options_2026-04-16.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-16/IWM_options_2026-04-16.parquet new file mode 100644 index 0000000..2430376 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-16/IWM_options_2026-04-16.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-16/QQQ_options_2026-04-16.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-16/QQQ_options_2026-04-16.parquet new file mode 100644 index 0000000..523abf2 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-16/QQQ_options_2026-04-16.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-16/SLV_options_2026-04-16.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-16/SLV_options_2026-04-16.parquet new file mode 100644 index 0000000..a3e3edc Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-16/SLV_options_2026-04-16.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-16/SPY_options_2026-04-16.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-16/SPY_options_2026-04-16.parquet new file mode 100644 index 0000000..11c6942 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-16/SPY_options_2026-04-16.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-18/GLD_options_2026-04-18.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-18/GLD_options_2026-04-18.parquet new file mode 100644 index 0000000..f02a19d Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-18/GLD_options_2026-04-18.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-18/IWM_options_2026-04-18.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-18/IWM_options_2026-04-18.parquet new file mode 100644 index 0000000..7726e27 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-18/IWM_options_2026-04-18.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-18/QQQ_options_2026-04-18.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-18/QQQ_options_2026-04-18.parquet new file mode 100644 index 0000000..78e2399 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-18/QQQ_options_2026-04-18.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-18/SLV_options_2026-04-18.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-18/SLV_options_2026-04-18.parquet new file mode 100644 index 0000000..92251bf Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-18/SLV_options_2026-04-18.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-18/SPY_options_2026-04-18.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-18/SPY_options_2026-04-18.parquet new file mode 100644 index 0000000..8cea615 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-18/SPY_options_2026-04-18.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-19/GLD_options_2026-04-19.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-19/GLD_options_2026-04-19.parquet new file mode 100644 index 0000000..a67adbe Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-19/GLD_options_2026-04-19.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-19/IWM_options_2026-04-19.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-19/IWM_options_2026-04-19.parquet new file mode 100644 index 0000000..34166a5 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-19/IWM_options_2026-04-19.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-19/QQQ_options_2026-04-19.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-19/QQQ_options_2026-04-19.parquet new file mode 100644 index 0000000..b976034 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-19/QQQ_options_2026-04-19.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-19/SLV_options_2026-04-19.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-19/SLV_options_2026-04-19.parquet new file mode 100644 index 0000000..5c8308f Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-19/SLV_options_2026-04-19.parquet differ diff --git a/Data/2_Silver_Processed/Options_Market_Data/2026-04-19/SPY_options_2026-04-19.parquet b/Data/2_Silver_Processed/Options_Market_Data/2026-04-19/SPY_options_2026-04-19.parquet new file mode 100644 index 0000000..c63fc89 Binary files /dev/null and b/Data/2_Silver_Processed/Options_Market_Data/2026-04-19/SPY_options_2026-04-19.parquet differ diff --git a/Data/3_Gold_Semantic/GPR_index/2026-04-10/gpr_narrative_corpus.md b/Data/3_Gold_Semantic/GPR_index/2026-04-10/gpr_narrative_corpus.md new file mode 100644 index 0000000..4974825 --- /dev/null +++ b/Data/3_Gold_Semantic/GPR_index/2026-04-10/gpr_narrative_corpus.md @@ -0,0 +1,1275 @@ +### Geopolitical Risk (GPR) Index Update: January 2020 + +**Date:** January 2020 +**GPR Score:** 138.42 + +**Summary:** +In January 2020, the global Geopolitical Risk (GPR) Index stood at **138.42**. This represents a **significant escalation**, surging by 86.35% compared to the previous month. Compared to the same period last year, the index shifted by 58.33%. + +**Historical Context:** +This reading sits at the **87.5th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 95.26 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: February 2020 + +**Date:** February 2020 +**GPR Score:** 75.96 + +**Summary:** +In February 2020, the global Geopolitical Risk (GPR) Index stood at **75.96**. This indicates a **cooling off** of geopolitical tensions, dropping by 45.13% month-over-month. Compared to the same period last year, the index shifted by -21.53%. + +**Historical Context:** +This reading sits at the **18.8th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 96.22 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: March 2020 + +**Date:** March 2020 +**GPR Score:** 81.54 + +**Summary:** +In March 2020, the global Geopolitical Risk (GPR) Index stood at **81.54**. The index changed by 7.35% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -0.96%. + +**Historical Context:** +This reading sits at the **27.9th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 98.64 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: April 2020 + +**Date:** April 2020 +**GPR Score:** 69.34 + +**Summary:** +In April 2020, the global Geopolitical Risk (GPR) Index stood at **69.34**. This indicates a **cooling off** of geopolitical tensions, dropping by 14.96% month-over-month. Compared to the same period last year, the index shifted by -12.51%. + +**Historical Context:** +This reading sits at the **12.5th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 75.61 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: May 2020 + +**Date:** May 2020 +**GPR Score:** 68.51 + +**Summary:** +In May 2020, the global Geopolitical Risk (GPR) Index stood at **68.51**. The index changed by -1.20% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -35.66%. + +**Historical Context:** +This reading sits at the **11.5th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 73.13 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: June 2020 + +**Date:** June 2020 +**GPR Score:** 71.23 + +**Summary:** +In June 2020, the global Geopolitical Risk (GPR) Index stood at **71.23**. The index changed by 3.97% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -33.17%. + +**Historical Context:** +This reading sits at the **13.9th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 69.69 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: July 2020 + +**Date:** July 2020 +**GPR Score:** 66.47 + +**Summary:** +In July 2020, the global Geopolitical Risk (GPR) Index stood at **66.47**. The index changed by -6.68% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -28.92%. + +**Historical Context:** +This reading sits at the **10.3th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 68.74 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: August 2020 + +**Date:** August 2020 +**GPR Score:** 65.47 + +**Summary:** +In August 2020, the global Geopolitical Risk (GPR) Index stood at **65.47**. The index changed by -1.52% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -36.69%. + +**Historical Context:** +This reading sits at the **9.5th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 67.72 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: September 2020 + +**Date:** September 2020 +**GPR Score:** 80.38 + +**Summary:** +In September 2020, the global Geopolitical Risk (GPR) Index stood at **80.38**. This represents a **significant escalation**, surging by 22.78% compared to the previous month. Compared to the same period last year, the index shifted by -11.06%. + +**Historical Context:** +This reading sits at the **25.4th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 70.77 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: October 2020 + +**Date:** October 2020 +**GPR Score:** 76.08 + +**Summary:** +In October 2020, the global Geopolitical Risk (GPR) Index stood at **76.08**. The index changed by -5.34% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -22.23%. + +**Historical Context:** +This reading sits at the **19.2th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 73.98 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: November 2020 + +**Date:** November 2020 +**GPR Score:** 70.07 + +**Summary:** +In November 2020, the global Geopolitical Risk (GPR) Index stood at **70.07**. The index changed by -7.91% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -4.12%. + +**Historical Context:** +This reading sits at the **13.1th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 75.51 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: December 2020 + +**Date:** December 2020 +**GPR Score:** 64.07 + +**Summary:** +In December 2020, the global Geopolitical Risk (GPR) Index stood at **64.07**. The index changed by -8.56% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -13.75%. + +**Historical Context:** +This reading sits at the **8.3th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 70.07 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: January 2021 + +**Date:** January 2021 +**GPR Score:** 77.42 + +**Summary:** +In January 2021, the global Geopolitical Risk (GPR) Index stood at **77.42**. This represents a **significant escalation**, surging by 20.84% compared to the previous month. Compared to the same period last year, the index shifted by -44.07%. + +**Historical Context:** +This reading sits at the **21.0th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 70.52 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: February 2021 + +**Date:** February 2021 +**GPR Score:** 73.96 + +**Summary:** +In February 2021, the global Geopolitical Risk (GPR) Index stood at **73.96**. The index changed by -4.47% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -2.63%. + +**Historical Context:** +This reading sits at the **16.0th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 71.81 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: March 2021 + +**Date:** March 2021 +**GPR Score:** 78.62 + +**Summary:** +In March 2021, the global Geopolitical Risk (GPR) Index stood at **78.62**. The index changed by 6.30% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -3.58%. + +**Historical Context:** +This reading sits at the **22.4th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 76.66 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: April 2021 + +**Date:** April 2021 +**GPR Score:** 88.17 + +**Summary:** +In April 2021, the global Geopolitical Risk (GPR) Index stood at **88.17**. This represents a **significant escalation**, surging by 12.14% compared to the previous month. Compared to the same period last year, the index shifted by 27.15%. + +**Historical Context:** +This reading sits at the **41.2th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 80.25 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: May 2021 + +**Date:** May 2021 +**GPR Score:** 93.01 + +**Summary:** +In May 2021, the global Geopolitical Risk (GPR) Index stood at **93.01**. The index changed by 5.49% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by 35.76%. + +**Historical Context:** +This reading sits at the **50.9th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 86.60 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: June 2021 + +**Date:** June 2021 +**GPR Score:** 74.13 + +**Summary:** +In June 2021, the global Geopolitical Risk (GPR) Index stood at **74.13**. This indicates a **cooling off** of geopolitical tensions, dropping by 20.30% month-over-month. Compared to the same period last year, the index shifted by 4.07%. + +**Historical Context:** +This reading sits at the **16.6th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 85.10 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: July 2021 + +**Date:** July 2021 +**GPR Score:** 58.42 + +**Summary:** +In July 2021, the global Geopolitical Risk (GPR) Index stood at **58.42**. This indicates a **cooling off** of geopolitical tensions, dropping by 21.19% month-over-month. Compared to the same period last year, the index shifted by -12.11%. + +**Historical Context:** +This reading sits at the **5.9th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 75.19 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: August 2021 + +**Date:** August 2021 +**GPR Score:** 89.49 + +**Summary:** +In August 2021, the global Geopolitical Risk (GPR) Index stood at **89.49**. This represents a **significant escalation**, surging by 53.18% compared to the previous month. Compared to the same period last year, the index shifted by 36.69%. + +**Historical Context:** +This reading sits at the **44.0th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 74.01 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: September 2021 + +**Date:** September 2021 +**GPR Score:** 80.7 + +**Summary:** +In September 2021, the global Geopolitical Risk (GPR) Index stood at **80.7**. The index changed by -9.82% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by 0.40%. + +**Historical Context:** +This reading sits at the **26.3th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 76.20 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: October 2021 + +**Date:** October 2021 +**GPR Score:** 79.03 + +**Summary:** +In October 2021, the global Geopolitical Risk (GPR) Index stood at **79.03**. The index changed by -2.07% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by 3.87%. + +**Historical Context:** +This reading sits at the **23.0th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 83.07 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: November 2021 + +**Date:** November 2021 +**GPR Score:** 86.57 + +**Summary:** +In November 2021, the global Geopolitical Risk (GPR) Index stood at **86.57**. The index changed by 9.54% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by 23.55%. + +**Historical Context:** +This reading sits at the **38.8th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 82.10 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: December 2021 + +**Date:** December 2021 +**GPR Score:** 105.35 + +**Summary:** +In December 2021, the global Geopolitical Risk (GPR) Index stood at **105.35**. This represents a **significant escalation**, surging by 21.69% compared to the previous month. Compared to the same period last year, the index shifted by 64.43%. + +**Historical Context:** +This reading sits at the **68.1th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 90.31 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: January 2022 + +**Date:** January 2022 +**GPR Score:** 138.67 + +**Summary:** +In January 2022, the global Geopolitical Risk (GPR) Index stood at **138.67**. This represents a **significant escalation**, surging by 31.64% compared to the previous month. Compared to the same period last year, the index shifted by 79.12%. + +**Historical Context:** +This reading sits at the **88.3th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 110.20 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: February 2022 + +**Date:** February 2022 +**GPR Score:** 216.16 + +**Summary:** +In February 2022, the global Geopolitical Risk (GPR) Index stood at **216.16**. This represents a **significant escalation**, surging by 55.87% compared to the previous month. Compared to the same period last year, the index shifted by 192.28%. + +**Historical Context:** +This reading sits at the **97.4th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 153.39 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: March 2022 + +**Date:** March 2022 +**GPR Score:** 318.95 + +**Summary:** +In March 2022, the global Geopolitical Risk (GPR) Index stood at **318.95**. This represents a **significant escalation**, surging by 47.56% compared to the previous month. Compared to the same period last year, the index shifted by 305.70%. + +**Historical Context:** +This reading sits at the **99.0th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 224.60 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: April 2022 + +**Date:** April 2022 +**GPR Score:** 191.14 + +**Summary:** +In April 2022, the global Geopolitical Risk (GPR) Index stood at **191.14**. This indicates a **cooling off** of geopolitical tensions, dropping by 40.07% month-over-month. Compared to the same period last year, the index shifted by 116.80%. + +**Historical Context:** +This reading sits at the **96.8th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 242.09 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: May 2022 + +**Date:** May 2022 +**GPR Score:** 142.26 + +**Summary:** +In May 2022, the global Geopolitical Risk (GPR) Index stood at **142.26**. This indicates a **cooling off** of geopolitical tensions, dropping by 25.57% month-over-month. Compared to the same period last year, the index shifted by 52.95%. + +**Historical Context:** +This reading sits at the **89.3th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 217.45 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: June 2022 + +**Date:** June 2022 +**GPR Score:** 130.71 + +**Summary:** +In June 2022, the global Geopolitical Risk (GPR) Index stood at **130.71**. The index changed by -8.12% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by 76.33%. + +**Historical Context:** +This reading sits at the **84.0th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 154.70 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: July 2022 + +**Date:** July 2022 +**GPR Score:** 117.18 + +**Summary:** +In July 2022, the global Geopolitical Risk (GPR) Index stood at **117.18**. This indicates a **cooling off** of geopolitical tensions, dropping by 10.35% month-over-month. Compared to the same period last year, the index shifted by 100.57%. + +**Historical Context:** +This reading sits at the **77.8th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 130.05 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: August 2022 + +**Date:** August 2022 +**GPR Score:** 132.86 + +**Summary:** +In August 2022, the global Geopolitical Risk (GPR) Index stood at **132.86**. This represents a **significant escalation**, surging by 13.39% compared to the previous month. Compared to the same period last year, the index shifted by 48.47%. + +**Historical Context:** +This reading sits at the **85.0th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 126.92 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: September 2022 + +**Date:** September 2022 +**GPR Score:** 131.99 + +**Summary:** +In September 2022, the global Geopolitical Risk (GPR) Index stood at **131.99**. The index changed by -0.66% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by 63.56%. + +**Historical Context:** +This reading sits at the **84.8th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 127.34 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: October 2022 + +**Date:** October 2022 +**GPR Score:** 143.16 + +**Summary:** +In October 2022, the global Geopolitical Risk (GPR) Index stood at **143.16**. The index changed by 8.47% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by 81.15%. + +**Historical Context:** +This reading sits at the **89.9th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 136.00 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: November 2022 + +**Date:** November 2022 +**GPR Score:** 116.72 + +**Summary:** +In November 2022, the global Geopolitical Risk (GPR) Index stood at **116.72**. This indicates a **cooling off** of geopolitical tensions, dropping by 18.47% month-over-month. Compared to the same period last year, the index shifted by 34.82%. + +**Historical Context:** +This reading sits at the **77.2th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 130.62 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: December 2022 + +**Date:** December 2022 +**GPR Score:** 111.2 + +**Summary:** +In December 2022, the global Geopolitical Risk (GPR) Index stood at **111.2**. The index changed by -4.73% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by 5.55%. + +**Historical Context:** +This reading sits at the **72.9th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 123.69 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: January 2023 + +**Date:** January 2023 +**GPR Score:** 104.27 + +**Summary:** +In January 2023, the global Geopolitical Risk (GPR) Index stood at **104.27**. The index changed by -6.23% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -24.81%. + +**Historical Context:** +This reading sits at the **66.5th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 110.73 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: February 2023 + +**Date:** February 2023 +**GPR Score:** 120.99 + +**Summary:** +In February 2023, the global Geopolitical Risk (GPR) Index stood at **120.99**. This represents a **significant escalation**, surging by 16.04% compared to the previous month. Compared to the same period last year, the index shifted by -44.03%. + +**Historical Context:** +This reading sits at the **80.2th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 112.15 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: March 2023 + +**Date:** March 2023 +**GPR Score:** 105.38 + +**Summary:** +In March 2023, the global Geopolitical Risk (GPR) Index stood at **105.38**. This indicates a **cooling off** of geopolitical tensions, dropping by 12.91% month-over-month. Compared to the same period last year, the index shifted by -66.96%. + +**Historical Context:** +This reading sits at the **68.3th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 110.21 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: April 2023 + +**Date:** April 2023 +**GPR Score:** 106.81 + +**Summary:** +In April 2023, the global Geopolitical Risk (GPR) Index stood at **106.81**. The index changed by 1.36% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -44.12%. + +**Historical Context:** +This reading sits at the **69.7th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 111.06 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: May 2023 + +**Date:** May 2023 +**GPR Score:** 108.47 + +**Summary:** +In May 2023, the global Geopolitical Risk (GPR) Index stood at **108.47**. The index changed by 1.55% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -23.75%. + +**Historical Context:** +This reading sits at the **70.7th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 106.89 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: June 2023 + +**Date:** June 2023 +**GPR Score:** 110.53 + +**Summary:** +In June 2023, the global Geopolitical Risk (GPR) Index stood at **110.53**. The index changed by 1.90% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -15.44%. + +**Historical Context:** +This reading sits at the **72.5th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 108.60 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: July 2023 + +**Date:** July 2023 +**GPR Score:** 107.45 + +**Summary:** +In July 2023, the global Geopolitical Risk (GPR) Index stood at **107.45**. The index changed by -2.79% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -8.30%. + +**Historical Context:** +This reading sits at the **70.1th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 108.82 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: August 2023 + +**Date:** August 2023 +**GPR Score:** 101.14 + +**Summary:** +In August 2023, the global Geopolitical Risk (GPR) Index stood at **101.14**. The index changed by -5.87% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -23.88%. + +**Historical Context:** +This reading sits at the **62.4th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 106.37 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: September 2023 + +**Date:** September 2023 +**GPR Score:** 98.63 + +**Summary:** +In September 2023, the global Geopolitical Risk (GPR) Index stood at **98.63**. The index changed by -2.48% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -25.27%. + +**Historical Context:** +This reading sits at the **58.8th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 102.41 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: October 2023 + +**Date:** October 2023 +**GPR Score:** 197.89 + +**Summary:** +In October 2023, the global Geopolitical Risk (GPR) Index stood at **197.89**. This represents a **significant escalation**, surging by 100.63% compared to the previous month. Compared to the same period last year, the index shifted by 38.23%. + +**Historical Context:** +This reading sits at the **97.0th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 132.55 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: November 2023 + +**Date:** November 2023 +**GPR Score:** 156.7 + +**Summary:** +In November 2023, the global Geopolitical Risk (GPR) Index stood at **156.7**. This indicates a **cooling off** of geopolitical tensions, dropping by 20.82% month-over-month. Compared to the same period last year, the index shifted by 34.25%. + +**Historical Context:** +This reading sits at the **93.3th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 151.07 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: December 2023 + +**Date:** December 2023 +**GPR Score:** 142.28 + +**Summary:** +In December 2023, the global Geopolitical Risk (GPR) Index stood at **142.28**. The index changed by -9.20% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by 27.95%. + +**Historical Context:** +This reading sits at the **89.5th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 165.62 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: January 2024 + +**Date:** January 2024 +**GPR Score:** 160.37 + +**Summary:** +In January 2024, the global Geopolitical Risk (GPR) Index stood at **160.37**. This represents a **significant escalation**, surging by 12.72% compared to the previous month. Compared to the same period last year, the index shifted by 53.81%. + +**Historical Context:** +This reading sits at the **94.1th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 153.12 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: February 2024 + +**Date:** February 2024 +**GPR Score:** 146.6 + +**Summary:** +In February 2024, the global Geopolitical Risk (GPR) Index stood at **146.6**. The index changed by -8.59% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by 21.16%. + +**Historical Context:** +This reading sits at the **90.7th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 149.75 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: March 2024 + +**Date:** March 2024 +**GPR Score:** 133.21 + +**Summary:** +In March 2024, the global Geopolitical Risk (GPR) Index stood at **133.21**. The index changed by -9.13% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by 26.41%. + +**Historical Context:** +This reading sits at the **85.2th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 146.73 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: April 2024 + +**Date:** April 2024 +**GPR Score:** 163.95 + +**Summary:** +In April 2024, the global Geopolitical Risk (GPR) Index stood at **163.95**. This represents a **significant escalation**, surging by 23.07% compared to the previous month. Compared to the same period last year, the index shifted by 53.49%. + +**Historical Context:** +This reading sits at the **94.8th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 147.92 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: May 2024 + +**Date:** May 2024 +**GPR Score:** 130.52 + +**Summary:** +In May 2024, the global Geopolitical Risk (GPR) Index stood at **130.52**. This indicates a **cooling off** of geopolitical tensions, dropping by 20.39% month-over-month. Compared to the same period last year, the index shifted by 20.33%. + +**Historical Context:** +This reading sits at the **83.6th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 142.56 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: June 2024 + +**Date:** June 2024 +**GPR Score:** 113.09 + +**Summary:** +In June 2024, the global Geopolitical Risk (GPR) Index stood at **113.09**. This indicates a **cooling off** of geopolitical tensions, dropping by 13.35% month-over-month. Compared to the same period last year, the index shifted by 2.32%. + +**Historical Context:** +This reading sits at the **74.8th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 135.85 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: July 2024 + +**Date:** July 2024 +**GPR Score:** 92.39 + +**Summary:** +In July 2024, the global Geopolitical Risk (GPR) Index stood at **92.39**. This indicates a **cooling off** of geopolitical tensions, dropping by 18.30% month-over-month. Compared to the same period last year, the index shifted by -14.01%. + +**Historical Context:** +This reading sits at the **49.1th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 112.00 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: August 2024 + +**Date:** August 2024 +**GPR Score:** 140.98 + +**Summary:** +In August 2024, the global Geopolitical Risk (GPR) Index stood at **140.98**. This represents a **significant escalation**, surging by 52.58% compared to the previous month. Compared to the same period last year, the index shifted by 39.38%. + +**Historical Context:** +This reading sits at the **89.1th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 115.49 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: September 2024 + +**Date:** September 2024 +**GPR Score:** 130.36 + +**Summary:** +In September 2024, the global Geopolitical Risk (GPR) Index stood at **130.36**. The index changed by -7.53% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by 32.16%. + +**Historical Context:** +This reading sits at the **83.4th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 121.24 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: October 2024 + +**Date:** October 2024 +**GPR Score:** 130.69 + +**Summary:** +In October 2024, the global Geopolitical Risk (GPR) Index stood at **130.69**. The index changed by 0.25% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -33.96%. + +**Historical Context:** +This reading sits at the **83.8th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 134.01 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: November 2024 + +**Date:** November 2024 +**GPR Score:** 128.9 + +**Summary:** +In November 2024, the global Geopolitical Risk (GPR) Index stood at **128.9**. The index changed by -1.37% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -17.74%. + +**Historical Context:** +This reading sits at the **82.8th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 129.98 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: December 2024 + +**Date:** December 2024 +**GPR Score:** 142.37 + +**Summary:** +In December 2024, the global Geopolitical Risk (GPR) Index stood at **142.37**. This represents a **significant escalation**, surging by 10.45% compared to the previous month. Compared to the same period last year, the index shifted by 0.06%. + +**Historical Context:** +This reading sits at the **89.7th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 133.99 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: January 2025 + +**Date:** January 2025 +**GPR Score:** 113.23 + +**Summary:** +In January 2025, the global Geopolitical Risk (GPR) Index stood at **113.23**. This indicates a **cooling off** of geopolitical tensions, dropping by 20.46% month-over-month. Compared to the same period last year, the index shifted by -29.39%. + +**Historical Context:** +This reading sits at the **75.2th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 128.17 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: February 2025 + +**Date:** February 2025 +**GPR Score:** 136.97 + +**Summary:** +In February 2025, the global Geopolitical Risk (GPR) Index stood at **136.97**. This represents a **significant escalation**, surging by 20.96% compared to the previous month. Compared to the same period last year, the index shifted by -6.57%. + +**Historical Context:** +This reading sits at the **86.7th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 130.86 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: March 2025 + +**Date:** March 2025 +**GPR Score:** 173.91 + +**Summary:** +In March 2025, the global Geopolitical Risk (GPR) Index stood at **173.91**. This represents a **significant escalation**, surging by 26.97% compared to the previous month. Compared to the same period last year, the index shifted by 30.55%. + +**Historical Context:** +This reading sits at the **96.0th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 141.37 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: April 2025 + +**Date:** April 2025 +**GPR Score:** 140.97 + +**Summary:** +In April 2025, the global Geopolitical Risk (GPR) Index stood at **140.97**. This indicates a **cooling off** of geopolitical tensions, dropping by 18.94% month-over-month. Compared to the same period last year, the index shifted by -14.01%. + +**Historical Context:** +This reading sits at the **88.9th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 150.62 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: May 2025 + +**Date:** May 2025 +**GPR Score:** 165.66 + +**Summary:** +In May 2025, the global Geopolitical Risk (GPR) Index stood at **165.66**. This represents a **significant escalation**, surging by 17.51% compared to the previous month. Compared to the same period last year, the index shifted by 26.92%. + +**Historical Context:** +This reading sits at the **95.0th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 160.18 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: June 2025 + +**Date:** June 2025 +**GPR Score:** 222.38 + +**Summary:** +In June 2025, the global Geopolitical Risk (GPR) Index stood at **222.38**. This represents a **significant escalation**, surging by 34.24% compared to the previous month. Compared to the same period last year, the index shifted by 96.63%. + +**Historical Context:** +This reading sits at the **97.6th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 176.34 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: July 2025 + +**Date:** July 2025 +**GPR Score:** 134.02 + +**Summary:** +In July 2025, the global Geopolitical Risk (GPR) Index stood at **134.02**. This indicates a **cooling off** of geopolitical tensions, dropping by 39.73% month-over-month. Compared to the same period last year, the index shifted by 45.05%. + +**Historical Context:** +This reading sits at the **85.7th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 174.02 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: August 2025 + +**Date:** August 2025 +**GPR Score:** 138.56 + +**Summary:** +In August 2025, the global Geopolitical Risk (GPR) Index stood at **138.56**. The index changed by 3.39% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -1.71%. + +**Historical Context:** +This reading sits at the **88.1th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 164.99 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: September 2025 + +**Date:** September 2025 +**GPR Score:** 125.87 + +**Summary:** +In September 2025, the global Geopolitical Risk (GPR) Index stood at **125.87**. The index changed by -9.16% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -3.44%. + +**Historical Context:** +This reading sits at the **82.2th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 132.82 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: October 2025 + +**Date:** October 2025 +**GPR Score:** 154.51 + +**Summary:** +In October 2025, the global Geopolitical Risk (GPR) Index stood at **154.51**. This represents a **significant escalation**, surging by 22.76% compared to the previous month. Compared to the same period last year, the index shifted by 18.23%. + +**Historical Context:** +This reading sits at the **93.1th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 139.65 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: November 2025 + +**Date:** November 2025 +**GPR Score:** 104.34 + +**Summary:** +In November 2025, the global Geopolitical Risk (GPR) Index stood at **104.34**. This indicates a **cooling off** of geopolitical tensions, dropping by 32.47% month-over-month. Compared to the same period last year, the index shifted by -19.06%. + +**Historical Context:** +This reading sits at the **66.7th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 128.24 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: December 2025 + +**Date:** December 2025 +**GPR Score:** 131.39 + +**Summary:** +In December 2025, the global Geopolitical Risk (GPR) Index stood at **131.39**. This represents a **significant escalation**, surging by 25.93% compared to the previous month. Compared to the same period last year, the index shifted by -7.71%. + +**Historical Context:** +This reading sits at the **84.4th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 130.08 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: January 2026 + +**Date:** January 2026 +**GPR Score:** 167.8 + +**Summary:** +In January 2026, the global Geopolitical Risk (GPR) Index stood at **167.8**. This represents a **significant escalation**, surging by 27.71% compared to the previous month. Compared to the same period last year, the index shifted by 48.19%. + +**Historical Context:** +This reading sits at the **95.3th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 134.51 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: February 2026 + +**Date:** February 2026 +**GPR Score:** 121.62 + +**Summary:** +In February 2026, the global Geopolitical Risk (GPR) Index stood at **121.62**. This indicates a **cooling off** of geopolitical tensions, dropping by 27.52% month-over-month. Compared to the same period last year, the index shifted by -11.21%. + +**Historical Context:** +This reading sits at the **80.8th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 140.27 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + +### Geopolitical Risk (GPR) Index Update: March 2026 + +**Date:** March 2026 +**GPR Score:** 297.27 + +**Summary:** +In March 2026, the global Geopolitical Risk (GPR) Index stood at **297.27**. This represents a **significant escalation**, surging by 144.43% compared to the previous month. Compared to the same period last year, the index shifted by 70.93%. + +**Historical Context:** +This reading sits at the **98.6th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 195.56 suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). + + +--- + diff --git a/Data/3_Gold_Semantic/GPR_index/2026-04-10/qdrant_gpr_input.jsonl b/Data/3_Gold_Semantic/GPR_index/2026-04-10/qdrant_gpr_input.jsonl new file mode 100644 index 0000000..d31bcdc --- /dev/null +++ b/Data/3_Gold_Semantic/GPR_index/2026-04-10/qdrant_gpr_input.jsonl @@ -0,0 +1,75 @@ +{"id": "8aa40e1b-b56e-55b4-addd-af6fe6041045", "text": "### Geopolitical Risk (GPR) Index Update: January 2020\n\n**Date:** January 2020\n**GPR Score:** 138.42\n\n**Summary:**\nIn January 2020, the global Geopolitical Risk (GPR) Index stood at **138.42**. This represents a **significant escalation**, surging by 86.35% compared to the previous month. Compared to the same period last year, the index shifted by 58.33%.\n\n**Historical Context:**\nThis reading sits at the **87.5th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 95.26 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2020-01", "publish_date": "2020-01-01", "publish_timestamp": 1577836800, "gpr_score": 138.42, "gpr_percentile": 87.47}} +{"id": "37c10f6b-7a33-54d4-aa57-f54d6e02b047", "text": "### Geopolitical Risk (GPR) Index Update: February 2020\n\n**Date:** February 2020\n**GPR Score:** 75.96\n\n**Summary:**\nIn February 2020, the global Geopolitical Risk (GPR) Index stood at **75.96**. This indicates a **cooling off** of geopolitical tensions, dropping by 45.13% month-over-month. Compared to the same period last year, the index shifted by -21.53%.\n\n**Historical Context:**\nThis reading sits at the **18.8th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 96.22 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2020-02", "publish_date": "2020-02-01", "publish_timestamp": 1580515200, "gpr_score": 75.96, "gpr_percentile": 18.79}} +{"id": "2085a0c1-043d-5f18-82a8-03eea46ea07f", "text": "### Geopolitical Risk (GPR) Index Update: March 2020\n\n**Date:** March 2020\n**GPR Score:** 81.54\n\n**Summary:**\nIn March 2020, the global Geopolitical Risk (GPR) Index stood at **81.54**. The index changed by 7.35% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -0.96%.\n\n**Historical Context:**\nThis reading sits at the **27.9th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 98.64 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2020-03", "publish_date": "2020-03-01", "publish_timestamp": 1583020800, "gpr_score": 81.54, "gpr_percentile": 27.88}} +{"id": "214e06ea-3991-59b3-9fb6-5a198b0f4580", "text": "### Geopolitical Risk (GPR) Index Update: April 2020\n\n**Date:** April 2020\n**GPR Score:** 69.34\n\n**Summary:**\nIn April 2020, the global Geopolitical Risk (GPR) Index stood at **69.34**. This indicates a **cooling off** of geopolitical tensions, dropping by 14.96% month-over-month. Compared to the same period last year, the index shifted by -12.51%.\n\n**Historical Context:**\nThis reading sits at the **12.5th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 75.61 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2020-04", "publish_date": "2020-04-01", "publish_timestamp": 1585699200, "gpr_score": 69.34, "gpr_percentile": 12.53}} +{"id": "b17910ae-9aeb-5c07-995e-409bab57543a", "text": "### Geopolitical Risk (GPR) Index Update: May 2020\n\n**Date:** May 2020\n**GPR Score:** 68.51\n\n**Summary:**\nIn May 2020, the global Geopolitical Risk (GPR) Index stood at **68.51**. The index changed by -1.20% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -35.66%.\n\n**Historical Context:**\nThis reading sits at the **11.5th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 73.13 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2020-05", "publish_date": "2020-05-01", "publish_timestamp": 1588291200, "gpr_score": 68.51, "gpr_percentile": 11.52}} +{"id": "cea60daa-73a0-5d98-bc8f-bf4000509223", "text": "### Geopolitical Risk (GPR) Index Update: June 2020\n\n**Date:** June 2020\n**GPR Score:** 71.23\n\n**Summary:**\nIn June 2020, the global Geopolitical Risk (GPR) Index stood at **71.23**. The index changed by 3.97% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -33.17%.\n\n**Historical Context:**\nThis reading sits at the **13.9th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 69.69 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2020-06", "publish_date": "2020-06-01", "publish_timestamp": 1590969600, "gpr_score": 71.23, "gpr_percentile": 13.94}} +{"id": "58952a55-4410-5967-b6d7-6004ec1228dd", "text": "### Geopolitical Risk (GPR) Index Update: July 2020\n\n**Date:** July 2020\n**GPR Score:** 66.47\n\n**Summary:**\nIn July 2020, the global Geopolitical Risk (GPR) Index stood at **66.47**. The index changed by -6.68% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -28.92%.\n\n**Historical Context:**\nThis reading sits at the **10.3th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 68.74 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2020-07", "publish_date": "2020-07-01", "publish_timestamp": 1593561600, "gpr_score": 66.47, "gpr_percentile": 10.3}} +{"id": "b20ee7e1-4664-5a0a-aa56-d15fe7eecb10", "text": "### Geopolitical Risk (GPR) Index Update: August 2020\n\n**Date:** August 2020\n**GPR Score:** 65.47\n\n**Summary:**\nIn August 2020, the global Geopolitical Risk (GPR) Index stood at **65.47**. The index changed by -1.52% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -36.69%.\n\n**Historical Context:**\nThis reading sits at the **9.5th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 67.72 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2020-08", "publish_date": "2020-08-01", "publish_timestamp": 1596240000, "gpr_score": 65.47, "gpr_percentile": 9.49}} +{"id": "0a9eb60d-9cc7-53b0-8e7e-492efb7397c8", "text": "### Geopolitical Risk (GPR) Index Update: September 2020\n\n**Date:** September 2020\n**GPR Score:** 80.38\n\n**Summary:**\nIn September 2020, the global Geopolitical Risk (GPR) Index stood at **80.38**. This represents a **significant escalation**, surging by 22.78% compared to the previous month. Compared to the same period last year, the index shifted by -11.06%.\n\n**Historical Context:**\nThis reading sits at the **25.4th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 70.77 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2020-09", "publish_date": "2020-09-01", "publish_timestamp": 1598918400, "gpr_score": 80.38, "gpr_percentile": 25.45}} +{"id": "e04d9434-76eb-5f68-b85b-0c3ac4cb9b33", "text": "### Geopolitical Risk (GPR) Index Update: October 2020\n\n**Date:** October 2020\n**GPR Score:** 76.08\n\n**Summary:**\nIn October 2020, the global Geopolitical Risk (GPR) Index stood at **76.08**. The index changed by -5.34% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -22.23%.\n\n**Historical Context:**\nThis reading sits at the **19.2th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 73.98 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2020-10", "publish_date": "2020-10-01", "publish_timestamp": 1601510400, "gpr_score": 76.08, "gpr_percentile": 19.19}} +{"id": "4c8c88a3-0e1f-5496-89e4-390f5a8e1770", "text": "### Geopolitical Risk (GPR) Index Update: November 2020\n\n**Date:** November 2020\n**GPR Score:** 70.07\n\n**Summary:**\nIn November 2020, the global Geopolitical Risk (GPR) Index stood at **70.07**. The index changed by -7.91% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -4.12%.\n\n**Historical Context:**\nThis reading sits at the **13.1th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 75.51 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2020-11", "publish_date": "2020-11-01", "publish_timestamp": 1604188800, "gpr_score": 70.07, "gpr_percentile": 13.13}} +{"id": "b63072dc-5040-515f-b3ea-02483d3a8079", "text": "### Geopolitical Risk (GPR) Index Update: December 2020\n\n**Date:** December 2020\n**GPR Score:** 64.07\n\n**Summary:**\nIn December 2020, the global Geopolitical Risk (GPR) Index stood at **64.07**. The index changed by -8.56% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -13.75%.\n\n**Historical Context:**\nThis reading sits at the **8.3th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 70.07 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2020-12", "publish_date": "2020-12-01", "publish_timestamp": 1606780800, "gpr_score": 64.07, "gpr_percentile": 8.28}} +{"id": "9b29a461-2be8-5ffe-a204-f4b0e198ee11", "text": "### Geopolitical Risk (GPR) Index Update: January 2021\n\n**Date:** January 2021\n**GPR Score:** 77.42\n\n**Summary:**\nIn January 2021, the global Geopolitical Risk (GPR) Index stood at **77.42**. This represents a **significant escalation**, surging by 20.84% compared to the previous month. Compared to the same period last year, the index shifted by -44.07%.\n\n**Historical Context:**\nThis reading sits at the **21.0th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 70.52 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2021-01", "publish_date": "2021-01-01", "publish_timestamp": 1609459200, "gpr_score": 77.42, "gpr_percentile": 21.01}} +{"id": "3d05aa85-4099-5390-84f9-8a43f4af2672", "text": "### Geopolitical Risk (GPR) Index Update: February 2021\n\n**Date:** February 2021\n**GPR Score:** 73.96\n\n**Summary:**\nIn February 2021, the global Geopolitical Risk (GPR) Index stood at **73.96**. The index changed by -4.47% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -2.63%.\n\n**Historical Context:**\nThis reading sits at the **16.0th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 71.81 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2021-02", "publish_date": "2021-02-01", "publish_timestamp": 1612137600, "gpr_score": 73.96, "gpr_percentile": 15.96}} +{"id": "4c689546-4513-5498-87bf-f4be30a4e98d", "text": "### Geopolitical Risk (GPR) Index Update: March 2021\n\n**Date:** March 2021\n**GPR Score:** 78.62\n\n**Summary:**\nIn March 2021, the global Geopolitical Risk (GPR) Index stood at **78.62**. The index changed by 6.30% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -3.58%.\n\n**Historical Context:**\nThis reading sits at the **22.4th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 76.66 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2021-03", "publish_date": "2021-03-01", "publish_timestamp": 1614556800, "gpr_score": 78.62, "gpr_percentile": 22.42}} +{"id": "b4a5f400-63fb-5c1f-9abf-cf10df4534f2", "text": "### Geopolitical Risk (GPR) Index Update: April 2021\n\n**Date:** April 2021\n**GPR Score:** 88.17\n\n**Summary:**\nIn April 2021, the global Geopolitical Risk (GPR) Index stood at **88.17**. This represents a **significant escalation**, surging by 12.14% compared to the previous month. Compared to the same period last year, the index shifted by 27.15%.\n\n**Historical Context:**\nThis reading sits at the **41.2th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 80.25 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2021-04", "publish_date": "2021-04-01", "publish_timestamp": 1617235200, "gpr_score": 88.17, "gpr_percentile": 41.21}} +{"id": "b476abc3-9b9c-5136-b076-e64f51f4833a", "text": "### Geopolitical Risk (GPR) Index Update: May 2021\n\n**Date:** May 2021\n**GPR Score:** 93.01\n\n**Summary:**\nIn May 2021, the global Geopolitical Risk (GPR) Index stood at **93.01**. The index changed by 5.49% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by 35.76%.\n\n**Historical Context:**\nThis reading sits at the **50.9th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 86.60 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2021-05", "publish_date": "2021-05-01", "publish_timestamp": 1619827200, "gpr_score": 93.01, "gpr_percentile": 50.91}} +{"id": "e650993e-f5ab-540e-bc76-b3fd191cc0f2", "text": "### Geopolitical Risk (GPR) Index Update: June 2021\n\n**Date:** June 2021\n**GPR Score:** 74.13\n\n**Summary:**\nIn June 2021, the global Geopolitical Risk (GPR) Index stood at **74.13**. This indicates a **cooling off** of geopolitical tensions, dropping by 20.30% month-over-month. Compared to the same period last year, the index shifted by 4.07%.\n\n**Historical Context:**\nThis reading sits at the **16.6th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 85.10 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2021-06", "publish_date": "2021-06-01", "publish_timestamp": 1622505600, "gpr_score": 74.13, "gpr_percentile": 16.57}} +{"id": "c7080c2d-fcb4-5ce8-be15-89ed1403142d", "text": "### Geopolitical Risk (GPR) Index Update: July 2021\n\n**Date:** July 2021\n**GPR Score:** 58.42\n\n**Summary:**\nIn July 2021, the global Geopolitical Risk (GPR) Index stood at **58.42**. This indicates a **cooling off** of geopolitical tensions, dropping by 21.19% month-over-month. Compared to the same period last year, the index shifted by -12.11%.\n\n**Historical Context:**\nThis reading sits at the **5.9th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 75.19 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2021-07", "publish_date": "2021-07-01", "publish_timestamp": 1625097600, "gpr_score": 58.42, "gpr_percentile": 5.86}} +{"id": "845edb1e-4779-52b6-9a66-44ec8e00501d", "text": "### Geopolitical Risk (GPR) Index Update: August 2021\n\n**Date:** August 2021\n**GPR Score:** 89.49\n\n**Summary:**\nIn August 2021, the global Geopolitical Risk (GPR) Index stood at **89.49**. This represents a **significant escalation**, surging by 53.18% compared to the previous month. Compared to the same period last year, the index shifted by 36.69%.\n\n**Historical Context:**\nThis reading sits at the **44.0th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 74.01 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2021-08", "publish_date": "2021-08-01", "publish_timestamp": 1627776000, "gpr_score": 89.49, "gpr_percentile": 44.04}} +{"id": "8ce4b880-6fce-561c-8128-87c805ba1333", "text": "### Geopolitical Risk (GPR) Index Update: September 2021\n\n**Date:** September 2021\n**GPR Score:** 80.7\n\n**Summary:**\nIn September 2021, the global Geopolitical Risk (GPR) Index stood at **80.7**. The index changed by -9.82% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by 0.40%.\n\n**Historical Context:**\nThis reading sits at the **26.3th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 76.20 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2021-09", "publish_date": "2021-09-01", "publish_timestamp": 1630454400, "gpr_score": 80.7, "gpr_percentile": 26.26}} +{"id": "4e49e4e0-e103-57b6-9f80-ff6fa27543d7", "text": "### Geopolitical Risk (GPR) Index Update: October 2021\n\n**Date:** October 2021\n**GPR Score:** 79.03\n\n**Summary:**\nIn October 2021, the global Geopolitical Risk (GPR) Index stood at **79.03**. The index changed by -2.07% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by 3.87%.\n\n**Historical Context:**\nThis reading sits at the **23.0th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 83.07 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2021-10", "publish_date": "2021-10-01", "publish_timestamp": 1633046400, "gpr_score": 79.03, "gpr_percentile": 23.03}} +{"id": "beabc870-4fcd-5636-944f-79054d24ecf0", "text": "### Geopolitical Risk (GPR) Index Update: November 2021\n\n**Date:** November 2021\n**GPR Score:** 86.57\n\n**Summary:**\nIn November 2021, the global Geopolitical Risk (GPR) Index stood at **86.57**. The index changed by 9.54% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by 23.55%.\n\n**Historical Context:**\nThis reading sits at the **38.8th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 82.10 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2021-11", "publish_date": "2021-11-01", "publish_timestamp": 1635724800, "gpr_score": 86.57, "gpr_percentile": 38.79}} +{"id": "71235083-8d71-5a97-bc58-373053ad79b6", "text": "### Geopolitical Risk (GPR) Index Update: December 2021\n\n**Date:** December 2021\n**GPR Score:** 105.35\n\n**Summary:**\nIn December 2021, the global Geopolitical Risk (GPR) Index stood at **105.35**. This represents a **significant escalation**, surging by 21.69% compared to the previous month. Compared to the same period last year, the index shifted by 64.43%.\n\n**Historical Context:**\nThis reading sits at the **68.1th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 90.31 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2021-12", "publish_date": "2021-12-01", "publish_timestamp": 1638316800, "gpr_score": 105.35, "gpr_percentile": 68.08}} +{"id": "dfacf6a7-3225-57b9-9e18-dd439c6639f6", "text": "### Geopolitical Risk (GPR) Index Update: January 2022\n\n**Date:** January 2022\n**GPR Score:** 138.67\n\n**Summary:**\nIn January 2022, the global Geopolitical Risk (GPR) Index stood at **138.67**. This represents a **significant escalation**, surging by 31.64% compared to the previous month. Compared to the same period last year, the index shifted by 79.12%.\n\n**Historical Context:**\nThis reading sits at the **88.3th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 110.20 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2022-01", "publish_date": "2022-01-01", "publish_timestamp": 1640995200, "gpr_score": 138.67, "gpr_percentile": 88.28}} +{"id": "bc68b51a-48a6-52af-b9f3-271beeaff356", "text": "### Geopolitical Risk (GPR) Index Update: February 2022\n\n**Date:** February 2022\n**GPR Score:** 216.16\n\n**Summary:**\nIn February 2022, the global Geopolitical Risk (GPR) Index stood at **216.16**. This represents a **significant escalation**, surging by 55.87% compared to the previous month. Compared to the same period last year, the index shifted by 192.28%.\n\n**Historical Context:**\nThis reading sits at the **97.4th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 153.39 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2022-02", "publish_date": "2022-02-01", "publish_timestamp": 1643673600, "gpr_score": 216.16, "gpr_percentile": 97.37}} +{"id": "eebd7873-7519-52d5-a5e3-cca45187edf2", "text": "### Geopolitical Risk (GPR) Index Update: March 2022\n\n**Date:** March 2022\n**GPR Score:** 318.95\n\n**Summary:**\nIn March 2022, the global Geopolitical Risk (GPR) Index stood at **318.95**. This represents a **significant escalation**, surging by 47.56% compared to the previous month. Compared to the same period last year, the index shifted by 305.70%.\n\n**Historical Context:**\nThis reading sits at the **99.0th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 224.60 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2022-03", "publish_date": "2022-03-01", "publish_timestamp": 1646092800, "gpr_score": 318.95, "gpr_percentile": 98.99}} +{"id": "0d3ed813-8c4a-52df-b617-a26dc62afe0c", "text": "### Geopolitical Risk (GPR) Index Update: April 2022\n\n**Date:** April 2022\n**GPR Score:** 191.14\n\n**Summary:**\nIn April 2022, the global Geopolitical Risk (GPR) Index stood at **191.14**. This indicates a **cooling off** of geopolitical tensions, dropping by 40.07% month-over-month. Compared to the same period last year, the index shifted by 116.80%.\n\n**Historical Context:**\nThis reading sits at the **96.8th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 242.09 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2022-04", "publish_date": "2022-04-01", "publish_timestamp": 1648771200, "gpr_score": 191.14, "gpr_percentile": 96.77}} +{"id": "1d6b0ec9-7653-5ed9-b26a-2605c4ca90fb", "text": "### Geopolitical Risk (GPR) Index Update: May 2022\n\n**Date:** May 2022\n**GPR Score:** 142.26\n\n**Summary:**\nIn May 2022, the global Geopolitical Risk (GPR) Index stood at **142.26**. This indicates a **cooling off** of geopolitical tensions, dropping by 25.57% month-over-month. Compared to the same period last year, the index shifted by 52.95%.\n\n**Historical Context:**\nThis reading sits at the **89.3th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 217.45 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2022-05", "publish_date": "2022-05-01", "publish_timestamp": 1651363200, "gpr_score": 142.26, "gpr_percentile": 89.29}} +{"id": "fe818e47-b1da-54e0-855b-9eb374e833c2", "text": "### Geopolitical Risk (GPR) Index Update: June 2022\n\n**Date:** June 2022\n**GPR Score:** 130.71\n\n**Summary:**\nIn June 2022, the global Geopolitical Risk (GPR) Index stood at **130.71**. The index changed by -8.12% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by 76.33%.\n\n**Historical Context:**\nThis reading sits at the **84.0th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 154.70 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2022-06", "publish_date": "2022-06-01", "publish_timestamp": 1654041600, "gpr_score": 130.71, "gpr_percentile": 84.04}} +{"id": "8b5d94be-38d3-55f4-99e1-403059e504f0", "text": "### Geopolitical Risk (GPR) Index Update: July 2022\n\n**Date:** July 2022\n**GPR Score:** 117.18\n\n**Summary:**\nIn July 2022, the global Geopolitical Risk (GPR) Index stood at **117.18**. This indicates a **cooling off** of geopolitical tensions, dropping by 10.35% month-over-month. Compared to the same period last year, the index shifted by 100.57%.\n\n**Historical Context:**\nThis reading sits at the **77.8th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 130.05 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2022-07", "publish_date": "2022-07-01", "publish_timestamp": 1656633600, "gpr_score": 117.18, "gpr_percentile": 77.78}} +{"id": "a09f0ea8-3acd-5358-ad45-1771145b7f15", "text": "### Geopolitical Risk (GPR) Index Update: August 2022\n\n**Date:** August 2022\n**GPR Score:** 132.86\n\n**Summary:**\nIn August 2022, the global Geopolitical Risk (GPR) Index stood at **132.86**. This represents a **significant escalation**, surging by 13.39% compared to the previous month. Compared to the same period last year, the index shifted by 48.47%.\n\n**Historical Context:**\nThis reading sits at the **85.0th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 126.92 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2022-08", "publish_date": "2022-08-01", "publish_timestamp": 1659312000, "gpr_score": 132.86, "gpr_percentile": 85.05}} +{"id": "05c42d4b-6e17-5e96-9016-1b0f710cd01d", "text": "### Geopolitical Risk (GPR) Index Update: September 2022\n\n**Date:** September 2022\n**GPR Score:** 131.99\n\n**Summary:**\nIn September 2022, the global Geopolitical Risk (GPR) Index stood at **131.99**. The index changed by -0.66% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by 63.56%.\n\n**Historical Context:**\nThis reading sits at the **84.8th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 127.34 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2022-09", "publish_date": "2022-09-01", "publish_timestamp": 1661990400, "gpr_score": 131.99, "gpr_percentile": 84.85}} +{"id": "549f8f4f-4081-566f-a3e2-f883083c3d5e", "text": "### Geopolitical Risk (GPR) Index Update: October 2022\n\n**Date:** October 2022\n**GPR Score:** 143.16\n\n**Summary:**\nIn October 2022, the global Geopolitical Risk (GPR) Index stood at **143.16**. The index changed by 8.47% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by 81.15%.\n\n**Historical Context:**\nThis reading sits at the **89.9th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 136.00 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2022-10", "publish_date": "2022-10-01", "publish_timestamp": 1664582400, "gpr_score": 143.16, "gpr_percentile": 89.9}} +{"id": "4bc4da11-be70-5626-a9b3-a5763cd9b58c", "text": "### Geopolitical Risk (GPR) Index Update: November 2022\n\n**Date:** November 2022\n**GPR Score:** 116.72\n\n**Summary:**\nIn November 2022, the global Geopolitical Risk (GPR) Index stood at **116.72**. This indicates a **cooling off** of geopolitical tensions, dropping by 18.47% month-over-month. Compared to the same period last year, the index shifted by 34.82%.\n\n**Historical Context:**\nThis reading sits at the **77.2th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 130.62 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2022-11", "publish_date": "2022-11-01", "publish_timestamp": 1667260800, "gpr_score": 116.72, "gpr_percentile": 77.17}} +{"id": "f4ebedde-7e31-5018-be36-c824111fb99d", "text": "### Geopolitical Risk (GPR) Index Update: December 2022\n\n**Date:** December 2022\n**GPR Score:** 111.2\n\n**Summary:**\nIn December 2022, the global Geopolitical Risk (GPR) Index stood at **111.2**. The index changed by -4.73% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by 5.55%.\n\n**Historical Context:**\nThis reading sits at the **72.9th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 123.69 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2022-12", "publish_date": "2022-12-01", "publish_timestamp": 1669852800, "gpr_score": 111.2, "gpr_percentile": 72.93}} +{"id": "d30e17d2-c624-58f9-887d-f0ec8c3da221", "text": "### Geopolitical Risk (GPR) Index Update: January 2023\n\n**Date:** January 2023\n**GPR Score:** 104.27\n\n**Summary:**\nIn January 2023, the global Geopolitical Risk (GPR) Index stood at **104.27**. The index changed by -6.23% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -24.81%.\n\n**Historical Context:**\nThis reading sits at the **66.5th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 110.73 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2023-01", "publish_date": "2023-01-01", "publish_timestamp": 1672531200, "gpr_score": 104.27, "gpr_percentile": 66.46}} +{"id": "b57d4dcf-4f24-5f39-a0b5-a9b254227022", "text": "### Geopolitical Risk (GPR) Index Update: February 2023\n\n**Date:** February 2023\n**GPR Score:** 120.99\n\n**Summary:**\nIn February 2023, the global Geopolitical Risk (GPR) Index stood at **120.99**. This represents a **significant escalation**, surging by 16.04% compared to the previous month. Compared to the same period last year, the index shifted by -44.03%.\n\n**Historical Context:**\nThis reading sits at the **80.2th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 112.15 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2023-02", "publish_date": "2023-02-01", "publish_timestamp": 1675209600, "gpr_score": 120.99, "gpr_percentile": 80.2}} +{"id": "ab709dae-80e5-5621-8dee-51e6fc41edf0", "text": "### Geopolitical Risk (GPR) Index Update: March 2023\n\n**Date:** March 2023\n**GPR Score:** 105.38\n\n**Summary:**\nIn March 2023, the global Geopolitical Risk (GPR) Index stood at **105.38**. This indicates a **cooling off** of geopolitical tensions, dropping by 12.91% month-over-month. Compared to the same period last year, the index shifted by -66.96%.\n\n**Historical Context:**\nThis reading sits at the **68.3th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 110.21 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2023-03", "publish_date": "2023-03-01", "publish_timestamp": 1677628800, "gpr_score": 105.38, "gpr_percentile": 68.28}} +{"id": "9cd09bab-5b4c-5fdc-a7d7-de7d54e4e916", "text": "### Geopolitical Risk (GPR) Index Update: April 2023\n\n**Date:** April 2023\n**GPR Score:** 106.81\n\n**Summary:**\nIn April 2023, the global Geopolitical Risk (GPR) Index stood at **106.81**. The index changed by 1.36% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -44.12%.\n\n**Historical Context:**\nThis reading sits at the **69.7th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 111.06 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2023-04", "publish_date": "2023-04-01", "publish_timestamp": 1680307200, "gpr_score": 106.81, "gpr_percentile": 69.7}} +{"id": "17a9f50e-d759-5f9a-a85f-8ae765234ac8", "text": "### Geopolitical Risk (GPR) Index Update: May 2023\n\n**Date:** May 2023\n**GPR Score:** 108.47\n\n**Summary:**\nIn May 2023, the global Geopolitical Risk (GPR) Index stood at **108.47**. The index changed by 1.55% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -23.75%.\n\n**Historical Context:**\nThis reading sits at the **70.7th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 106.89 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2023-05", "publish_date": "2023-05-01", "publish_timestamp": 1682899200, "gpr_score": 108.47, "gpr_percentile": 70.71}} +{"id": "7fc08cea-d8f5-5366-9552-968bfcfe2610", "text": "### Geopolitical Risk (GPR) Index Update: June 2023\n\n**Date:** June 2023\n**GPR Score:** 110.53\n\n**Summary:**\nIn June 2023, the global Geopolitical Risk (GPR) Index stood at **110.53**. The index changed by 1.90% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -15.44%.\n\n**Historical Context:**\nThis reading sits at the **72.5th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 108.60 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2023-06", "publish_date": "2023-06-01", "publish_timestamp": 1685577600, "gpr_score": 110.53, "gpr_percentile": 72.53}} +{"id": "8983f694-f54e-57bf-8e50-0bb16f9530ed", "text": "### Geopolitical Risk (GPR) Index Update: July 2023\n\n**Date:** July 2023\n**GPR Score:** 107.45\n\n**Summary:**\nIn July 2023, the global Geopolitical Risk (GPR) Index stood at **107.45**. The index changed by -2.79% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -8.30%.\n\n**Historical Context:**\nThis reading sits at the **70.1th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 108.82 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2023-07", "publish_date": "2023-07-01", "publish_timestamp": 1688169600, "gpr_score": 107.45, "gpr_percentile": 70.1}} +{"id": "4726b8d5-1d61-5fdd-9586-13ab46b62b01", "text": "### Geopolitical Risk (GPR) Index Update: August 2023\n\n**Date:** August 2023\n**GPR Score:** 101.14\n\n**Summary:**\nIn August 2023, the global Geopolitical Risk (GPR) Index stood at **101.14**. The index changed by -5.87% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -23.88%.\n\n**Historical Context:**\nThis reading sits at the **62.4th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 106.37 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2023-08", "publish_date": "2023-08-01", "publish_timestamp": 1690848000, "gpr_score": 101.14, "gpr_percentile": 62.42}} +{"id": "64e025c6-d993-5b06-b563-e3111e49b523", "text": "### Geopolitical Risk (GPR) Index Update: September 2023\n\n**Date:** September 2023\n**GPR Score:** 98.63\n\n**Summary:**\nIn September 2023, the global Geopolitical Risk (GPR) Index stood at **98.63**. The index changed by -2.48% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -25.27%.\n\n**Historical Context:**\nThis reading sits at the **58.8th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 102.41 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2023-09", "publish_date": "2023-09-01", "publish_timestamp": 1693526400, "gpr_score": 98.63, "gpr_percentile": 58.79}} +{"id": "e0fa3eba-ccba-5679-a9ad-9dd7630f1ec4", "text": "### Geopolitical Risk (GPR) Index Update: October 2023\n\n**Date:** October 2023\n**GPR Score:** 197.89\n\n**Summary:**\nIn October 2023, the global Geopolitical Risk (GPR) Index stood at **197.89**. This represents a **significant escalation**, surging by 100.63% compared to the previous month. Compared to the same period last year, the index shifted by 38.23%.\n\n**Historical Context:**\nThis reading sits at the **97.0th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 132.55 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2023-10", "publish_date": "2023-10-01", "publish_timestamp": 1696118400, "gpr_score": 197.89, "gpr_percentile": 96.97}} +{"id": "90237d10-c10b-5fd3-a3d5-ad05e59ca97e", "text": "### Geopolitical Risk (GPR) Index Update: November 2023\n\n**Date:** November 2023\n**GPR Score:** 156.7\n\n**Summary:**\nIn November 2023, the global Geopolitical Risk (GPR) Index stood at **156.7**. This indicates a **cooling off** of geopolitical tensions, dropping by 20.82% month-over-month. Compared to the same period last year, the index shifted by 34.25%.\n\n**Historical Context:**\nThis reading sits at the **93.3th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 151.07 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2023-11", "publish_date": "2023-11-01", "publish_timestamp": 1698796800, "gpr_score": 156.7, "gpr_percentile": 93.33}} +{"id": "aad585ab-ab9c-591b-b86b-eeb198a23027", "text": "### Geopolitical Risk (GPR) Index Update: December 2023\n\n**Date:** December 2023\n**GPR Score:** 142.28\n\n**Summary:**\nIn December 2023, the global Geopolitical Risk (GPR) Index stood at **142.28**. The index changed by -9.20% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by 27.95%.\n\n**Historical Context:**\nThis reading sits at the **89.5th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 165.62 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2023-12", "publish_date": "2023-12-01", "publish_timestamp": 1701388800, "gpr_score": 142.28, "gpr_percentile": 89.49}} +{"id": "143aeb97-e095-51e1-bd87-b9be1203da92", "text": "### Geopolitical Risk (GPR) Index Update: January 2024\n\n**Date:** January 2024\n**GPR Score:** 160.37\n\n**Summary:**\nIn January 2024, the global Geopolitical Risk (GPR) Index stood at **160.37**. This represents a **significant escalation**, surging by 12.72% compared to the previous month. Compared to the same period last year, the index shifted by 53.81%.\n\n**Historical Context:**\nThis reading sits at the **94.1th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 153.12 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2024-01", "publish_date": "2024-01-01", "publish_timestamp": 1704067200, "gpr_score": 160.37, "gpr_percentile": 94.14}} +{"id": "baa96302-3b8f-57c7-a42d-94727e838254", "text": "### Geopolitical Risk (GPR) Index Update: February 2024\n\n**Date:** February 2024\n**GPR Score:** 146.6\n\n**Summary:**\nIn February 2024, the global Geopolitical Risk (GPR) Index stood at **146.6**. The index changed by -8.59% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by 21.16%.\n\n**Historical Context:**\nThis reading sits at the **90.7th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 149.75 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2024-02", "publish_date": "2024-02-01", "publish_timestamp": 1706745600, "gpr_score": 146.6, "gpr_percentile": 90.71}} +{"id": "6fe9e729-9f51-5fcc-b7bd-dbd74408c2a9", "text": "### Geopolitical Risk (GPR) Index Update: March 2024\n\n**Date:** March 2024\n**GPR Score:** 133.21\n\n**Summary:**\nIn March 2024, the global Geopolitical Risk (GPR) Index stood at **133.21**. The index changed by -9.13% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by 26.41%.\n\n**Historical Context:**\nThis reading sits at the **85.2th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 146.73 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2024-03", "publish_date": "2024-03-01", "publish_timestamp": 1709251200, "gpr_score": 133.21, "gpr_percentile": 85.25}} +{"id": "a2f0fd0c-6316-53e9-b68d-0e30fdc318f4", "text": "### Geopolitical Risk (GPR) Index Update: April 2024\n\n**Date:** April 2024\n**GPR Score:** 163.95\n\n**Summary:**\nIn April 2024, the global Geopolitical Risk (GPR) Index stood at **163.95**. This represents a **significant escalation**, surging by 23.07% compared to the previous month. Compared to the same period last year, the index shifted by 53.49%.\n\n**Historical Context:**\nThis reading sits at the **94.8th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 147.92 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2024-04", "publish_date": "2024-04-01", "publish_timestamp": 1711929600, "gpr_score": 163.95, "gpr_percentile": 94.75}} +{"id": "7d7c7172-50e6-5570-93ac-aa132a32dfea", "text": "### Geopolitical Risk (GPR) Index Update: May 2024\n\n**Date:** May 2024\n**GPR Score:** 130.52\n\n**Summary:**\nIn May 2024, the global Geopolitical Risk (GPR) Index stood at **130.52**. This indicates a **cooling off** of geopolitical tensions, dropping by 20.39% month-over-month. Compared to the same period last year, the index shifted by 20.33%.\n\n**Historical Context:**\nThis reading sits at the **83.6th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 142.56 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2024-05", "publish_date": "2024-05-01", "publish_timestamp": 1714521600, "gpr_score": 130.52, "gpr_percentile": 83.64}} +{"id": "e1ef82ab-1a8e-5b62-9a16-0c3d5e3d471e", "text": "### Geopolitical Risk (GPR) Index Update: June 2024\n\n**Date:** June 2024\n**GPR Score:** 113.09\n\n**Summary:**\nIn June 2024, the global Geopolitical Risk (GPR) Index stood at **113.09**. This indicates a **cooling off** of geopolitical tensions, dropping by 13.35% month-over-month. Compared to the same period last year, the index shifted by 2.32%.\n\n**Historical Context:**\nThis reading sits at the **74.8th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 135.85 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2024-06", "publish_date": "2024-06-01", "publish_timestamp": 1717200000, "gpr_score": 113.09, "gpr_percentile": 74.75}} +{"id": "9d49f9b2-d5bf-5f81-95e6-0e73ecd5eb38", "text": "### Geopolitical Risk (GPR) Index Update: July 2024\n\n**Date:** July 2024\n**GPR Score:** 92.39\n\n**Summary:**\nIn July 2024, the global Geopolitical Risk (GPR) Index stood at **92.39**. This indicates a **cooling off** of geopolitical tensions, dropping by 18.30% month-over-month. Compared to the same period last year, the index shifted by -14.01%.\n\n**Historical Context:**\nThis reading sits at the **49.1th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 112.00 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2024-07", "publish_date": "2024-07-01", "publish_timestamp": 1719792000, "gpr_score": 92.39, "gpr_percentile": 49.09}} +{"id": "e9d870f0-c970-5870-ab3b-852ac959072a", "text": "### Geopolitical Risk (GPR) Index Update: August 2024\n\n**Date:** August 2024\n**GPR Score:** 140.98\n\n**Summary:**\nIn August 2024, the global Geopolitical Risk (GPR) Index stood at **140.98**. This represents a **significant escalation**, surging by 52.58% compared to the previous month. Compared to the same period last year, the index shifted by 39.38%.\n\n**Historical Context:**\nThis reading sits at the **89.1th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 115.49 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2024-08", "publish_date": "2024-08-01", "publish_timestamp": 1722470400, "gpr_score": 140.98, "gpr_percentile": 89.09}} +{"id": "185cab6e-e1be-5c37-8460-050e49822442", "text": "### Geopolitical Risk (GPR) Index Update: September 2024\n\n**Date:** September 2024\n**GPR Score:** 130.36\n\n**Summary:**\nIn September 2024, the global Geopolitical Risk (GPR) Index stood at **130.36**. The index changed by -7.53% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by 32.16%.\n\n**Historical Context:**\nThis reading sits at the **83.4th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 121.24 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2024-09", "publish_date": "2024-09-01", "publish_timestamp": 1725148800, "gpr_score": 130.36, "gpr_percentile": 83.43}} +{"id": "d4490492-0303-585a-bc92-921459a3aef4", "text": "### Geopolitical Risk (GPR) Index Update: October 2024\n\n**Date:** October 2024\n**GPR Score:** 130.69\n\n**Summary:**\nIn October 2024, the global Geopolitical Risk (GPR) Index stood at **130.69**. The index changed by 0.25% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -33.96%.\n\n**Historical Context:**\nThis reading sits at the **83.8th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 134.01 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2024-10", "publish_date": "2024-10-01", "publish_timestamp": 1727740800, "gpr_score": 130.69, "gpr_percentile": 83.84}} +{"id": "f0890fb0-45c2-5c8a-b3c7-16af61738eb5", "text": "### Geopolitical Risk (GPR) Index Update: November 2024\n\n**Date:** November 2024\n**GPR Score:** 128.9\n\n**Summary:**\nIn November 2024, the global Geopolitical Risk (GPR) Index stood at **128.9**. The index changed by -1.37% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -17.74%.\n\n**Historical Context:**\nThis reading sits at the **82.8th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 129.98 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2024-11", "publish_date": "2024-11-01", "publish_timestamp": 1730419200, "gpr_score": 128.9, "gpr_percentile": 82.83}} +{"id": "ab17edc1-e7d6-5684-8080-1817a9597872", "text": "### Geopolitical Risk (GPR) Index Update: December 2024\n\n**Date:** December 2024\n**GPR Score:** 142.37\n\n**Summary:**\nIn December 2024, the global Geopolitical Risk (GPR) Index stood at **142.37**. This represents a **significant escalation**, surging by 10.45% compared to the previous month. Compared to the same period last year, the index shifted by 0.06%.\n\n**Historical Context:**\nThis reading sits at the **89.7th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 133.99 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2024-12", "publish_date": "2024-12-01", "publish_timestamp": 1733011200, "gpr_score": 142.37, "gpr_percentile": 89.7}} +{"id": "8ce5e6b4-3fc3-5770-ab05-a5a12971b8d9", "text": "### Geopolitical Risk (GPR) Index Update: January 2025\n\n**Date:** January 2025\n**GPR Score:** 113.23\n\n**Summary:**\nIn January 2025, the global Geopolitical Risk (GPR) Index stood at **113.23**. This indicates a **cooling off** of geopolitical tensions, dropping by 20.46% month-over-month. Compared to the same period last year, the index shifted by -29.39%.\n\n**Historical Context:**\nThis reading sits at the **75.2th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 128.17 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2025-01", "publish_date": "2025-01-01", "publish_timestamp": 1735689600, "gpr_score": 113.23, "gpr_percentile": 75.15}} +{"id": "f2ff6cd0-6b3c-5327-aec3-51d44abc12ca", "text": "### Geopolitical Risk (GPR) Index Update: February 2025\n\n**Date:** February 2025\n**GPR Score:** 136.97\n\n**Summary:**\nIn February 2025, the global Geopolitical Risk (GPR) Index stood at **136.97**. This represents a **significant escalation**, surging by 20.96% compared to the previous month. Compared to the same period last year, the index shifted by -6.57%.\n\n**Historical Context:**\nThis reading sits at the **86.7th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 130.86 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2025-02", "publish_date": "2025-02-01", "publish_timestamp": 1738368000, "gpr_score": 136.97, "gpr_percentile": 86.67}} +{"id": "43b2d8bd-21dd-54c5-b7eb-b2b8defbc0be", "text": "### Geopolitical Risk (GPR) Index Update: March 2025\n\n**Date:** March 2025\n**GPR Score:** 173.91\n\n**Summary:**\nIn March 2025, the global Geopolitical Risk (GPR) Index stood at **173.91**. This represents a **significant escalation**, surging by 26.97% compared to the previous month. Compared to the same period last year, the index shifted by 30.55%.\n\n**Historical Context:**\nThis reading sits at the **96.0th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 141.37 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2025-03", "publish_date": "2025-03-01", "publish_timestamp": 1740787200, "gpr_score": 173.91, "gpr_percentile": 95.96}} +{"id": "3d617a4e-2541-5841-9048-14a94f2b691c", "text": "### Geopolitical Risk (GPR) Index Update: April 2025\n\n**Date:** April 2025\n**GPR Score:** 140.97\n\n**Summary:**\nIn April 2025, the global Geopolitical Risk (GPR) Index stood at **140.97**. This indicates a **cooling off** of geopolitical tensions, dropping by 18.94% month-over-month. Compared to the same period last year, the index shifted by -14.01%.\n\n**Historical Context:**\nThis reading sits at the **88.9th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 150.62 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2025-04", "publish_date": "2025-04-01", "publish_timestamp": 1743465600, "gpr_score": 140.97, "gpr_percentile": 88.89}} +{"id": "234c7c3d-81e2-5b85-ac1c-58d8961a1e6f", "text": "### Geopolitical Risk (GPR) Index Update: May 2025\n\n**Date:** May 2025\n**GPR Score:** 165.66\n\n**Summary:**\nIn May 2025, the global Geopolitical Risk (GPR) Index stood at **165.66**. This represents a **significant escalation**, surging by 17.51% compared to the previous month. Compared to the same period last year, the index shifted by 26.92%.\n\n**Historical Context:**\nThis reading sits at the **95.0th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 160.18 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2025-05", "publish_date": "2025-05-01", "publish_timestamp": 1746057600, "gpr_score": 165.66, "gpr_percentile": 94.95}} +{"id": "e30e503e-a815-5871-9445-883c5af53165", "text": "### Geopolitical Risk (GPR) Index Update: June 2025\n\n**Date:** June 2025\n**GPR Score:** 222.38\n\n**Summary:**\nIn June 2025, the global Geopolitical Risk (GPR) Index stood at **222.38**. This represents a **significant escalation**, surging by 34.24% compared to the previous month. Compared to the same period last year, the index shifted by 96.63%.\n\n**Historical Context:**\nThis reading sits at the **97.6th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 176.34 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2025-06", "publish_date": "2025-06-01", "publish_timestamp": 1748736000, "gpr_score": 222.38, "gpr_percentile": 97.58}} +{"id": "2874f4d9-d0c2-5fd3-aa14-7516e13ae8ec", "text": "### Geopolitical Risk (GPR) Index Update: July 2025\n\n**Date:** July 2025\n**GPR Score:** 134.02\n\n**Summary:**\nIn July 2025, the global Geopolitical Risk (GPR) Index stood at **134.02**. This indicates a **cooling off** of geopolitical tensions, dropping by 39.73% month-over-month. Compared to the same period last year, the index shifted by 45.05%.\n\n**Historical Context:**\nThis reading sits at the **85.7th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 174.02 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2025-07", "publish_date": "2025-07-01", "publish_timestamp": 1751328000, "gpr_score": 134.02, "gpr_percentile": 85.66}} +{"id": "da9bd184-06b8-5fb3-b935-2241b35d9d43", "text": "### Geopolitical Risk (GPR) Index Update: August 2025\n\n**Date:** August 2025\n**GPR Score:** 138.56\n\n**Summary:**\nIn August 2025, the global Geopolitical Risk (GPR) Index stood at **138.56**. The index changed by 3.39% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -1.71%.\n\n**Historical Context:**\nThis reading sits at the **88.1th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 164.99 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2025-08", "publish_date": "2025-08-01", "publish_timestamp": 1754006400, "gpr_score": 138.56, "gpr_percentile": 88.08}} +{"id": "3831f3e0-7c4b-510a-af3d-8186e1ad9632", "text": "### Geopolitical Risk (GPR) Index Update: September 2025\n\n**Date:** September 2025\n**GPR Score:** 125.87\n\n**Summary:**\nIn September 2025, the global Geopolitical Risk (GPR) Index stood at **125.87**. The index changed by -9.16% month-over-month, showing relative stability. Compared to the same period last year, the index shifted by -3.44%.\n\n**Historical Context:**\nThis reading sits at the **82.2th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 132.82 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2025-09", "publish_date": "2025-09-01", "publish_timestamp": 1756684800, "gpr_score": 125.87, "gpr_percentile": 82.22}} +{"id": "62373a3e-5090-56f6-b483-4e49dd322ace", "text": "### Geopolitical Risk (GPR) Index Update: October 2025\n\n**Date:** October 2025\n**GPR Score:** 154.51\n\n**Summary:**\nIn October 2025, the global Geopolitical Risk (GPR) Index stood at **154.51**. This represents a **significant escalation**, surging by 22.76% compared to the previous month. Compared to the same period last year, the index shifted by 18.23%.\n\n**Historical Context:**\nThis reading sits at the **93.1th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 139.65 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2025-10", "publish_date": "2025-10-01", "publish_timestamp": 1759276800, "gpr_score": 154.51, "gpr_percentile": 93.13}} +{"id": "e39ffc50-574f-55e6-b057-d312958ed344", "text": "### Geopolitical Risk (GPR) Index Update: November 2025\n\n**Date:** November 2025\n**GPR Score:** 104.34\n\n**Summary:**\nIn November 2025, the global Geopolitical Risk (GPR) Index stood at **104.34**. This indicates a **cooling off** of geopolitical tensions, dropping by 32.47% month-over-month. Compared to the same period last year, the index shifted by -19.06%.\n\n**Historical Context:**\nThis reading sits at the **66.7th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 128.24 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2025-11", "publish_date": "2025-11-01", "publish_timestamp": 1761955200, "gpr_score": 104.34, "gpr_percentile": 66.67}} +{"id": "d861053f-3ce3-57d5-99ca-b54907183bde", "text": "### Geopolitical Risk (GPR) Index Update: December 2025\n\n**Date:** December 2025\n**GPR Score:** 131.39\n\n**Summary:**\nIn December 2025, the global Geopolitical Risk (GPR) Index stood at **131.39**. This represents a **significant escalation**, surging by 25.93% compared to the previous month. Compared to the same period last year, the index shifted by -7.71%.\n\n**Historical Context:**\nThis reading sits at the **84.4th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 130.08 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2025-12", "publish_date": "2025-12-01", "publish_timestamp": 1764547200, "gpr_score": 131.39, "gpr_percentile": 84.44}} +{"id": "bd672c3b-1f25-5ae1-9b2c-dea11f718305", "text": "### Geopolitical Risk (GPR) Index Update: January 2026\n\n**Date:** January 2026\n**GPR Score:** 167.8\n\n**Summary:**\nIn January 2026, the global Geopolitical Risk (GPR) Index stood at **167.8**. This represents a **significant escalation**, surging by 27.71% compared to the previous month. Compared to the same period last year, the index shifted by 48.19%.\n\n**Historical Context:**\nThis reading sits at the **95.3th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 134.51 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2026-01", "publish_date": "2026-01-01", "publish_timestamp": 1767225600, "gpr_score": 167.8, "gpr_percentile": 95.35}} +{"id": "9e7b3f18-e68d-541e-a3b3-76b9fbcb8ac7", "text": "### Geopolitical Risk (GPR) Index Update: February 2026\n\n**Date:** February 2026\n**GPR Score:** 121.62\n\n**Summary:**\nIn February 2026, the global Geopolitical Risk (GPR) Index stood at **121.62**. This indicates a **cooling off** of geopolitical tensions, dropping by 27.52% month-over-month. Compared to the same period last year, the index shifted by -11.21%.\n\n**Historical Context:**\nThis reading sits at the **80.8th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 140.27 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2026-02", "publish_date": "2026-02-01", "publish_timestamp": 1769904000, "gpr_score": 121.62, "gpr_percentile": 80.81}} +{"id": "25620164-722d-50a3-8776-330bdcc83a75", "text": "### Geopolitical Risk (GPR) Index Update: March 2026\n\n**Date:** March 2026\n**GPR Score:** 297.27\n\n**Summary:**\nIn March 2026, the global Geopolitical Risk (GPR) Index stood at **297.27**. This represents a **significant escalation**, surging by 144.43% compared to the previous month. Compared to the same period last year, the index shifted by 70.93%.\n\n**Historical Context:**\nThis reading sits at the **98.6th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of 195.56 suggests the current medium-term trend.\n\n**Impact on Precious Metals:**\nHistorically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG).\n", "metadata": {"topic": "macro_geopolitics_risk", "title": "GPR Index Update 2026-03", "publish_date": "2026-03-01", "publish_timestamp": 1772323200, "gpr_score": 297.27, "gpr_percentile": 98.59}} diff --git a/Data/3_Gold_Semantic/Macro_Narratives/2026-04-04/macro_context_2026-04-04.md b/Data/3_Gold_Semantic/Macro_Narratives/2026-04-04/macro_context_2026-04-04.md new file mode 100644 index 0000000..524dec8 --- /dev/null +++ b/Data/3_Gold_Semantic/Macro_Narratives/2026-04-04/macro_context_2026-04-04.md @@ -0,0 +1,16 @@ +## 📊 Macro & Market Daily Snapshot +> **Generated on:** 2026-04-04 +> **Note to LLM:** Macro indicators lag behind market data. Use YoY/MoM changes to gauge economic momentum. + +### 📈 Market Data (Daily) +- **[Equity Index] S&P 500 (^GSPC)**: 6582.69 Points | Change: **+0.11%** *(Observed: 2026-04-02)* +- **[Equity Index] NASDAQ (^IXIC)**: 21879.18 Points | Change: **+0.18%** *(Observed: 2026-04-02)* +- **[Volatility Index] VIX Volatility (^VIX)**: 23.87 Points | Change: **-2.73%** *(Observed: 2026-04-02)* +- **[Currency] US Dollar Index (DX-Y.NYB)**: 100.19 Points | Change: **+0.16%** *(Observed: 2026-04-03)* +- **[Commodity ETF] Gold ETF (GLD)**: 429.41 USD | Change: **-1.92%** *(Observed: 2026-04-02)* +- **[Commodity ETF] Silver ETF (SLV)**: 65.79 USD | Change: **-3.45%** *(Observed: 2026-04-02)* + +### 🏛️ Macro Economic Indicators (Lagging) +- **[Interest Rate] Effective Federal Funds Rate (FEDFUNDS)**: 3.64 % | MoM: **+0.00%** | YoY: **-15.94%** *(Observed: 2026-03-01)* +- **[Inflation] CPI (Inflation) (CPIAUCSL)**: 327.46 Index | MoM: **+0.27%** | YoY: **+2.66%** *(Observed: 2026-02-01)* +- **[Labor Market] Unemployment Rate (UNRATE)**: 4.30 % | MoM: **-2.27%** | YoY: **+2.38%** *(Observed: 2026-03-01)* \ No newline at end of file diff --git a/Data/3_Gold_Semantic/Macro_Narratives/2026-04-06/macro_context_2026-04-06.md b/Data/3_Gold_Semantic/Macro_Narratives/2026-04-06/macro_context_2026-04-06.md new file mode 100644 index 0000000..815feaf --- /dev/null +++ b/Data/3_Gold_Semantic/Macro_Narratives/2026-04-06/macro_context_2026-04-06.md @@ -0,0 +1,16 @@ +## 📊 Macro & Market Daily Snapshot +> **Generated on:** 2026-04-06 +> **Note to LLM:** Macro indicators lag behind market data. Use YoY/MoM changes to gauge economic momentum. + +### 📈 Market Data (Daily) +- **[Equity Index] S&P 500 (^GSPC)**: 6603.27 Points | Change: **+0.31%** *(Observed: 2026-04-06)* +- **[Equity Index] NASDAQ (^IXIC)**: 21974.25 Points | Change: **+0.43%** *(Observed: 2026-04-06)* +- **[Volatility Index] VIX Volatility (^VIX)**: 24.37 Points | Change: **+2.09%** *(Observed: 2026-04-06)* +- **[Currency] US Dollar Index (DX-Y.NYB)**: 99.99 Points | Change: **-0.04%** *(Observed: 2026-04-06)* +- **[Commodity ETF] Gold ETF (GLD)**: 427.36 USD | Change: **-0.48%** *(Observed: 2026-04-06)* +- **[Commodity ETF] Silver ETF (SLV)**: 66.16 USD | Change: **+0.56%** *(Observed: 2026-04-06)* + +### 🏛️ Macro Economic Indicators (Lagging) +- **[Interest Rate] Effective Federal Funds Rate (FEDFUNDS)**: 3.64 % | MoM: **+0.00%** | YoY: **-15.94%** *(Observed: 2026-03-01)* +- **[Inflation] CPI (Inflation) (CPIAUCSL)**: 327.46 Index | MoM: **+0.27%** | YoY: **+2.66%** *(Observed: 2026-02-01)* +- **[Labor Market] Unemployment Rate (UNRATE)**: 4.30 % | MoM: **-2.27%** | YoY: **+2.38%** *(Observed: 2026-03-01)* \ No newline at end of file diff --git a/Data/3_Gold_Semantic/Macro_Narratives/2026-04-08/macro_context_2026-04-08.md b/Data/3_Gold_Semantic/Macro_Narratives/2026-04-08/macro_context_2026-04-08.md new file mode 100644 index 0000000..5417342 --- /dev/null +++ b/Data/3_Gold_Semantic/Macro_Narratives/2026-04-08/macro_context_2026-04-08.md @@ -0,0 +1,16 @@ +## 📊 Macro & Market Daily Snapshot +> **Generated on:** 2026-04-08 +> **Note to LLM:** Macro indicators lag behind market data. Use YoY/MoM changes to gauge economic momentum. + +### 📈 Market Data (Daily) +- **[Equity Index] S&P 500 (^GSPC)**: 6774.82 Points | Change: **+2.39%** *(Observed: 2026-04-08)* +- **[Equity Index] NASDAQ (^IXIC)**: 22651.88 Points | Change: **+2.88%** *(Observed: 2026-04-08)* +- **[Volatility Index] VIX Volatility (^VIX)**: 20.97 Points | Change: **-18.66%** *(Observed: 2026-04-08)* +- **[Currency] US Dollar Index (DX-Y.NYB)**: 98.95 Points | Change: **-0.69%** *(Observed: 2026-04-08)* +- **[Commodity ETF] Gold ETF (GLD)**: 435.65 USD | Change: **+0.89%** *(Observed: 2026-04-08)* +- **[Commodity ETF] Silver ETF (SLV)**: 68.22 USD | Change: **+3.46%** *(Observed: 2026-04-08)* + +### 🏛️ Macro Economic Indicators (Lagging) +- **[Interest Rate] Effective Federal Funds Rate (FEDFUNDS)**: 3.64 % | MoM: **+0.00%** | YoY: **-15.94%** *(Observed: 2026-03-01)* +- **[Inflation] CPI (Inflation) (CPIAUCSL)**: 327.46 Index | MoM: **+0.27%** | YoY: **+2.66%** *(Observed: 2026-02-01)* +- **[Labor Market] Unemployment Rate (UNRATE)**: 4.30 % | MoM: **-2.27%** | YoY: **+2.38%** *(Observed: 2026-03-01)* \ No newline at end of file diff --git a/Data/3_Gold_Semantic/Macro_Narratives/2026-04-09/macro_context_2026-04-09.md b/Data/3_Gold_Semantic/Macro_Narratives/2026-04-09/macro_context_2026-04-09.md new file mode 100644 index 0000000..f8506e7 --- /dev/null +++ b/Data/3_Gold_Semantic/Macro_Narratives/2026-04-09/macro_context_2026-04-09.md @@ -0,0 +1,16 @@ +## 📊 Macro & Market Daily Snapshot +> **Generated on:** 2026-04-09 +> **Note to LLM:** Macro indicators lag behind market data. Use YoY/MoM changes to gauge economic momentum. + +### 📈 Market Data (Daily) +- **[Equity Index] S&P 500 (^GSPC)**: 6815.30 Points | Change: **+0.48%** *(Observed: 2026-04-09)* +- **[Equity Index] NASDAQ (^IXIC)**: 22749.99 Points | Change: **+0.51%** *(Observed: 2026-04-09)* +- **[Volatility Index] VIX Volatility (^VIX)**: 19.96 Points | Change: **-5.13%** *(Observed: 2026-04-09)* +- **[Currency] US Dollar Index (DX-Y.NYB)**: 98.77 Points | Change: **-0.26%** *(Observed: 2026-04-09)* +- **[Commodity ETF] Gold ETF (GLD)**: 439.27 USD | Change: **+1.09%** *(Observed: 2026-04-09)* +- **[Commodity ETF] Silver ETF (SLV)**: 68.78 USD | Change: **+1.94%** *(Observed: 2026-04-09)* + +### 🏛️ Macro Economic Indicators (Lagging) +- **[Interest Rate] Effective Federal Funds Rate (FEDFUNDS)**: 3.64 % | MoM: **+0.00%** | YoY: **-15.94%** *(Observed: 2026-03-01)* +- **[Inflation] CPI (Inflation) (CPIAUCSL)**: 327.46 Index | MoM: **+0.27%** | YoY: **+2.66%** *(Observed: 2026-02-01)* +- **[Labor Market] Unemployment Rate (UNRATE)**: 4.30 % | MoM: **-2.27%** | YoY: **+2.38%** *(Observed: 2026-03-01)* \ No newline at end of file diff --git a/Data/3_Gold_Semantic/Macro_Narratives/2026-04-10/macro_context_2026-04-10.md b/Data/3_Gold_Semantic/Macro_Narratives/2026-04-10/macro_context_2026-04-10.md new file mode 100644 index 0000000..5d7a65e --- /dev/null +++ b/Data/3_Gold_Semantic/Macro_Narratives/2026-04-10/macro_context_2026-04-10.md @@ -0,0 +1,16 @@ +## 📊 Macro & Market Daily Snapshot +> **Generated on:** 2026-04-10 +> **Note to LLM:** Macro indicators lag behind market data. Use YoY/MoM changes to gauge economic momentum. + +### 📈 Market Data (Daily) +- **[Equity Index] S&P 500 (^GSPC)**: 6812.93 Points | Change: **-0.17%** *(Observed: 2026-04-10)* +- **[Equity Index] NASDAQ (^IXIC)**: 22895.40 Points | Change: **+0.32%** *(Observed: 2026-04-10)* +- **[Volatility Index] VIX Volatility (^VIX)**: 19.53 Points | Change: **+0.21%** *(Observed: 2026-04-10)* +- **[Currency] US Dollar Index (DX-Y.NYB)**: 98.66 Points | Change: **-0.16%** *(Observed: 2026-04-10)* +- **[Commodity ETF] Gold ETF (GLD)**: 437.34 USD | Change: **-0.13%** *(Observed: 2026-04-10)* +- **[Commodity ETF] Silver ETF (SLV)**: 69.11 USD | Change: **+1.05%** *(Observed: 2026-04-10)* + +### 🏛️ Macro Economic Indicators (Lagging) +- **[Interest Rate] Effective Federal Funds Rate (FEDFUNDS)**: 3.64 % | MoM: **+0.00%** | YoY: **-15.94%** *(Observed: 2026-03-01)* +- **[Inflation] CPI (Inflation) (CPIAUCSL)**: 330.29 Index | MoM: **+0.87%** | YoY: **+3.32%** *(Observed: 2026-03-01)* +- **[Labor Market] Unemployment Rate (UNRATE)**: 4.30 % | MoM: **-2.27%** | YoY: **+2.38%** *(Observed: 2026-03-01)* \ No newline at end of file diff --git a/Data/3_Gold_Semantic/Macro_Narratives/2026-04-14/macro_context_2026-04-14.md b/Data/3_Gold_Semantic/Macro_Narratives/2026-04-14/macro_context_2026-04-14.md new file mode 100644 index 0000000..a727356 --- /dev/null +++ b/Data/3_Gold_Semantic/Macro_Narratives/2026-04-14/macro_context_2026-04-14.md @@ -0,0 +1,16 @@ +## 📊 Macro & Market Daily Snapshot +> **Generated on:** 2026-04-14 +> **Note to LLM:** Macro indicators lag behind market data. Use YoY/MoM changes to gauge economic momentum. + +### 📈 Market Data (Daily) +- **[Equity Index] S&P 500 (^GSPC)**: 6967.38 Points | Change: **+1.18%** *(Observed: 2026-04-14)* +- **[Equity Index] NASDAQ (^IXIC)**: 23639.08 Points | Change: **+1.96%** *(Observed: 2026-04-14)* +- **[Volatility Index] VIX Volatility (^VIX)**: 18.36 Points | Change: **-3.97%** *(Observed: 2026-04-14)* +- **[Currency] US Dollar Index (DX-Y.NYB)**: 98.19 Points | Change: **-0.19%** *(Observed: 2026-04-14)* +- **[Commodity ETF] Gold ETF (GLD)**: 445.09 USD | Change: **+2.23%** *(Observed: 2026-04-14)* +- **[Commodity ETF] Silver ETF (SLV)**: 72.04 USD | Change: **+5.51%** *(Observed: 2026-04-14)* + +### 🏛️ Macro Economic Indicators (Lagging) +- **[Interest Rate] Effective Federal Funds Rate (FEDFUNDS)**: 3.64 % | MoM: **+0.00%** | YoY: **-15.94%** *(Observed: 2026-03-01)* +- **[Inflation] CPI (Inflation) (CPIAUCSL)**: 330.29 Index | MoM: **+0.87%** | YoY: **+3.32%** *(Observed: 2026-03-01)* +- **[Labor Market] Unemployment Rate (UNRATE)**: 4.30 % | MoM: **-2.27%** | YoY: **+2.38%** *(Observed: 2026-03-01)* \ No newline at end of file diff --git a/Data/3_Gold_Semantic/Macro_Narratives/2026-04-16/macro_context_2026-04-16.md b/Data/3_Gold_Semantic/Macro_Narratives/2026-04-16/macro_context_2026-04-16.md new file mode 100644 index 0000000..83d35d6 --- /dev/null +++ b/Data/3_Gold_Semantic/Macro_Narratives/2026-04-16/macro_context_2026-04-16.md @@ -0,0 +1,16 @@ +## 📊 Macro & Market Daily Snapshot +> **Generated on:** 2026-04-16 +> **Note to LLM:** Macro indicators lag behind market data. Use YoY/MoM changes to gauge economic momentum. + +### 📈 Market Data (Daily) +- **[Equity Index] S&P 500 (^GSPC)**: 7022.95 Points | Change: **+0.80%** *(Observed: 2026-04-15)* +- **[Equity Index] NASDAQ (^IXIC)**: 24016.02 Points | Change: **+1.59%** *(Observed: 2026-04-15)* +- **[Volatility Index] VIX Volatility (^VIX)**: 18.25 Points | Change: **+0.44%** *(Observed: 2026-04-16)* +- **[Currency] US Dollar Index (DX-Y.NYB)**: 98.22 Points | Change: **+0.16%** *(Observed: 2026-04-16)* +- **[Commodity ETF] Gold ETF (GLD)**: 440.46 USD | Change: **-1.04%** *(Observed: 2026-04-15)* +- **[Commodity ETF] Silver ETF (SLV)**: 71.84 USD | Change: **-0.28%** *(Observed: 2026-04-15)* + +### 🏛️ Macro Economic Indicators (Lagging) +- **[Interest Rate] Effective Federal Funds Rate (FEDFUNDS)**: 3.64 % | MoM: **+0.00%** | YoY: **-15.94%** *(Observed: 2026-03-01)* +- **[Inflation] CPI (Inflation) (CPIAUCSL)**: 330.29 Index | MoM: **+0.87%** | YoY: **+3.32%** *(Observed: 2026-03-01)* +- **[Labor Market] Unemployment Rate (UNRATE)**: 4.30 % | MoM: **-2.27%** | YoY: **+2.38%** *(Observed: 2026-03-01)* \ No newline at end of file diff --git a/Data/3_Gold_Semantic/Macro_Narratives/2026-04-19/macro_context_2026-04-19.md b/Data/3_Gold_Semantic/Macro_Narratives/2026-04-19/macro_context_2026-04-19.md new file mode 100644 index 0000000..1ef6f6a --- /dev/null +++ b/Data/3_Gold_Semantic/Macro_Narratives/2026-04-19/macro_context_2026-04-19.md @@ -0,0 +1,16 @@ +## 📊 Macro & Market Daily Snapshot +> **Generated on:** 2026-04-19 +> **Note to LLM:** Macro indicators lag behind market data. Use YoY/MoM changes to gauge economic momentum. + +### 📈 Market Data (Daily) +- **[Equity Index] S&P 500 (^GSPC)**: 7126.06 Points | Change: **+1.20%** *(Observed: 2026-04-17)* +- **[Equity Index] NASDAQ (^IXIC)**: 24468.48 Points | Change: **+1.52%** *(Observed: 2026-04-17)* +- **[Volatility Index] VIX Volatility (^VIX)**: 17.48 Points | Change: **-2.56%** *(Observed: 2026-04-17)* +- **[Currency] US Dollar Index (DX-Y.NYB)**: 98.10 Points | Change: **-0.12%** *(Observed: 2026-04-17)* +- **[Commodity ETF] Gold ETF (GLD)**: 445.93 USD | Change: **+1.33%** *(Observed: 2026-04-17)* +- **[Commodity ETF] Silver ETF (SLV)**: 73.63 USD | Change: **+3.35%** *(Observed: 2026-04-17)* + +### 🏛️ Macro Economic Indicators (Lagging) +- **[Interest Rate] Effective Federal Funds Rate (FEDFUNDS)**: 3.64 % | MoM: **+0.00%** | YoY: **-15.94%** *(Observed: 2026-03-01)* +- **[Inflation] CPI (Inflation) (CPIAUCSL)**: 330.29 Index | MoM: **+0.87%** | YoY: **+3.32%** *(Observed: 2026-03-01)* +- **[Labor Market] Unemployment Rate (UNRATE)**: 4.30 % | MoM: **-2.27%** | YoY: **+2.38%** *(Observed: 2026-03-01)* \ No newline at end of file diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-08/qdrant_asset_precious_metals_spot_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-08/qdrant_asset_precious_metals_spot_processed.jsonl new file mode 100644 index 0000000..8a7af9a --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-08/qdrant_asset_precious_metals_spot_processed.jsonl @@ -0,0 +1,3 @@ +{"id": "cca38239-6593-5985-9ba4-7ecbd87b54e4", "text": "\"Anxin Unveils New High-End Brand Hyper, Aiming to Lead the Industry in Smart Cars\". Anxin, a Chinese company, has launched its new high-end brand Hyper, which aims to lead the industry in smart cars. The brand's first product, Hyper SSR, is a supercar with impressive acceleration and AI-powered trajectory control system. This move is seen as a key step in Anxin's transformation from a traditional car manufacturer to a technology company. As China continues to strengthen its technological attributes through space cooperation projects, Anxin's new brand may drive the country's new energy vehicle industry to break new ground.\n\nThe tone score of +2 reflects the bullish sentiment towards Gold/Silver prices due to the potential increase in market fear/VIX driven by the rapid development of smart cars and China's growing technological capabilities. The impacted assets include Equities, Gold, and USD, as the news may have implications for global markets and currencies.", "metadata": {"topic": "asset_precious_metals_spot", "title": "\"Anxin Unveils New High-End Brand Hyper, Aiming to Lead the Industry in Smart Cars\"", "original_title": "逆境中破局前行 , 埃安换标推新高端品牌引领行业新变革 - 智能汽车 - ITBear比尔科技", "publish_date": "2026-04-09T01:22:35Z", "publish_timestamp": 1775697755, "source": "itbear.com.cn", "url": "https://www.itbear.com.cn/html/2026-04/1264928.html", "entities": ["Anxin", "Tesla", "China"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Increase", "llm_tone_score": 2}} +{"id": "17caf862-efab-55c3-9d5d-6c626214176c", "text": "Unfazed by Geopolitical Headwinds! Goldman Sachs: AI Spending Wave Surges, Sets Up for Sell-Off at the Right Time| Artificial Intelligence. Goldman Sachs' commentary on AI spending trends suggests a potential sell-off in the market. The firm notes that despite geopolitical headwinds, the AI sector remains resilient and poised for growth. This neutral tone implies no significant macro drivers impacting gold or silver prices at this time.", "metadata": {"topic": "asset_precious_metals_spot", "title": "Unfazed by Geopolitical Headwinds! Goldman Sachs: AI Spending Wave Surges, Sets Up for Sell-Off at the Right Time| Artificial Intelligence", "original_title": "无惧地缘逆风 ! 高盛 : AI支出浪潮汹涌 , 布局 卖铲人 正当时|人工智能", "publish_date": "2026-04-09T01:22:35Z", "publish_timestamp": 1775697755, "source": "163.com", "url": "https://www.163.com/dy/article/KQ2DKDEO05198UNI.html", "entities": ["Goldman Sachs", "NetEase Hao", "artificial intelligence"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "a0a487b3-c585-5852-b167-58cec9b24127", "text": "March 2026 Quarter Production Update from Alkane Resources Limited. Alkane Resources reported strong quarterly production of 45,776 oz AuEq from its three operating mines. The company maintained a healthy cash balance of $362 million and pro forma liquidity of $472 million. Guidance for FY2026 remains unchanged at 160,000 to 175,000 AuEq oz production at an AISC of A$2,600 - $2,900 per AuEq oz. The update suggests a stable macro environment with no significant disruptions or surprises that would impact gold and antimony prices.", "metadata": {"topic": "asset_precious_metals_spot", "title": "March 2026 Quarter Production Update from Alkane Resources Limited", "original_title": "Alkane Resources Limited : March 2026 Quarter Production Update", "publish_date": "2026-04-09T01:22:35Z", "publish_timestamp": 1775697755, "source": "finanznachrichten.de", "url": "https://www.finanznachrichten.de/nachrichten-2026-04/68152259-alkane-resources-limited-march-2026-quarter-production-update-399.htm", "entities": ["Alkane Resources Limited", "Nic Earner (Managing Director & CEO)", "Australia", "Sweden"], "impacted_assets": ["Gold", "Antimony", "Cash and Bullion"], "volatility_implication": "Neutral", "llm_tone_score": 2}} diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-08/qdrant_macro_central_banks_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-08/qdrant_macro_central_banks_processed.jsonl new file mode 100644 index 0000000..9a22dc6 --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-08/qdrant_macro_central_banks_processed.jsonl @@ -0,0 +1,9 @@ +{"id": "e59121fd-02bd-5521-a7b4-7f1e860eeaba", "text": "Housing Market Mood Shift Amid Rising Mortgage Costs and Geopolitical Uncertainty. The UK housing market is losing momentum due to rising mortgage costs and geopolitical uncertainty. Buyer demand has softened, with a net balance of 39% of professionals seeing new buyer inquiries falling rather than rising. This trend is expected to continue in the coming months, with a net balance of 33% of professionals expecting sales activity to weaken further. The macro transmission mechanism is driven by higher borrowing costs and inflationary concerns, which are likely to keep mortgage rates elevated for some time yet.", "metadata": {"topic": "macro_central_banks", "title": "Housing Market Mood Shift Amid Rising Mortgage Costs and Geopolitical Uncertainty", "original_title": "Rising mortgage costs dent buyer demand amid housing market mood shift ", "publish_date": "2026-04-09T01:19:11Z", "publish_timestamp": 1775697551, "source": "clactonandfrintongazette.co.uk", "url": "https://www.clactonandfrintongazette.co.uk/news/national/26005807.rising-mortgage-costs-dent-buyer-demand-amid-housing-market-mood-shift/", "entities": ["Royal Institution of Chartered Surveyors (Rics)", "Moneyfacts", "Sprive"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Increase", "llm_tone_score": -2}} +{"id": "3efce571-c129-5a55-8662-5fb1c0b49592", "text": "Housing Market Mood Shift Amid Rising Mortgage Costs and Geopolitical Uncertainty. The UK housing market is losing momentum due to rising mortgage costs and geopolitical uncertainty. Buyer demand has softened, with a net balance of 39% of professionals seeing new buyer inquiries falling rather than rising. This trend is expected to continue in the short term, with a net balance of 33% of professionals expecting sales activity to weaken further over the next few months. The macro transmission mechanism is driven by higher borrowing costs and inflationary concerns, which are likely to impact gold and silver prices positively.\n\nNote: The tone score is bearish due to the negative sentiment surrounding the housing market and the potential for increased volatility in the short term.", "metadata": {"topic": "macro_central_banks", "title": "Housing Market Mood Shift Amid Rising Mortgage Costs and Geopolitical Uncertainty", "original_title": "Rising mortgage costs dent buyer demand amid housing market mood shift ", "publish_date": "2026-04-09T01:19:11Z", "publish_timestamp": 1775697551, "source": "northwichguardian.co.uk", "url": "https://www.northwichguardian.co.uk/news/national/26005807.rising-mortgage-costs-dent-buyer-demand-amid-housing-market-mood-shift/", "entities": ["Royal Institution of Chartered Surveyors (Rics)", "Moneyfacts", "Sprive"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Increase", "llm_tone_score": -2}} +{"id": "6d4345a8-6526-5cd9-87d9-2dc152fa6b84", "text": "Turkish Treasury's Cash Flow and Debt Management in the First Quarter of 2023. The Turkish Treasury reported a significant increase in debt repayment and interest payments in the first quarter of 2023. The treasury's cash flow deficit widened to 618 billion lira, driven by high-interest payments and debt repayments. This development may lead to increased market volatility and potentially weigh on gold prices.\n\nThe macro transmission mechanism is as follows: The Turkish Treasury's increasing debt repayment and interest payments will likely lead to a decrease in the value of government bonds, which may cause investors to seek safer assets like gold. Additionally, the widening cash flow deficit may lead to concerns about Turkey's fiscal sustainability, further contributing to market volatility.", "metadata": {"topic": "macro_central_banks", "title": "Turkish Treasury's Cash Flow and Debt Management in the First Quarter of 2023", "original_title": "Günde ortalama 18 milyar TL - Naki BAKIR", "publish_date": "2026-04-09T01:19:11Z", "publish_timestamp": 1775697551, "source": "dunya.com", "url": "https://www.dunya.com/kose-yazisi/gunde-ortalama-18-milyar-tl/820965", "entities": ["Turkish Treasury", "Hazine", "Tasarruf Mevduatı Sigorta Fonu (TMSF)"], "impacted_assets": ["Government Bonds", "Turkish Lira (TRY)", "Gold"], "volatility_implication": "Decrease", "llm_tone_score": -2}} +{"id": "92e564c6-62ea-568d-8e67-5727cd26dcbb", "text": "South Korea's Card Loan Balance Surpasses 15 Trillion Won for the First Time in 6 Months Amid Economic Downturn. South Korea's card loan balance has surpassed 15 trillion won for the first time in six months amid economic downturn. The increase is attributed to banks tightening credit standards, leading to a surge in demand for credit cards. This trend may continue, potentially increasing delinquency rates and affecting the overall economy. The Bank of Korea's recent data shows that the credit card loan delinquency rate has reached its highest level in 20 years, indicating a potential risk to the financial system.\n\nThe macro transmission mechanism is as follows: the economic downturn leads to increased demand for credit cards, which in turn drives up delinquency rates. This may have a negative impact on the overall economy and potentially affect asset prices such as equities and gold. The decrease in volatility implication suggests that market fear (VIX) may decrease due to the expected increase in delinquency rates, which could lead to a decrease in risk appetite and a subsequent decline in asset prices.", "metadata": {"topic": "macro_central_banks", "title": "South Korea's Card Loan Balance Surpasses 15 Trillion Won for the First Time in 6 Months Amid Economic Downturn", "original_title": "경기 불황에 카드 돌려막기 6개월 만에 반등 … 연체율도 20년새 최고", "publish_date": "2026-04-09T01:19:11Z", "publish_timestamp": 1775697551, "source": "fnnews.com", "url": "https://www.fnnews.com/news/202604090630516306", "entities": ["Bank of Korea", "Korean Federation of Banks", "major credit card companies (Shinhan", "Samsung", "Hyundai", "KB Kookmin", "Lotte", "Woosong", "Hanwha", "and BC Card)"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Decrease", "llm_tone_score": -2}} +{"id": "5fb74704-7627-5fd8-ac58-a5ad871baee4", "text": "Stocks Rally as Oil Prices Plummet Following Iran War Ceasefire. The temporary ceasefire between the US and Iran has led to a surge in global equities, with the S&P 500, Dow Jones Industrial Average, and Nasdaq composite all rising significantly. The decline in oil prices has also had a positive impact on airline and travel stocks, while Treasury yields have fallen as hopes of lower interest rates later in the year increase. However, analysts caution that the ceasefire remains fragile, and any further escalation could negatively impact market sentiment.\n\nThe macro transmission mechanism is as follows: A decrease in oil prices reduces inflationary pressures, which can lead to a more accommodative monetary policy from central banks like the Federal Reserve. This, in turn, can boost equities and other risk assets, while also reducing the appeal of safe-haven assets like gold.", "metadata": {"topic": "macro_central_banks", "title": "Stocks Rally as Oil Prices Plummet Following Iran War Ceasefire", "original_title": "Stocks Close The Day Higher As Oil Prices Plummet Over Iran War Cease Fire", "publish_date": "2026-04-09T01:19:11Z", "publish_timestamp": 1775697551, "source": "newsradio1290wtks.iheart.com", "url": "https://newsradio1290wtks.iheart.com/content/2026-04-08-stocks-close-the-day-higher-as-oil-prices-plummet-over-iran-war-cease-fire/", "entities": ["United States", "Iran", "President Donald Trump", "United Airlines", "Carnival cruise lines", "Delta Air Lines"], "impacted_assets": ["Equities", "Gold", "Oil"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "9432d3d9-5abe-590f-bba0-9bb072a5ba6c", "text": "Housing Market Mood Shift: Rising Mortgage Costs Dent Buyer Demand. The UK housing market is losing momentum due to rising mortgage costs and geopolitical uncertainty. Buyer demand has softened, with a net balance of 39% of professionals seeing new buyer inquiries falling rather than rising. This trend is expected to continue, with a net balance of 33% of professionals expecting sales activity to weaken further over the next few months. The macro transmission mechanism is driven by higher borrowing costs and inflationary concerns, which are likely to impact gold and silver prices positively.\n\nNote: The tone score is bearish due to the negative impact on buyer demand and housing market activity, which may lead to increased volatility in the short term.", "metadata": {"topic": "macro_central_banks", "title": "Housing Market Mood Shift: Rising Mortgage Costs Dent Buyer Demand", "original_title": "Rising mortgage costs dent buyer demand amid housing market mood shift ", "publish_date": "2026-04-09T01:19:11Z", "publish_timestamp": 1775697551, "source": "watfordobserver.co.uk", "url": "https://www.watfordobserver.co.uk/news/national/26005807.rising-mortgage-costs-dent-buyer-demand-amid-housing-market-mood-shift/", "entities": ["Royal Institution of Chartered Surveyors (Rics)", "Moneyfacts", "Sprive"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Increase", "llm_tone_score": -2}} +{"id": "63b64aeb-5490-563b-9263-f47110cbd261", "text": "Stocks Rally as Oil Prices Plummet Following Iran War Ceasefire. The temporary ceasefire between the US and Iran led to a surge in stocks, with the S&P 500, Dow Jones Industrial Average, and Nasdaq composite all rising. Oil prices plummeted, falling below $95 per barrel, which could lead to lower inflation and potentially pave the way for further interest rate cuts by the Federal Reserve. The market's optimism was tempered by concerns about the ceasefire's fragility and potential continued attacks in the region.", "metadata": {"topic": "macro_central_banks", "title": "Stocks Rally as Oil Prices Plummet Following Iran War Ceasefire", "original_title": "Stocks Close The Day Higher As Oil Prices Plummet Over Iran War Cease Fire | NewsRadio WKCY", "publish_date": "2026-04-09T01:19:11Z", "publish_timestamp": 1775697551, "source": "newsradiowkcy.iheart.com", "url": "https://newsradiowkcy.iheart.com/content/2026-04-08-stocks-close-the-day-higher-as-oil-prices-plummet-over-iran-war-cease-fire/", "entities": ["United States", "Iran", "President Donald Trump", "United Airlines", "Carnival cruise lines", "Delta Air Lines"], "impacted_assets": ["Equities", "Gold", "Oil"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "d80bb29c-caf5-5828-80db-b71322f41e81", "text": "Housing Market Mood Shift: Rising Mortgage Costs Dent Buyer Demand. The UK housing market is losing momentum due to rising mortgage costs and geopolitical uncertainty. Buyer demand has softened, with a net balance of 39% of professionals seeing new buyer inquiries falling rather than rising. This trend is expected to continue, with a net balance of 33% of professionals expecting sales activity to weaken further over the next few months. The macro transmission mechanism is driven by higher borrowing costs and inflationary concerns, which are likely to impact gold and silver prices positively.\n\nNote: The tone score is bearish due to the negative impact on buyer demand and housing market activity, which may lead to increased volatility in the short term.", "metadata": {"topic": "macro_central_banks", "title": "Housing Market Mood Shift: Rising Mortgage Costs Dent Buyer Demand", "original_title": "Rising mortgage costs dent buyer demand amid housing market mood shift ", "publish_date": "2026-04-09T01:19:11Z", "publish_timestamp": 1775697551, "source": "stourbridgenews.co.uk", "url": "https://www.stourbridgenews.co.uk/news/national/26005807.rising-mortgage-costs-dent-buyer-demand-amid-housing-market-mood-shift/", "entities": ["Royal Institution of Chartered Surveyors (Rics)", "Moneyfacts", "Sprive"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Increase", "llm_tone_score": -2}} +{"id": "17c196f3-2982-5021-9934-22612ee7a3c3", "text": "The Harm Caused by Export Restrictions to Prevent Price Increases. The article discusses the negative impact of export restrictions on producers and the economy. The restriction is intended to prevent price increases, but it hinders production capacity, investment, and exports. The author suggests that a re-consideration of the credit mechanism could help stimulate production, exports, and economic growth. The article highlights the importance of prioritizing policies that drive demand and stimulate production in sectors such as construction, which has a high domestic content rate and contributes significantly to the economy.\n\nThe macro transmission mechanism is that the export restriction reduces production capacity, investment, and exports, leading to a decrease in economic activity and potentially inflationary pressures. The article's tone is neutral, as it presents both sides of the argument without taking a clear stance on the issue.", "metadata": {"topic": "macro_central_banks", "title": "The Harm Caused by Export Restrictions to Prevent Price Increases", "original_title": "Fiyat artışını ihracat kısıtlaması ile önlemenin verdiği zarar … ", "publish_date": "2026-04-09T01:19:11Z", "publish_timestamp": 1775697551, "source": "dunya.com", "url": "https://www.dunya.com/kose-yazisi/fiyat-artisini-ihracat-kisitlamasi-ile-onlemenin-verdigi-zarar/820975", "entities": ["Erdem Çenesiz", "Çimento", "Cam", "Seramik ve Toprak Ürünleri İhracatçıları Birliği"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 0}} diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-08/qdrant_macro_inflation_employment_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-08/qdrant_macro_inflation_employment_processed.jsonl new file mode 100644 index 0000000..e072134 --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-08/qdrant_macro_inflation_employment_processed.jsonl @@ -0,0 +1,6 @@ +{"id": "921918df-ca85-5319-acb0-e0d377b4569c", "text": "Why Is Carnival (CCL) Stock Soaring Today?. The suspension of military action in Iran and a potential negotiated settlement have triggered a relief rally in cruise operator stocks, including Carnival. Lower \"bunker\" fuel costs and eased travel concerns due to the ceasefire have positively impacted the company's stock price. The macro transmission mechanism is through reduced uncertainty and increased consumer confidence, which may also benefit other tourism-related industries.", "metadata": {"topic": "macro_inflation_employment", "title": "Why Is Carnival (CCL) Stock Soaring Today?", "original_title": "Why Is Carnival ( CCL ) Stock Soaring Today", "publish_date": "2026-04-09T01:20:13Z", "publish_timestamp": 1775697613, "source": "finance.yahoo.com", "url": "https://finance.yahoo.com/markets/stocks/articles/why-carnival-ccl-stock-soaring-000547814.html", "entities": ["President Trump", "Iran", "Carnival Corporation (CCL)", "Strait of Hormuz"], "impacted_assets": ["Equities", "Gold", "Oil"], "volatility_implication": "Increase", "llm_tone_score": 2}} +{"id": "d41a4ff3-d568-59a6-81c7-2875aabd28eb", "text": "Iran to Limit Passage of Ships Through Hormuz Strait Despite Ceasefire Agreement. Despite the ceasefire agreement, Iran is planning to limit the passage of ships through the Hormuz Strait, requiring vessels to pay fees in cryptocurrencies or Chinese yuan. This move could lead to a significant decrease in oil and LNG supplies, impacting global energy markets and inflation expectations. The uncertainty surrounding this development may increase market volatility, particularly for oil prices.\n\nThe macro transmission mechanism is as follows: Iran's control over the Hormuz Strait, a critical energy transportation route, could lead to a shortage of oil and LNG supplies, driving up prices and inflation expectations. This, in turn, could strengthen the USD and weigh on gold prices. The increased uncertainty may also lead to a decrease in equities and an increase in volatility.", "metadata": {"topic": "macro_inflation_employment", "title": "Iran to Limit Passage of Ships Through Hormuz Strait Despite Ceasefire Agreement", "original_title": "호르무즈 계속 막은 이란 … 하루 통과 10여척으로 제한 계획 ", "publish_date": "2026-04-09T01:20:13Z", "publish_timestamp": 1775697613, "source": "fnnews.com", "url": "https://www.fnnews.com/news/202604090857326831", "entities": ["Iran", "United States", "Israel", "China"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Increase", "llm_tone_score": -2}} +{"id": "e051fc3b-d996-5c0a-ba45-5d3fc6bceb06", "text": "Oil prices plummet as hopes for resolving Strait of Hormuz tensions rise. The article reports a significant decline in oil prices due to increased hopes for resolving tensions at the Strait of Hormuz. This development is expected to ease concerns about inflation and stabilize global energy supplies. As a result, gold prices may decrease as market fear (VIX) subsides.", "metadata": {"topic": "macro_inflation_employment", "title": "Oil prices plummet as hopes for resolving Strait of Hormuz tensions rise", "original_title": "Giá dầu giảm mạnh khi kỳ vọng khơi thông eo biển Hormuz gia tăng", "publish_date": "2026-04-09T01:20:13Z", "publish_timestamp": 1775697613, "source": "baotintuc.vn", "url": "https://baotintuc.vn/thi-truong-tien-te/gia-dau-giam-manh-khi-ky-vong-khoi-thong-eo-bien-hormuz-gia-tang-20260409072028597.htm", "entities": ["United States", "Iran", "Pakistan", "Capital Economics"], "impacted_assets": ["Gold", "Oil"], "volatility_implication": "Decrease", "llm_tone_score": 2}} +{"id": "98ca5474-a386-5054-9a20-74cd0f45cde5", "text": "FRP Holdings Announces Earnings Release Date and Conference Call Details. FRP Holdings, a real estate holding company, announced its earnings release date for the fourth quarter and full year 2025, as well as details for an upcoming conference call. The event is unlikely to have any significant impact on gold or silver prices, as it is a routine corporate announcement unrelated to macroeconomic or financial market drivers.", "metadata": {"topic": "macro_inflation_employment", "title": "FRP Holdings Announces Earnings Release Date and Conference Call Details", "original_title": "FRP Holdings , Inc . Announces Release Date for Its 2025 Fourth Quarter and Full Year Earnings and Details for the Earnings Conference Call", "publish_date": "2026-04-09T01:20:13Z", "publish_timestamp": 1775697613, "source": "californiatelegraph.com", "url": "http://www.californiatelegraph.com/news/278972410/frp-holdings-inc-announces-release-date-for-its-2025-fourth-quarter-and-full-year-earnings-and-details-for-the-earnings-conference-call", "entities": ["FRP Holdings", "Inc.", "Securities and Exchange Commission", "Matthew C. McNulty"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "62ea6efd-e04b-5da4-b4d1-99aec73d9aaa", "text": "Wall Street Closes in Strong Gain, Relieved by Iran-US Ceasefire Agreement. The US stock market surged on the news of a 2-week ceasefire agreement between the US and Iran, easing concerns about a potential conflict in the Middle East. This development contributed to reduced fears of recession, higher growth expectations, and lower inflation anticipations, leading to a strong gain for equities. The oil price decline also had a positive impact on the market, with energy sector stocks experiencing losses due to the reduced demand.", "metadata": {"topic": "macro_inflation_employment", "title": "Wall Street Closes in Strong Gain, Relieved by Iran-US Ceasefire Agreement", "original_title": "Wall Street clôture en nette hausse , soulagée par le cessez - le - feu en Iran", "publish_date": "2026-04-09T01:20:13Z", "publish_timestamp": 1775697613, "source": "africanmanager.com", "url": "https://africanmanager.com/wall-street-cloture-en-nette-hausse-soulagee-par-le-cessez-le-feu-en-iran/", "entities": ["United States", "Iran", "Edward Jones", "Interactive Brokers", "Chevron", "ConocoPhillips", "EOG Resources", "ExxonMobil"], "impacted_assets": ["Equities", "Oil", "USD"], "volatility_implication": "Decrease", "llm_tone_score": 3}} +{"id": "739516af-d0a7-5fa3-b647-4132035e5d4b", "text": "Update the IRPF (Personal Income Tax). The article suggests that the Spanish government should consider reducing the IRPF tax rate to help consumers and improve their purchasing power. This could be a positive macro driver for gold and silver prices, as it may lead to increased consumer spending and inflationary pressures.", "metadata": {"topic": "macro_inflation_employment", "title": "Update the IRPF (Personal Income Tax)", "original_title": "Actualitzar lIRPF", "publish_date": "2026-04-09T01:20:13Z", "publish_timestamp": 1775697613, "source": "lavanguardia.com", "url": "https://www.lavanguardia.com/participacion/cartas/20260409/11508990/actualitzar-l-irpf.html", "entities": ["Rosa Martí Conill", "Spanish Government", "IRPF (Spanish Personal Income Tax)"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 2}} diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-08/qdrant_macro_yields_dollar_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-08/qdrant_macro_yields_dollar_processed.jsonl new file mode 100644 index 0000000..0c1237c --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-08/qdrant_macro_yields_dollar_processed.jsonl @@ -0,0 +1,9 @@ +{"id": "62ea6efd-e04b-5da4-b4d1-99aec73d9aaa", "text": "Wall Street Closes in Strong Gain, Relieved by Iran-US Ceasefire Agreement. The US stock market surged on the news of a 2-week ceasefire agreement between the US and Iran, easing concerns about a potential conflict in the Middle East. This development contributed to reduced fears of recession, higher growth expectations, and lower inflation anticipations, leading to a strong gain for equities. The oil price decline also had a positive impact on the market, with energy sector stocks experiencing losses due to the reduced demand.", "metadata": {"topic": "macro_yields_dollar", "title": "Wall Street Closes in Strong Gain, Relieved by Iran-US Ceasefire Agreement", "original_title": "Wall Street clôture en nette hausse , soulagée par le cessez - le - feu en Iran", "publish_date": "2026-04-09T01:21:11Z", "publish_timestamp": 1775697671, "source": "africanmanager.com", "url": "https://africanmanager.com/wall-street-cloture-en-nette-hausse-soulagee-par-le-cessez-le-feu-en-iran/", "entities": ["United States", "Iran", "Edward Jones", "Interactive Brokers", "Chevron", "ConocoPhillips", "EOG Resources", "ExxonMobil"], "impacted_assets": ["Equities", "Oil", "USD"], "volatility_implication": "Decrease", "llm_tone_score": 3}} +{"id": "5fb74704-7627-5fd8-ac58-a5ad871baee4", "text": "Stocks Rally as Oil Prices Plummet Following Iran War Ceasefire. The temporary ceasefire between the US and Iran has led to a surge in global equities, with the S&P 500, Dow Jones Industrial Average, and Nasdaq composite all rising significantly. The decline in oil prices has also had a positive impact on airline and travel stocks, while Treasury yields have fallen as hopes of lower interest rates later in the year increase. However, analysts caution that the ceasefire remains fragile, and any further escalation could negatively impact market sentiment.\n\nThe macro transmission mechanism is as follows: A decrease in oil prices reduces inflationary pressures, which can lead to a more accommodative monetary policy from central banks like the Federal Reserve. This, in turn, can boost equities and other risk assets, while also reducing the appeal of safe-haven assets like gold.", "metadata": {"topic": "macro_yields_dollar", "title": "Stocks Rally as Oil Prices Plummet Following Iran War Ceasefire", "original_title": "Stocks Close The Day Higher As Oil Prices Plummet Over Iran War Cease Fire", "publish_date": "2026-04-09T01:21:11Z", "publish_timestamp": 1775697671, "source": "newsradio1290wtks.iheart.com", "url": "https://newsradio1290wtks.iheart.com/content/2026-04-08-stocks-close-the-day-higher-as-oil-prices-plummet-over-iran-war-cease-fire/", "entities": ["United States", "Iran", "President Donald Trump", "United Airlines", "Carnival cruise lines", "Delta Air Lines"], "impacted_assets": ["Equities", "Gold", "Oil"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "63b64aeb-5490-563b-9263-f47110cbd261", "text": "Stocks Rally as Oil Prices Plummet Following Iran War Cease Fire. The temporary ceasefire between the US and Iran led to a surge in stocks, with the S&P 500, Dow Jones Industrial Average, and Nasdaq composite all rising. The decline in oil prices also boosted airline and travel stocks, while Treasury yields fell as hopes for lower interest rates increased. The market's optimism was tempered by concerns about the ceasefire's fragility and potential disruptions to shipping through the Strait of Hormuz.\n\nThe macro transmission mechanism is that a decrease in oil prices can lead to increased consumer spending and economic growth, which can boost equities and reduce inflationary pressures, making it more likely for the Federal Reserve to cut interest rates.", "metadata": {"topic": "macro_yields_dollar", "title": "Stocks Rally as Oil Prices Plummet Following Iran War Cease Fire", "original_title": "Stocks Close The Day Higher As Oil Prices Plummet Over Iran War Cease Fire | NewsRadio WKCY", "publish_date": "2026-04-09T01:21:11Z", "publish_timestamp": 1775697671, "source": "newsradiowkcy.iheart.com", "url": "https://newsradiowkcy.iheart.com/content/2026-04-08-stocks-close-the-day-higher-as-oil-prices-plummet-over-iran-war-cease-fire/", "entities": ["United Airlines", "Carnival cruise lines", "Delta Air Lines", "President Donald Trump", "Iran's foreign minister"], "impacted_assets": ["Equities", "Gold", "Oil"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "a6ea31b5-c35a-54e7-b593-feb4f8d7e6cc", "text": "Stocks Rally as Oil Prices Plummet Following Iran War Ceasefire. The temporary ceasefire between the US and Iran led to a surge in global equities, with the S&P 500, Dow Jones, and Nasdaq composite all rising significantly. The decline in oil prices also boosted airline and travel stocks, while Treasury yields fell as hopes for lower interest rates increased. However, analysts cautioned that the ceasefire remains fragile, and market optimism faded somewhat later in the day.\n\nThe macro transmission mechanism is as follows: a decrease in oil prices reduces inflationary pressures, which could lead to a more accommodative monetary policy from the Federal Reserve, potentially resulting in lower interest rates. This, in turn, can boost equities and other risk assets, such as gold. The ceasefire also reduces geopolitical tensions, which can positively impact market sentiment and investor confidence.", "metadata": {"topic": "macro_yields_dollar", "title": "Stocks Rally as Oil Prices Plummet Following Iran War Ceasefire", "original_title": "Stocks Close The Day Higher As Oil Prices Plummet Over Iran War Cease Fire", "publish_date": "2026-04-09T01:21:11Z", "publish_timestamp": 1775697671, "source": "whp580.iheart.com", "url": "https://whp580.iheart.com/content/2026-04-08-stocks-close-the-day-higher-as-oil-prices-plummet-over-iran-war-cease-fire/", "entities": ["United States", "Iran", "President Donald Trump", "United Airlines", "Carnival cruise lines", "Delta Air Lines"], "impacted_assets": ["Equities", "Gold", "Oil"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "9da3262c-b5fa-541c-964d-06cbc2042a3a", "text": "Wall Street Closes Higher, Relieved by Iran Ceasefire Announcement. Wall Street closed higher as investors welcomed the announcement of a 14-day ceasefire between the US and Iran. The news contributed to a decrease in oil prices, which in turn reduced concerns about recession, inflation, and growth. This led to optimism on the equity markets, with sectors such as energy, airlines, and logistics companies performing well. Cryptocurrency-related stocks also benefited from the increased appetite for risk.", "metadata": {"topic": "macro_yields_dollar", "title": "Wall Street Closes Higher, Relieved by Iran Ceasefire Announcement", "original_title": "Wall Street clôture en nette hausse , soulagée par le cessez - le - feu en Iran", "publish_date": "2026-04-09T01:21:11Z", "publish_timestamp": 1775697671, "source": "lecourrier.vn", "url": "https://lecourrier.vn/wall-street-cloture-en-nette-hausse-soulagee-par-le-cessez-le-feu-en-iran/1345035.html", "entities": ["United States", "Iran", "Edward Jones", "Interactive Brokers", "Chevron", "ConocoPhillips", "EOG Resources", "ExxonMobil", "Delta Air Lines", "American Airlines", "Alaska Air Group", "Carnival", "Royal Caribbean", "FedEx", "UPS", "Robinhood", "Riot Platforms"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Neutral: The ceasefire announcement has a calming effect on the market, reducing volatility.", "llm_tone_score": 2}} +{"id": "369d1304-9d6b-5291-83f2-02f4990faaf5", "text": "Rupee Expected to Stabilize at 92-93 Level Against USD. The article quotes the EAC-PM chairman as saying that the Indian Rupee is expected to stabilize at 92-93 levels against the USD, driven by improvements in macroeconomic fundamentals and a reduction in global uncertainties. He also expressed optimism about India's economic growth prospects, citing its resilience and fiscal space to absorb external shocks. The article highlights structural factors such as debt-to-GDP ratio improvements, ongoing reforms, and technological advancements as supportive of private sector investment and higher growth.\n\nThe stabilization of the Rupee is expected to have a positive impact on Indian equities and gold prices, as it reduces uncertainty and increases investor confidence in the economy.", "metadata": {"topic": "macro_yields_dollar", "title": "Rupee Expected to Stabilize at 92-93 Level Against USD", "original_title": "Rupee likely to stabilise at 92 - 93 level : EAC - PM chairman", "publish_date": "2026-04-09T01:21:11Z", "publish_timestamp": 1775697671, "source": "dailyexcelsior.com", "url": "https://www.dailyexcelsior.com/rupee-likely-to-stabilise-at-92-93-level-eac-pm-chairman/", "entities": ["S Mahendra Dev", "Economic Advisory Council to the Prime Minister (EAC-PM)", "Reserve Bank of India (RBI)"], "impacted_assets": ["Equities", "Gold"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "6cadf122-0f0b-51cd-9fd8-d998ce4b86fd", "text": "Stocks Rally as Oil Prices Plummet Following Iran War Ceasefire. The temporary ceasefire between the US and Iran has led to a surge in global equities, with the S&P 500, Dow Jones Industrial Average, and Nasdaq composite all rising significantly. The decline in oil prices has also had a positive impact on airline and travel stocks, while Treasury yields have fallen as hopes of lower interest rates later in the year increase. However, analysts caution that the ceasefire remains fragile, and any further escalation could negatively impact market sentiment.\n\nThe macro transmission mechanism is as follows: A decrease in oil prices reduces inflationary pressures, which can lead to a more accommodative monetary policy from central banks like the Federal Reserve. This, in turn, can boost equities and other risk assets, while also reducing the appeal of safe-haven assets like gold.", "metadata": {"topic": "macro_yields_dollar", "title": "Stocks Rally as Oil Prices Plummet Following Iran War Ceasefire", "original_title": "Stocks Close The Day Higher As Oil Prices Plummet Over Iran War Cease Fire", "publish_date": "2026-04-09T01:21:11Z", "publish_timestamp": 1775697671, "source": "1019bigwaax.iheart.com", "url": "https://1019bigwaax.iheart.com/content/2026-04-08-stocks-close-the-day-higher-as-oil-prices-plummet-over-iran-war-cease-fire/", "entities": ["United States", "Iran", "President Donald Trump", "United Airlines", "Carnival cruise lines", "Delta Air Lines"], "impacted_assets": ["Equities", "Gold", "Oil"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "ee33f9a6-575d-5c99-a12a-2bb5e9204f55", "text": "Oil Prices Plunge Below $95 as Global Markets Rally Following Ceasefire with Iran. The ceasefire between Iran and the global community has led to a surge in global markets, with the Dow Jones Industrial Average rising by 1,300 points. This development has resulted in a decrease in oil prices, which have fallen below $95 per barrel. The macro transmission mechanism is that the improved geopolitical situation has reduced uncertainty, leading to increased risk appetite and a subsequent rally in equities.", "metadata": {"topic": "macro_yields_dollar", "title": "Oil Prices Plunge Below $95 as Global Markets Rally Following Ceasefire with Iran", "original_title": "Oil plunges below $95 as the Dow surges 1 , 300 in a worldwide rally following a ceasefire with Iran", "publish_date": "2026-04-09T01:21:11Z", "publish_timestamp": 1775697671, "source": "santamariatimes.com", "url": "https://santamariatimes.com/ap/business/oil-plunges-below-95-as-the-dow-surges-1-300-in-a-worldwide-rally-following/article_a54e11c8-bfe7-4866-8e05-38da805d67ae.html", "entities": ["Iran", "Dow Jones Industrial Average"], "impacted_assets": ["Equities", "Gold", "Oil"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "15f1b2a9-51fd-5069-b6f4-25eea5fe8912", "text": "Suze Orman's Advice on Using Tax Refunds to Build Financial Security. Suze Orman advises using tax refunds strategically to build financial security. She recommends building emergency reserves, paying off high-interest credit card debt, investing in maintenance spending for cars and homes, contributing to retirement accounts, and avoiding unnecessary expenses. This advice is aimed at helping individuals strengthen their financial position rather than simply spending the refund.\n\nNote: As this article does not have a direct impact on gold or silver prices, the tone score is neutral. The advice provided by Suze Orman is general financial guidance that may indirectly affect consumer spending and savings habits, but it does not have a significant macro transmission mechanism to influence precious metals markets.", "metadata": {"topic": "macro_yields_dollar", "title": "Suze Orman's Advice on Using Tax Refunds to Build Financial Security", "original_title": "Suze Orman : 6 Best Ways To Use Tax Refund", "publish_date": "2026-04-09T01:21:11Z", "publish_timestamp": 1775697671, "source": "gobankingrates.com", "url": "https://www.gobankingrates.com/taxes/refunds/suze-orman-best-ways-use-large-tax-refund-to-become-financially-secure/", "entities": ["Suze Orman", "Congress", "economists"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-10/qdrant_asset_metals_derivatives_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-10/qdrant_asset_metals_derivatives_processed.jsonl new file mode 100644 index 0000000..1321fca --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-10/qdrant_asset_metals_derivatives_processed.jsonl @@ -0,0 +1,3 @@ +{"id": "08241189-e8f3-59fc-a636-57188345649e", "text": "March CPI Surges to 3.3% as Iran War Drives Energy Costs Higher; What It Means for Investors. The March CPI report showed a 3.3% annual increase, driven primarily by energy costs due to the Iran war. This has led to a surge in oil prices and inflationary pressures. While headline inflation is high, core inflation remains relatively calm. The market reaction was positive, with equities rising on the news. The Federal Reserve is unlikely to make any significant moves in response to this data, as both headline and core inflation are within expected ranges. Energy stocks, gold, and commodity-linked assets have been beneficiaries of the war-driven volatility and are likely to continue to perform well. The focus now shifts to earnings reports from major banks next week.", "metadata": {"topic": "asset_metals_derivatives", "title": "March CPI Surges to 3.3% as Iran War Drives Energy Costs Higher; What It Means for Investors", "original_title": "March CPI Surges to 3 . 3 % as Iran War Drives Energy Costs Higher ; What It Means for Investors", "publish_date": "2026-04-10T19:51:20Z", "publish_timestamp": 1775850680, "source": "investorideas.com", "url": "https://www.investorideas.com/news/2026/main/04101-cpi-inflation-energy-surge-market-impact.asp", "entities": ["Federal Reserve", "Bureau of Labor Statistics", "deVere", "JPMorgan", "Wells Fargo", "Citigroup", "Goldman Sachs", "BlackRock"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "30a0c48f-ed77-5b6e-a9da-1ba419968047", "text": "Major airlines cut flights and hike fares as fuel costs rise due to Middle East conflict. The ongoing conflict in the Middle East has led to a surge in fuel prices, prompting major airlines to cut flights and increase fares. This development may contribute to inflationary pressures, which could benefit gold and silver prices. The impact on oil prices is uncertain, but rising costs may lead to increased volatility.", "metadata": {"topic": "asset_metals_derivatives", "title": "Major airlines cut flights and hike fares as fuel costs rise due to Middle East conflict", "original_title": "Major airlines cut flights and hike fares as fuel costs rise", "publish_date": "2026-04-10T19:51:20Z", "publish_timestamp": 1775850680, "source": "penarthtimes.co.uk", "url": "https://www.penarthtimes.co.uk/news/26009421.major-airlines-cut-flights-hike-fares-fuel-costs-rise/", "entities": ["US", "Israel", "Iran", "Skybus", "Ryanair", "Air India", "Air New Zealand", "Delta Airlines", "Blue Islands Limited", "Air Kilroe Limited t/a Eastern Airways", "Play Airlines", "Legend Airlines"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Increase", "llm_tone_score": 2}} +{"id": "92826a0d-8fe9-585f-b6b5-f26305b2542a", "text": "Utilities Seek Federal Pause on Grid Bidding Amid AI-Driven Power Demand. A coalition of utilities is seeking federal intervention to pause competitive bidding for transmission projects needed to meet the vast energy needs of the data center boom. The request aims to address \"bureaucratic red tape\" and potential delays in project timelines. Ratepayer advocacy groups are pushing back, citing concerns about higher electricity bills. This development has no direct impact on gold or silver prices but may indirectly influence market sentiment through its implications for the broader economy.\n\nNote: As there is no explicit macro-financial driver mentioned in the article, I assigned a tone score of 0 (Neutral). The event's potential impact on the broader economy and market sentiment is indirect and not significant enough to warrant a specific tone score.", "metadata": {"topic": "asset_metals_derivatives", "title": "Utilities Seek Federal Pause on Grid Bidding Amid AI-Driven Power Demand", "original_title": "Utilities seek federal pause on grid bidding amid AI - driven power demand - WRCO", "publish_date": "2026-04-10T19:51:20Z", "publish_timestamp": 1775850680, "source": "wrco.com", "url": "https://wrco.com/news/2026/04/10/utilities-seek-federal-pause-on-grid-bidding-amid-ai-driven-power-demand", "entities": ["Xcel Energy", "Northern States Power Company-Wisconsin", "American Transmission Company (ATC)", "Wisconsin Citizens Utility Board", "Midcontinent Independent System Operator (MISO)", "Meta"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 0}} diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-10/qdrant_macro_central_banks_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-10/qdrant_macro_central_banks_processed.jsonl new file mode 100644 index 0000000..df01bb9 --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-10/qdrant_macro_central_banks_processed.jsonl @@ -0,0 +1,8 @@ +{"id": "65919d40-9bb8-597e-b7c3-df8f64b1b702", "text": "Inflation Surges in March Amid Oil Shock Triggered by U.S.-Israeli War with Iran. The article reports a surge in inflation in March due to an oil shock triggered by the U.S.-Israeli war with Iran. This development could complicate interest rate policy at the Federal Reserve, which may be reluctant to lower borrowing costs as inflation climbs. The rapid acceleration of price increases could pose difficulty for the Fed, particularly if it decides to raise interest rates to combat inflation.", "metadata": {"topic": "macro_central_banks", "title": "Inflation Surges in March Amid Oil Shock Triggered by U.S.-Israeli War with Iran", "original_title": "Business - HITS FM", "publish_date": "2026-04-10T19:48:06Z", "publish_timestamp": 1775850486, "source": "hitsfm.net", "url": "https://hitsfm.net/business/9a906e8ed2f1be1191aa6d7dc2574e4c", "entities": ["United States", "Israel", "Iran", "Federal Reserve Chairman Jerome Powell"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Increase", "llm_tone_score": 2}} +{"id": "22a75fef-140e-5f11-892f-644349c7b3ca", "text": "Inflation Surges to Highest Level in Nearly Two Years as Energy Costs Spike. The surge in inflation to its highest level in nearly two years, driven by energy costs and the US-Iran conflict, is likely to boost gold and silver prices. The Federal Reserve may be cautious about cutting interest rates due to rising core inflation, which could support precious metals. The uncertainty surrounding the war's impact on the job market and economy also contributes to a bullish tone for gold and silver.\n\nNote: The tone score of +2 reflects the moderate increase in inflation, which is likely to have a positive impact on gold and silver prices, but not strong enough to trigger a significant rate cut by the Federal Reserve.", "metadata": {"topic": "macro_central_banks", "title": "Inflation Surges to Highest Level in Nearly Two Years as Energy Costs Spike", "original_title": "Inflation surges to highest level in nearly 2 years as energy costs spike", "publish_date": "2026-04-10T19:48:06Z", "publish_timestamp": 1775850486, "source": "kacu.org", "url": "https://www.kacu.org/2026-04-10/inflation-surges-to-highest-level-in-nearly-2-years-as-energy-costs-spike", "entities": ["Austan Goolsbee", "Federal Reserve Bank of Chicago", "New York Fed"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Increase", "llm_tone_score": 2}} +{"id": "4ea0158e-e17d-50d7-9f42-c3be4f118d6b", "text": "Trump Summons Banking Chiefs for Closed-Door Meeting on AI Model. The meeting between President Trump, Treasury Secretary Scott Bessent, Federal Reserve Chair Jerome Powell, and top banking executives is focused on an artificial intelligence model called Mythos. The AI model has identified thousands of high-severity vulnerabilities in major operating systems and web browsers, raising concerns about national defense firewalls. While this event may not have a direct impact on gold or silver prices, it could contribute to market uncertainty and potentially influence interest rates or currency markets, which may indirectly affect precious metals.", "metadata": {"topic": "macro_central_banks", "title": "Trump Summons Banking Chiefs for Closed-Door Meeting on AI Model", "original_title": "Trump summons banking chiefs for a closed - door meeting about an AI model : report", "publish_date": "2026-04-10T19:48:06Z", "publish_timestamp": 1775850486, "source": "wgme.com", "url": "https://wgme.com/news/nation-world/trump-summons-banking-chiefs-for-a-closed-door-meeting-about-an-ai-model-report-jerome-powell-scott-bessent", "entities": ["Donald Trump", "Scott Bessent", "Jerome Powell", "Ted Pick", "David Solomon", "Jane Fraser"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "b72097d8-e01d-5d87-ab77-7979dbc7d003", "text": "Why did Trump's government go back to attacking the Pix (and what can the US do about it)?. The US government has reopened an investigation into Brazil's Pix payment system, citing concerns over competitive unfairness. This development may lead to retaliatory measures from the US, such as tariffs or trade restrictions, which could negatively impact gold and silver prices. The tone is bearish due to the potential for increased market uncertainty and a possible weakening of the USD.\n\nThe macro transmission mechanism is as follows: an investigation into Pix may lead to retaliatory measures from the US, which could weaken the USD and increase market volatility, ultimately impacting gold and silver prices.", "metadata": {"topic": "macro_central_banks", "title": "Why did Trump's government go back to attacking the Pix (and what can the US do about it)?", "original_title": "Por que governo Trump voltou a atacar o Pix ( e o que EUA podem fazer contra ele )? ", "publish_date": "2026-04-10T19:48:06Z", "publish_timestamp": 1775850486, "source": "em.com.br", "url": "http://www.em.com.br/economia/2026/04/7394973-por-que-governo-trump-voltou-a-atacar-o-pix-e-o-que-eua-podem-fazer-contra-ele.html", "entities": ["President Luiz Inácio Lula da Silva", "President Gustavo Petro", "Office of the United States Trade Representative (USTR)", "Banco Central do Brasil"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Decrease", "llm_tone_score": -2}} +{"id": "ea4a0790-7887-560b-b61f-0732d27e0a1b", "text": "Soaring Gas Prices Lead to Biggest Monthly Inflation Spike in Four Years in March. The article reports a significant increase in inflation due to soaring gas prices, which is expected to impact the Federal Reserve's monetary policy decisions. This development may lead to a rate hike or delay in rate cuts, potentially benefiting gold and silver prices. The macro transmission mechanism involves higher energy costs affecting consumer spending and economic growth, which could slow down the economy and increase demand for safe-haven assets like precious metals.", "metadata": {"topic": "macro_central_banks", "title": "Soaring Gas Prices Lead to Biggest Monthly Inflation Spike in Four Years in March", "original_title": "Soaring gas prices leads to biggest monthly inflation spike in four years in March", "publish_date": "2026-04-10T19:48:06Z", "publish_timestamp": 1775850486, "source": "1037qcountry.com", "url": "https://1037qcountry.com/news/030030-soaring-gas-prices-leads-to-biggest-monthly-inflation-spike-in-four-years-in-march/", "entities": ["Federal Reserve", "Iran", "White House", "Labor Department", "motor club AAA", "UBS"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Increase", "llm_tone_score": 2}} +{"id": "4a3d7ef5-8028-5979-8dba-c3c17e3c833e", "text": "Mexican Peso Strengthens to its Best Week in Over a Year as Dollar Falls. The Mexican peso is strengthening against the US dollar, with a 3.17% gain this week, driven by a weakening dollar and optimism in global markets. This trend is supported by a favorable international environment, including reduced tensions in the Middle East and potential diplomatic progress. The peso's appreciation is also influenced by inflation expectations in the US, which are driving interest rate decisions at the Federal Reserve.\n\nNote: The tone score of +2 reflects the bullish sentiment towards the Mexican peso, driven by its strengthening trend against the dollar, but with a neutral volatility implication as market fear/VIX remains stable.", "metadata": {"topic": "macro_central_banks", "title": "Mexican Peso Strengthens to its Best Week in Over a Year as Dollar Falls", "original_title": "Precio del dólar hoy viernes 10 de abril : peso mexicano perfila su mejor semana en un año", "publish_date": "2026-04-10T19:48:06Z", "publish_timestamp": 1775850486, "source": "elsiglodetorreon.com.mx", "url": "https://www.elsiglodetorreon.com.mx/noticia/2026/precio-del-dolar-hoy-viernes-10-de-abril-peso-mexicano-perfila-su-mejor-semana-en-un-ano.html", "entities": ["Mexican Peso", "US Dollar", "Bloomberg", "Banco Base", "Reserva Federal"], "impacted_assets": ["Gold", "Silver", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "ff6c4ccb-0384-5b7f-bb30-9764e4784ece", "text": "The Comeback of Swap Futures - Risk.net. A surge in directional block trades in interest rate swap futures contracts has been observed, with a total notional value of $2.5 billion printed in March. This increase in activity suggests growing market participation and potential for increased volatility in the interest rate derivatives space. The macro transmission mechanism is likely driven by changes in market expectations around monetary policy and economic growth, which may impact gold and silver prices through their inverse correlation with interest rates.", "metadata": {"topic": "macro_central_banks", "title": "The Comeback of Swap Futures - Risk.net", "original_title": "The swap futures comeback - Risk . net", "publish_date": "2026-04-10T19:48:06Z", "publish_timestamp": 1775850486, "source": "risk.net", "url": "https://www.risk.net/markets/7963346/the-swap-futures-comeback", "entities": ["None explicitly mentioned"], "impacted_assets": ["Gold", "Silver", "Interest Rate Derivatives"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "6dd1d9f9-5bdc-5e6b-aae1-cda390659f91", "text": "Oil Shock Triggers Inflation Surge Amid Middle East Conflict. The ongoing Middle East conflict has triggered a significant oil shock, leading to a surge in inflation and prices. This development could complicate interest rate policy at the Federal Reserve, which may be reluctant to lower borrowing costs as inflation climbs. The rapid acceleration of price increases could pose difficulty for the Fed, particularly if it decides to raise interest rates to combat inflation.", "metadata": {"topic": "macro_central_banks", "title": "Oil Shock Triggers Inflation Surge Amid Middle East Conflict", "original_title": "Prices surged in March after oil shock set off by Iran war", "publish_date": "2026-04-10T19:48:06Z", "publish_timestamp": 1775850486, "source": "abc30.com", "url": "https://abc30.com/post/prices-surged-march-oil-shock-set-off-iran-war/18865879/", "entities": ["Iran", "United States", "Israel", "Jerome Powell", "Federal Reserve"], "impacted_assets": ["Gold", "Silver", "USD", "Crude Oil"], "volatility_implication": "Increase", "llm_tone_score": 2}} diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-10/qdrant_macro_geopolitics_risk_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-10/qdrant_macro_geopolitics_risk_processed.jsonl new file mode 100644 index 0000000..4b0f0a1 --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-10/qdrant_macro_geopolitics_risk_processed.jsonl @@ -0,0 +1,7 @@ +{"id": "953bd332-c506-5eaa-b648-5cef0e82ed24", "text": "Vice President Challenges President on Aid Amid 2026 Energy Crisis. Vice President Sara Duterte questioned President Marcos' efforts to assist Filipinos affected by the ongoing energy crisis. She suggested that fuel prices could ease if tensions in the Middle East subside or alternative fuel sources are secured. The government has implemented measures to reduce energy consumption, and a State of National Energy Emergency has been declared. This development is likely to have a neutral impact on gold and silver prices, but may lead to some volatility in oil markets.\n\nNote: The tone score is +1 because while the Vice President's comments may create some uncertainty, they do not directly affect the macroeconomic environment or the central bank's monetary policy stance, which are key drivers of gold and silver prices.", "metadata": {"topic": "macro_geopolitics_risk", "title": "Vice President Challenges President on Aid Amid 2026 Energy Crisis", "original_title": "VP Sara Challenges Marcos on Aid Amid 2026 Energy Crisis", "publish_date": "2026-04-10T19:50:08Z", "publish_timestamp": 1775850608, "source": "sunstar.com.ph", "url": "https://www.sunstar.com.ph/davao/vp-sara-questions-pbbm-on-aid-amid-energy-crisis", "entities": ["Sara Duterte", "Ferdinand \"Bongbong\" Marcos Jr."], "impacted_assets": ["Equities", "Gold", "Oil"], "volatility_implication": "Neutral", "llm_tone_score": 1}} +{"id": "65919d40-9bb8-597e-b7c3-df8f64b1b702", "text": "Inflation Surges in March Amid Oil Shock Triggered by U.S.-Israeli War with Iran. The article reports a surge in inflation in March due to an oil shock triggered by the U.S.-Israeli war with Iran. This development could pose difficulties for the Federal Reserve as it weighs its interest rate policy. The rapid acceleration of price increases may lead to higher borrowing costs, which could impact gold and silver prices positively.", "metadata": {"topic": "macro_geopolitics_risk", "title": "Inflation Surges in March Amid Oil Shock Triggered by U.S.-Israeli War with Iran", "original_title": "Business - HITS FM", "publish_date": "2026-04-10T19:50:08Z", "publish_timestamp": 1775850608, "source": "hitsfm.net", "url": "https://hitsfm.net/business/9a906e8ed2f1be1191aa6d7dc2574e4c", "entities": ["United States", "Israel", "Iran", "Jerome Powell", "Federal Reserve"], "impacted_assets": ["Gold", "Silver", "USD", "Equities"], "volatility_implication": "Increase", "llm_tone_score": 2}} +{"id": "a94553db-aff9-5b82-ba8d-fa5ac28e600b", "text": "Trump Reveals Timeline for Iran-US Talks Outcome: US Warships Being Rearmed with Best Weapons. The article reports that US President Donald Trump has revealed a 24-hour timeline for the outcome of talks between the US and Iran. If negotiations fail, Trump warns that the US will rearm its warships with the best weapons ever made, implying a potential escalation in tensions. This development increases market fear and volatility, particularly in gold and oil markets, as investors anticipate a possible conflict scenario.\n\nNote: The tone score is bearish due to the escalating rhetoric and implied threat of military action, which could lead to increased uncertainty and market volatility.", "metadata": {"topic": "macro_geopolitics_risk", "title": "Trump Reveals Timeline for Iran-US Talks Outcome: US Warships Being Rearmed with Best Weapons", "original_title": " USKORO ĆEMO SAZNATI Tramp otkrio kad će biti poznato da li će pregovori SAD i Irana biti uspešni : Mi punimo brodove najboljim oružjem", "publish_date": "2026-04-10T19:50:08Z", "publish_timestamp": 1775850608, "source": "novosti.rs", "url": "https://www.novosti.rs/planeta/svet/1596010/uskoro-cemo-saznati-tramp-otkrio-kad-biti-poznato-pregovori-sad-irana-biti-uspesni-punimo-brodove-najboljim-oruzjem", "entities": ["Donald Trump", "Pakistan", "Iran", "United States"], "impacted_assets": ["Gold", "Oil", "USD"], "volatility_implication": "Increase", "llm_tone_score": -3}} +{"id": "0f382490-5526-5ad3-965b-8d85e1bb6c2c", "text": "China Sees Solid Rise in Cross-Border Travel in Q1, with Foreign National Trips Surging. China's cross-border travel growth is driven by relaxed entry policies and streamlined customs procedures. The surge in foreign national trips is a positive sign for the country's tourism industry, which saw over 150 million inbound tourist visits in 2025, with spending exceeding $130 billion. This trend may lead to increased demand for gold and silver as investors seek safe-haven assets amid growing economic activity.\n\nThe macro transmission mechanism is that increased consumer spending and tourism can boost economic growth, leading to higher demand for precious metals like gold and silver.", "metadata": {"topic": "macro_geopolitics_risk", "title": "China Sees Solid Rise in Cross-Border Travel in Q1, with Foreign National Trips Surging", "original_title": "China sees solid rise in cross - border travel in Q1 , with foreign national trips surging", "publish_date": "2026-04-10T19:50:08Z", "publish_timestamp": 1775850608, "source": "shanghainews.net", "url": "http://www.shanghainews.net/news/278975895/china-sees-solid-rise-in-cross-border-travel-in-q1-with-foreign-national-trips-surging", "entities": ["China", "Xinhua", "National Immigration Administration", "Hong Kong", "Macao", "Taiwan", "Fujian province", "Hainan province", "Ministry of Culture and Tourism"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "cce40e36-706a-5adf-bfba-2bcffb1e03ba", "text": "Club Med Opens New Resort in Sabah, Malaysia!. The opening of Club Med's new resort in Sabah, Malaysia, is expected to boost tourism in the region. The resort features a unique blend of natural and cultural experiences, including red forest exploration and wildlife observation. This development may have a neutral impact on gold and silver prices, as it does not directly affect macroeconomic drivers or global financial markets.\n\nNote: As there are no explicit mentions of macroeconomic drivers, interest rates, inflation, or geopolitical conflicts in the article, I assigned a tone score of 0 (Neutral).", "metadata": {"topic": "macro_geopolitics_risk", "title": "Club Med Opens New Resort in Sabah, Malaysia!", "original_title": "亞洲最新隱奢海島誕生 ! Club Med沙巴度假村開訂 4天3夜2萬起全包 | 流行消費 | 生活", "publish_date": "2026-04-10T19:50:08Z", "publish_timestamp": 1775850608, "source": "udn.com", "url": "https://udn.com/news/story/7270/9433920", "entities": ["Club Med", "Sabah", "Malaysia", "Kuala Penyu", "Amazon"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "fa744fb4-9367-5506-93fc-0ef864e84f13", "text": "Germany Delivers Five Armored Medical Vehicles to Ukrainian National Guard. The German government has delivered five armored medical vehicles, known as MEDIGUARD, to the Ukrainian National Guard. This is part of a larger agreement funded by Germany and marks an increase in military aid to Ukraine. The new batch of vehicles includes anti-drone nets for enhanced protection. While this news may not have a direct impact on Gold/Silver prices, it could contribute to market sentiment and potentially influence investor decisions.\n\nNote: As the tone score is 0 (Neutral), this event is unlikely to have a significant impact on Gold/Silver prices. However, as part of a broader macroeconomic context, it may contribute to market sentiment and influence investor decisions.", "metadata": {"topic": "macro_geopolitics_risk", "title": "Germany Delivers Five Armored Medical Vehicles to Ukrainian National Guard", "original_title": "Συνεχίζουν να εξοπλίζουν τους εγκληματίες - Η Γερμανία παρέδωσε 5 τεθωρακισμένα οχήματα MEDIGUARD στην Εθνοφρουρά της Ουκρανίας", "publish_date": "2026-04-10T19:50:08Z", "publish_timestamp": 1775850608, "source": "bankingnews.gr", "url": "https://www.bankingnews.gr/diethni/articles/867952/synexizoun-na-eksoplizoun-tous-egklimaties-i-germania-paredose-5-tethorakismena-oximata-mediguard-stin-ethnofroura-tis-oukranias", "entities": ["German government", "Ukraine", "MEDIGUARD manufacturers (Ukrainian and German companies)"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "c44c3ee2-f0bf-5202-92d6-f1f49dc05481", "text": "Airports Warn of Systemic Jet Fuel Shortage if Strait of Hormuz Remains Closed. The potential shortage of jet fuel due to the closure of the Strait of Hormuz could lead to higher prices, which may benefit gold and silver prices. The increased cost of jet fuel could be passed on to passengers, leading to higher airfares, which may negatively impact equities and oil prices. The USD may strengthen as a safe-haven asset in response to the potential shortage.\n\nNote: The tone score is +2 because while the event has negative implications for airlines and air travel, it may have positive implications for gold and silver prices due to increased market uncertainty and risk aversion.", "metadata": {"topic": "macro_geopolitics_risk", "title": "Airports Warn of Systemic Jet Fuel Shortage if Strait of Hormuz Remains Closed", "original_title": "Airports warn of systemic jet fuel shortage if Strait of Hormuz stays closed", "publish_date": "2026-04-10T19:50:08Z", "publish_timestamp": 1775850608, "source": "cravenherald.co.uk", "url": "https://www.cravenherald.co.uk/news/national/26012377.airports-warn-systemic-jet-fuel-shortage-strait-hormuz-stays-closed/", "entities": ["European Commission", "Airports Council International (ACI)", "Ryanair", "Sir Keir Starmer", "US President Donald Trump"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Increase", "llm_tone_score": 2}} diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-10/qdrant_macro_yields_dollar_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-10/qdrant_macro_yields_dollar_processed.jsonl new file mode 100644 index 0000000..35bec1b --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-10/qdrant_macro_yields_dollar_processed.jsonl @@ -0,0 +1,5 @@ +{"id": "f4bc7cc6-83a1-5646-8499-ff457a94e7d0", "text": "Commodity Prices Update. The article reports on the current prices of various commodities, including gold, silver, oil, and agricultural products. Gold and silver prices have increased, while oil prices have decreased. Agricultural commodity prices are mixed, with some increasing and others decreasing. Energy commodity prices have also seen changes, with natural gas and heating oil prices declining. The overall tone is neutral, as there are no clear directional macro drivers impacting the commodities market.\n\nNote: As the article does not explicitly mention any entities or macroeconomic factors that would significantly impact gold and silver prices, I assigned a tone score of +1 (Neutral).", "metadata": {"topic": "macro_yields_dollar", "title": "Commodity Prices Update", "original_title": "Rohstoffpreise am Freitagabend", "publish_date": "2026-04-10T19:49:15Z", "publish_timestamp": 1775850555, "source": "finanzen.net", "url": "https://www.finanzen.net/nachricht/rohstoffe/rohstoffpreise-am-freitagabend-15604785", "entities": ["None explicitly mentioned"], "impacted_assets": ["Gold", "Silver", "Oil", "Agricultural commodities (e.g.", "Wheat", "Coffee", "Soybeans)", "Energy commodities (e.g.", "Natural Gas", "Heating Oil)"], "volatility_implication": "Neutral", "llm_tone_score": 1}} +{"id": "a52e4d37-76f8-5d6c-9706-cb71c0372f1c", "text": "Elderly Man Suffers Serious Injury While Driving Tractor in Agricultural Area. A 79-year-old man suffered serious injuries while driving a tractor in an agricultural area near Arcisate, Varese. The incident occurred when the driver lost control of the vehicle and crashed into a fence. Emergency services were quickly dispatched to the scene, and the patient was transported to a nearby hospital for treatment. This event is unlikely to have any significant impact on gold or silver prices, but may contribute to a neutral tone in the market.", "metadata": {"topic": "macro_yields_dollar", "title": "Elderly Man Suffers Serious Injury While Driving Tractor in Agricultural Area", "original_title": "Arcisate , ha un malore mentre guida il trattore nei campi : 79enne in condizioni disperate", "publish_date": "2026-04-10T19:49:15Z", "publish_timestamp": 1775850555, "source": "ilgiorno.it", "url": "https://www.ilgiorno.it/varese/cronaca/arcisate-malore--guida-trattore-79enne-condizioni-disperate-764da021", "entities": ["Arcisate", "Varese", "Velmaio", "Donizetti", "Croce Rossa Valceresio"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": -2}} +{"id": "52a00f1e-74d1-514a-87d6-7ee730f3541b", "text": "India's Domestic Investors Show Resilience Amid Global Uncertainty and Market Volatility. Despite global market volatility and geopolitical tensions, Indian domestic investors have shown surprising resilience by increasing their inflows into equity funds. This trend is notable as it contrasts with the outflows seen from foreign investors. The data suggests that local demand for stocks in India remains robust even during periods of extreme uncertainty. While this may not be enough to offset the ongoing outflows from abroad, it does indicate where the market's current support lies - within the domestic market.\n\nNote: The tone score is +2 as the article highlights a positive trend in Indian equity markets, which could potentially boost gold prices if investors seek safe-haven assets.", "metadata": {"topic": "macro_yields_dollar", "title": "India's Domestic Investors Show Resilience Amid Global Uncertainty and Market Volatility", "original_title": "Schwellenländer - Rallye voraus ?: Trotz Krieg : Warum Indiens Aktienfonds jetzt plötzlich Kapital anziehen | wallstreetONLINE", "publish_date": "2026-04-10T19:49:15Z", "publish_timestamp": 1775850555, "source": "wallstreet-online.de", "url": "https://www.wallstreet-online.de/nachricht/20716512-schwellenlaender-rallye-voraus-trotz-krieg-indiens-aktienfonds-kapital-anziehen", "entities": ["Association of Mutual Funds in India", "NSE Nifty 50 Index", "Bloomberg"], "impacted_assets": ["Equities", "Gold"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "ba889749-cbe5-53de-874e-b8f97314f556", "text": "OpenAI's Compute Advantage Over Anthropic Escalates the AI Competition. The article highlights the escalating competition between OpenAI and Anthropic in the AI space. OpenAI has increased its compute capacity to gain an advantage over its rival, while Anthropic is investing heavily to catch up. This intensifying competition may lead to increased volatility in technology stocks and potentially impact the USD.", "metadata": {"topic": "macro_yields_dollar", "title": "OpenAI's Compute Advantage Over Anthropic Escalates the AI Competition", "original_title": "Konter gegen Anthropic : KI - Wettrennen eskaliert : OpenAI setzt Rivalen unter Druck | wallstreetONLINE", "publish_date": "2026-04-10T19:49:15Z", "publish_timestamp": 1775850555, "source": "wallstreet-online.de", "url": "https://www.wallstreet-online.de/nachricht/20718345-konter-anthropic-ki-wettrennen-eskaliert-openai-rivalen-druck", "entities": ["OpenAI", "Anthropic", "Bloomberg", "Google", "Broadcom"], "impacted_assets": ["Equities", "Technology Stocks", "USD"], "volatility_implication": "Increase", "llm_tone_score": 2}} +{"id": "ce32d34f-3e5b-55ca-b032-627433045f44", "text": "Two workers killed in crane accident in Palermo. A tragic accident occurred in Palermo where two workers fell from a crane during a work intervention. The incident is under investigation by authorities. This event has no direct macro-financial implications and is unlikely to impact gold or silver prices.\n\nNote: As the article reports on a localized industrial accident with no apparent macroeconomic or financial connections, it does not have any significant bearing on the Gold/Silver options trading desk.", "metadata": {"topic": "macro_yields_dollar", "title": "Two workers killed in crane accident in Palermo", "original_title": "Palermo morti due operai caduti da una gru", "publish_date": "2026-04-10T19:49:15Z", "publish_timestamp": 1775850555, "source": "zazoom.it", "url": "https://www.zazoom.it/2026-04-10/palermo-morti-due-operai-caduti-da-una-gru/18980070/", "entities": ["Pierluigi Vito", "TV2000.it", "Adnkronos", "La Sicilia"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-12/qdrant_asset_metals_derivatives_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-12/qdrant_asset_metals_derivatives_processed.jsonl new file mode 100644 index 0000000..9b7009c --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-12/qdrant_asset_metals_derivatives_processed.jsonl @@ -0,0 +1,4 @@ +{"id": "193f29a1-7d1e-5ad9-97da-f142bb567ee9", "text": "The Rise of DeepSeek, a Chinese AI Company that's Quietly Taking on the Giants. DeepSeek, a Chinese AI company, has been quietly gaining traction in the industry by releasing high-quality models at affordable prices. Its V2 model was praised for its efficiency and effectiveness, while its R1 model demonstrated impressive performance in deep learning tasks. The company's open-source approach and willingness to collaborate with other developers have earned it recognition and admiration from the AI community. As DeepSeek prepares to release its V4 model, it is expected to further solidify its position as a major player in the industry.\n\nThe article highlights DeepSeek's remarkable journey, from being an underdog to becoming a force to be reckoned with in the AI space. The company's success can be attributed to its focus on developing high-quality models at affordable prices, as well as its willingness to collaborate with other developers and share knowledge openly. As DeepSeek continues to innovate and push boundaries, it is likely to remain a major player in the industry for years to come.\n\nThe article also touches on the topic of AI's potential impact on the job market, with some experts predicting that AI will create more jobs than it replaces. However, the author notes that this is still a topic of debate and that more research is needed to fully understand the implications of AI on the job market.\n\nOverall, the article provides a comprehensive overview of DeepSeek's rise to prominence in the AI industry, highlighting its achievements, challenges, and potential impact on the job market.", "metadata": {"topic": "asset_metals_derivatives", "title": "The Rise of DeepSeek, a Chinese AI Company that's Quietly Taking on the Giants", "original_title": "DeepSeek , 该卸下扫地僧的枷锁了", "publish_date": "2026-04-12T14:43:52Z", "publish_timestamp": 1776005032, "source": "tech.ifeng.com", "url": "https://tech.ifeng.com/c/8sGYfvCKmod", "entities": ["DeepSeek", "OpenAI", "Meta", "SemiAnalysis", "Alexander Wang"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "1381fed0-d03a-5e47-b513-c019f553fd5e", "text": "Major airlines cut flights and hike fares as fuel costs rise due to Middle East conflict. The ongoing conflict in the Middle East has led to a surge in fuel prices, prompting major airlines to cut flights and hike fares. This development may contribute to inflationary pressures, which could benefit Gold/Silver prices. The impact on USD is uncertain, but rising fuel costs may weaken the currency.", "metadata": {"topic": "asset_metals_derivatives", "title": "Major airlines cut flights and hike fares as fuel costs rise due to Middle East conflict", "original_title": "Major airlines cut flights and hike fares as fuel costs rise", "publish_date": "2026-04-12T14:43:52Z", "publish_timestamp": 1776005032, "source": "swindonadvertiser.co.uk", "url": "https://www.swindonadvertiser.co.uk/news/26014087.major-airlines-cut-flights-hike-fares-fuel-costs-rise/", "entities": ["US", "Israel", "Iran", "Skybus", "Ryanair", "Air India", "Air New Zealand", "Delta Airlines", "Blue Islands Limited", "Air Kilroe Limited t/a Eastern Airways", "Play Airlines", "Legend Airlines"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Increase (Rising fuel costs and potential supply chain disruptions may increase market fear/VIX)", "llm_tone_score": 2}} +{"id": "c5212f5a-37ca-50a2-b921-33367bcb9271", "text": "Gold Volatility Amid Geopolitical Crises: What History Tells Us. The article discusses the volatility of gold prices during times of geopolitical crises. Despite a sharp escalation in tensions, gold prices pulled back after briefly retesting record highs. Historical context suggests that gold can experience volatility during the early stages of major global disruptions, driven by factors such as liquidity needs, rising rates, and a stronger U.S. dollar. The article concludes that once conditions stabilize, central bank demand is likely to normalize, and the broader trend of reserve diversification remains intact.\n\nNote: The tone score is neutral because the article does not provide clear directional macro drivers that would significantly impact gold prices.", "metadata": {"topic": "asset_metals_derivatives", "title": "Gold Volatility Amid Geopolitical Crises: What History Tells Us", "original_title": "Gold Volatility Amid Geopolitical Crises : What History Tells Us", "publish_date": "2026-04-12T14:43:52Z", "publish_timestamp": 1776005032, "source": "etftrends.com", "url": "https://www.etftrends.com/tactical-allocation-content-hub/gold-volatility-amid-geopolitical-crises-history-tells/", "entities": ["United States", "Israel", "Iran", "Turkey", "Indonesia", "Guatemala", "Malaysia", "World Gold Council"], "impacted_assets": ["Equities", "Oil", "USD", "Gold"], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "60e0203d-8ef1-5fa7-ba95-812b553d3146", "text": "Risk of Power Struggle between Brussels and Rome's Palazzo. The article discusses the potential power struggle between Brussels and Rome's Palazzo regarding the European Media Freedom Act. This regulation could impact the governance of Rai, Italy's public broadcasting service. The situation is complex, with various stakeholders involved, including the Italian government, Commissione europea, Agcom, and internal factions within Rai. The article highlights the uncertainty surrounding the future of Rai's leadership and potential changes to its governance structure.", "metadata": {"topic": "asset_metals_derivatives", "title": "Risk of Power Struggle between Brussels and Rome's Palazzo", "original_title": "Rai , in onda il risiko dei poteri tra Bruxelles e Palazzo", "publish_date": "2026-04-12T14:43:52Z", "publish_timestamp": 1776005032, "source": "iltempo.it", "url": "https://www.iltempo.it/personaggi/2026/04/12/news/luigi-bisignani-rai-poteri-riforma-governance-lobby-logge-giampaolo-rossi-47241443/", "entities": ["European Media Freedom Act", "Rai", "Italian government", "Commissione europea", "Agcom", "Simona Agnes", "Gian Marco Chiocci", "Francesco Verderami", "Incoronata Boccia", "Nicola Rao", "Mario Orfeo", "Stefano Coletta"], "impacted_assets": ["Equities", "Gold", "EURUSD"], "volatility_implication": "Neutral", "llm_tone_score": 0}} diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-12/qdrant_asset_precious_metals_spot_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-12/qdrant_asset_precious_metals_spot_processed.jsonl new file mode 100644 index 0000000..fabb309 --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-12/qdrant_asset_precious_metals_spot_processed.jsonl @@ -0,0 +1,6 @@ +{"id": "b381c7f6-ecbb-5353-82a7-e86f87efd582", "text": "Mid-East Update from Islam Memiş: Gold and Housing Warning for Monday!. A ceasefire agreement in the Middle East has been reached, leading to a natural and expected price adjustment. As a result, gold and silver prices have stabilized, while other assets like euro, Bitcoin, and equities have rebounded. However, market participants are still cautious, expecting further volatility before a more stable trend emerges.\n\nNote: The tone score is +2 because the article suggests a positive development in the Middle East, which could lead to increased investor confidence and a subsequent rise in gold and silver prices.", "metadata": {"topic": "asset_precious_metals_spot", "title": "Mid-East Update from Islam Memiş: Gold and Housing Warning for Monday!", "original_title": "İslam Memiş ten altın ve konut için pazartesi uyarısı ! Artık zamanı geldi", "publish_date": "2026-04-12T14:42:33Z", "publish_timestamp": 1776004953, "source": "tgrthaber.com", "url": "https://www.tgrthaber.com/ekonomi/islam-memisten-altin-ve-konut-icin-pazartesi-uyarisi-artik-zamani-geldi-3294009", "entities": ["Islam Memiş", "Middle East"], "impacted_assets": ["Gold", "Silver", "Euro", "Bitcoin", "Equities"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "39ca5764-6907-5ec4-8c90-e95986db48d1", "text": "Gold Prices in Egypt: A Stable Outlook for the Weekend of April 12, 2026. The article reports on the current state of gold prices in Egypt, with no significant changes or market-moving events. The prices of different karat weights (24, 22, 21, and 18) are stable, with the Egyptian pound-gold price remaining high. The article also provides information on the current exchange rate between the US dollar and the Egyptian pound. This neutral tone suggests that there is no immediate impact on gold or silver prices.\n\nNote: As the article does not contain any market-moving news or events, the tone score is neutral, indicating no significant impact on gold or silver prices.", "metadata": {"topic": "asset_precious_metals_spot", "title": "Gold Prices in Egypt: A Stable Outlook for the Weekend of April 12, 2026", "original_title": "بكام جرام الذهب ؟.. أسعار الذهب اليوم الأحد 12 إبريل 2026", "publish_date": "2026-04-12T14:42:33Z", "publish_timestamp": 1776004953, "source": "dostor.org", "url": "https://www.dostor.org/5503201", "entities": ["Egyptian gold prices", "Central Bank of Egypt", "international markets"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "0784abc8-2142-5e70-bb98-aa8a3a3ebeab", "text": "Who are the Toesca protagonists: The key players in Sanhattan's moment. Toesca S.A. Administradora de Fondos de Inversión, a specialized alternative assets manager, has been making headlines with its recent acquisitions and partnerships. The company's founders, Alejandro Reyes and Carlos Saieh, have a background in the financial industry, having worked at BTG Pactual and Celfin before starting Toesca. With over $2.5 billion in investments and managing around $1.5 billion in 25 funds, Toesca is gaining prominence in the market. The company's growth and expansion plans may have implications for the broader financial markets, particularly in the equities and gold sectors.\n\nNote: As there are no explicit macro-financial or geopolitical drivers mentioned in the article, I assigned a tone score of 0 (Neutral).", "metadata": {"topic": "asset_precious_metals_spot", "title": "Who are the Toesca protagonists: The key players in Sanhattan's moment", "original_title": "Quiénes son los Toesca : Los protagonistas del momento en Sanhattan", "publish_date": "2026-04-12T14:42:33Z", "publish_timestamp": 1776004953, "source": "latercera.com", "url": "https://www.latercera.com/pulso/noticia/quienes-son-los-toesca-los-protagonistas-del-momento-en-sanhattan/", "entities": ["Alejandro Reyes", "Carlos Saieh", "BTG Pactual", "Celfin", "Aetna", "ING", "Moneda Asset Management", "Frontal Trust", "TC Latin America Partners", "Primus Capital", "Ameris Capital"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "193f29a1-7d1e-5ad9-97da-f142bb567ee9", "text": "The Rise of DeepSeek, a Chinese AI Company that's Quietly Taking on the Giants. DeepSeek, a Chinese AI company, has been quietly gaining traction in the industry by releasing high-quality models at affordable prices. Its V2 model was praised for its efficiency and effectiveness, while its R1 model demonstrated impressive performance in deep learning tasks. The company's open-source approach and willingness to collaborate with other developers have earned it recognition and admiration from the AI community. As DeepSeek prepares to release its V4 model, it is expected to further solidify its position as a major player in the industry.\n\nThe article highlights DeepSeek's remarkable journey, from being an underdog to becoming a force to be reckoned with in the AI space. The company's success can be attributed to its focus on developing high-quality models at affordable prices, as well as its willingness to collaborate with other developers and share knowledge openly. As DeepSeek continues to innovate and push boundaries, it is likely to remain a major player in the industry for years to come.\n\nThe article also touches on the topic of AI's potential impact on the job market, with some experts predicting that AI will create more jobs than it replaces. However, the author notes that this is still a topic of debate and that more research is needed to fully understand the implications of AI on the job market.\n\nOverall, the article provides a comprehensive overview of DeepSeek's rise to prominence in the AI industry, highlighting its achievements, challenges, and potential impact on the job market.", "metadata": {"topic": "asset_precious_metals_spot", "title": "The Rise of DeepSeek, a Chinese AI Company that's Quietly Taking on the Giants", "original_title": "DeepSeek , 该卸下扫地僧的枷锁了", "publish_date": "2026-04-12T14:42:33Z", "publish_timestamp": 1776004953, "source": "tech.ifeng.com", "url": "https://tech.ifeng.com/c/8sGYfvCKmod", "entities": ["DeepSeek", "OpenAI", "Meta", "SemiAnalysis", "Alexander Wang"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "70d77a50-0bf0-5149-8e26-83fcfde790f3", "text": "Liverpool band's historic song and its connection to the city's music scene.. This article is a nostalgic look at the Liverpool band The Real Thing and their hit song \"You To Me Are Everything\". The story highlights the group's journey to success, including their early struggles and eventual breakthrough with the help of manager Tony Hall. The article provides insight into the band's history and music style, but does not have any direct impact on gold or silver prices.", "metadata": {"topic": "asset_precious_metals_spot", "title": "Liverpool band's historic song and its connection to the city's music scene.", "original_title": "Liverpool band made history - but theyre not the Beatles | Celebrity News | Showbiz & TV", "publish_date": "2026-04-12T14:42:33Z", "publish_timestamp": 1776004953, "source": "express.co.uk", "url": "https://www.express.co.uk/celebrity-news/2192212/liverpool-boy-band-who-made-history", "entities": ["The Real Thing", "Chris Amoo", "Dave Smith", "Tony Hall", "Ken Gold", "Micky Denne", "David Essex", "Johnny Bristol"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "707cd706-8727-51dd-94b5-579f9bccc536", "text": "WisdomTree Silver 3x ETC: Holdings Break Out!. The silver market is heading towards its sixth supply deficit in a row, driven by growing industrial demand and shrinking physical inventories. This fundamental imbalance supports prices and fuels leveraged investment products like the WisdomTree Silver 3x ETC. The strong US dollar weakness and diplomatic tensions in Islamabad are also contributing to the upward momentum.", "metadata": {"topic": "asset_precious_metals_spot", "title": "WisdomTree Silver 3x ETC: Holdings Break Out!", "original_title": "WisdomTree Silver 3x ETC : Bestände brechen ein ! ", "publish_date": "2026-04-12T14:42:33Z", "publish_timestamp": 1776004953, "source": "boerse-express.com", "url": "https://www.boerse-express.com/news/articles/wisdomtree-silver-3x-etc-bestaende-brechen-ein-891172", "entities": ["WisdomTree", "Silver Institute", "COMEX"], "impacted_assets": ["Gold", "Equities", "USD"], "volatility_implication": "Increase", "llm_tone_score": 4}} diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-12/qdrant_macro_central_banks_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-12/qdrant_macro_central_banks_processed.jsonl new file mode 100644 index 0000000..235c494 --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-12/qdrant_macro_central_banks_processed.jsonl @@ -0,0 +1,7 @@ +{"id": "73edcea6-f323-5e99-9eb9-a58b3ecc5cab", "text": "Should I Invest in an IRA or Pay Off Debt First?. The article discusses the importance of paying off debt before investing in a Roth IRA. According to Dave Ramsey, the caller should focus on eliminating their $45,000 non-mortgage debt first, as every dollar going towards debt payments is a dollar that cannot be invested. This advice suggests a bearish tone for gold and silver prices, as it implies a more cautious approach to investing and potentially less demand for precious metals.\n\nNote: The article does not directly impact the macro-financial landscape or have any significant implications for gold and silver prices. However, the emphasis on debt repayment and delayed investment in a Roth IRA could contribute to a slightly bearish tone in the market.", "metadata": {"topic": "macro_central_banks", "title": "Should I Invest in an IRA or Pay Off Debt First?", "original_title": "I Have $45K in Debt . Should I Invest in an IRA or Pay the Bills First ? ", "publish_date": "2026-04-12T14:39:07Z", "publish_timestamp": 1776004747, "source": "finance.yahoo.com", "url": "https://finance.yahoo.com/markets/options/articles/45k-debt-invest-ira-pay-125503481.html", "entities": ["Dave Ramsey", "SoFi Crypto"], "impacted_assets": ["Equities", "Gold"], "volatility_implication": "Neutral", "llm_tone_score": -3}} +{"id": "8027d293-efc0-5106-9f0b-028b07476ff4", "text": "Workers can withdraw up to 20% of their FGTS to pay debts, says minister. The Brazilian government plans to allow workers with income up to 5 minimum salaries (R$8,105) to withdraw up to 20% of their FGTS (Fundo de Garantia por Tempo de Serviço) to pay off debts. This measure aims to reduce endividamento and will be part of a broader program that includes bank discounts and government guarantees for refinancing. The macro transmission mechanism is expected to have a positive impact on the economy, potentially boosting consumer spending and reducing debt burdens.\n\nNote: The tone score is +2 because while the news is generally positive for the economy, it may not have a significant direct impact on gold or silver prices. However, the potential reduction in endividamento could lead to increased consumer spending and economic growth, which could indirectly support precious metals.", "metadata": {"topic": "macro_central_banks", "title": "Workers can withdraw up to 20% of their FGTS to pay debts, says minister", "original_title": "Trabalhador poderá sacar até 20 % do FGTS para pagar dívidas , diz ministro | Tribuna Online", "publish_date": "2026-04-12T14:39:07Z", "publish_timestamp": 1776004747, "source": "tribunaonline.com.br", "url": "https://tribunaonline.com.br/economia/trabalhador-podera-sacar-ate-20-do-fgts-para-pagar-dividas-diz-ministro-298957", "entities": ["Dario Durigan", "Luiz Marinho", "Jair Bolsonaro", "Lula"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "d92ee245-ab8e-5514-bf47-53fb1301b3d9", "text": "Recommendations for Stocks to Watch on April 13th. The article discusses the outlook for two Vietnamese companies, Gelex (GEX) and Masan High-Tech Materials (MSR). For GEX, the report highlights the potential growth in its equipment and construction materials segments, driven by domestic policies and FDI inflows. MSR is expected to benefit from strong demand for its vonfram products due to global supply chain disruptions and increasing prices. The article recommends buying GEX and increasing exposure to MSR.\n\nNote: The tone score is +2 because the article presents a neutral-bullish outlook for both companies, with no major bearish factors mentioned.", "metadata": {"topic": "macro_central_banks", "title": "Recommendations for Stocks to Watch on April 13th", "original_title": "Cổ phiếu cần quan tâm ngày 13 / 4", "publish_date": "2026-04-12T14:39:07Z", "publish_timestamp": 1776004747, "source": "tinnhanhchungkhoan.vn", "url": "https://www.tinnhanhchungkhoan.vn/co-phieu-can-quan-tam-ngay-134-post388652.html", "entities": ["Gelex (GEX)", "Masan High-Tech Materials (MSR)", "Agriseco (AGR)"], "impacted_assets": ["Equities", "Gold"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "0737dd43-bfb6-540d-91d9-e313b720342f", "text": "Vietnamese authorities prosecute Bankland group for fraudulently obtaining over 500 billion VND from over 5,300 victims. A group of individuals, led by Vũ Đức Tĩnh, has been accused of fraudulently obtaining over 500 billion VND (approximately $22 million) from over 5,300 victims through a Ponzi scheme. The group established three companies, Bankland, Cawiho, and GBF, which were used to solicit investments with high interest rates. The authorities have concluded that the group's actions resulted in the loss of over 572 billion VND (approximately $25 million) for the victims. This event is likely to decrease market volatility as it highlights the risks associated with unregulated investment schemes.\n\nNote: The tone score is bearish due to the negative impact on investor confidence and the potential for increased regulatory scrutiny, which may lead to a decrease in gold prices.", "metadata": {"topic": "macro_central_banks", "title": "Vietnamese authorities prosecute Bankland group for fraudulently obtaining over 500 billion VND from over 5,300 victims", "original_title": "Truy tố nhóm điều hành Bankland lừa gần 500 tỷ đồng của hơn 5 . 300 bị hại", "publish_date": "2026-04-12T14:39:07Z", "publish_timestamp": 1776004747, "source": "baomoi.com", "url": "https://baomoi.com/truy-to-nhom-dieu-hanh-bankland-lua-gan-500-ty-dong-cua-hon-5-300-bi-hai-c54920488.epi", "entities": ["Vũ Đức Tĩnh", "Nguyễn Thị Thanh Vân", "Bankland", "Cawiho", "GBF"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Decrease", "llm_tone_score": -3}} +{"id": "547523a8-5e6f-5c4d-bad3-80a885a39bc0", "text": "The Conference Board Employment Trends Index Declined in March. The Conference Board's Employment Trends Index (ETI) declined in March, indicating a potential slowdown in job growth. This is reflected in the increase in consumers reporting \"jobs are hard to get\" and the rise in involuntary part-time workers. The decline was driven by negative contributions from five ETI components, including industrial production and real manufacturing and trade sales. This news may lead to increased market caution, potentially impacting equities and gold prices, while having a neutral impact on USD volatility.\n\nNote: As the tone score is -2, it suggests a bearish sentiment for Gold/Silver prices, but not extremely bearish.", "metadata": {"topic": "macro_central_banks", "title": "The Conference Board Employment Trends Index Declined in March", "original_title": "The Conference Board Employment Trends Index™ ( ETI ) Declined in March", "publish_date": "2026-04-12T14:39:07Z", "publish_timestamp": 1776004747, "source": "prnewswire.com", "url": "https://www.prnewswire.com/news-releases/the-conference-board-employment-trends-index-eti-declined-in-march-302734697.html", "entities": ["Mitchell Barnes", "Economist at The Conference Board", "U.S. Department of Labor", "National Federation of Independent Business Research Foundation", "Federal Reserve Board", "Bureau of Economic Analysis", "Bureau of Labor Statistics"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": -2}} +{"id": "643e42a6-e60b-5fda-9163-37016c4bdf71", "text": "Central Banks Flee to Gold for First Time in 30 Years. Central banks have shifted their reserves from dollars to gold for the first time in 30 years, with gold now making up 24% of global reserve holdings. This trend is driven by concerns over US dollar dominance and the potential for sanctions on foreign assets. The World Gold Council reports that central banks purchased a record 863 tons of gold in 2025, with Poland's central bank leading the way. This surge in demand has pushed gold prices up around 70% year-over-year, making it an attractive alternative to US dollars.\n\nThe macro transmission mechanism is as follows: Central banks' shift away from US dollars and towards gold reflects concerns over the stability of the global financial system. As a result, investors are seeking safe-haven assets like gold, driving up prices and increasing market volatility. This trend has implications for the value of the US dollar, which could weaken further if central banks continue to diversify their reserves away from USD-denominated assets.", "metadata": {"topic": "macro_central_banks", "title": "Central Banks Flee to Gold for First Time in 30 Years", "original_title": "30 yıldır ilk kez yaşanıyor : Merkez bankaları dolardan kaçıp altına sığındı", "publish_date": "2026-04-12T14:39:07Z", "publish_timestamp": 1776004747, "source": "sozcu.com.tr", "url": "https://www.sozcu.com.tr/30-yildir-ilk-kez-yasaniyor-merkez-bankalari-dolardan-kacip-altina-sigindi-p309549", "entities": ["World Gold Council", "central banks", "Russia", "Ukraine", "US Treasury"], "impacted_assets": ["Gold", "USD", "Equities"], "volatility_implication": "Increase", "llm_tone_score": 3}} +{"id": "b835eb59-ccdf-5a76-97c9-5128f6fb3b33", "text": "Will Low Interest Rates Trigger a Stock Market Boom?. The article discusses the potential impact of low interest rates and market expectations on Vietnam's stock market. Analysts from various firms expect the VN-Index to continue its upward trend, potentially reaching 1,800 points in the near future. However, they also caution that the market may experience short-term corrections due to geopolitical risks and uncertainty. The article highlights the potential benefits for sectors such as construction, real estate, and consumer goods, which are expected to benefit from government investment plans and a recovering economy.\n\nThe macro transmission mechanism is driven by the combination of low interest rates, improving market sentiment, and government stimulus packages, which are expected to boost economic growth and investor confidence. The article does not explicitly mention any specific drivers that would significantly impact gold or silver prices; therefore, I have assigned a neutral tone score.", "metadata": {"topic": "macro_central_banks", "title": "Will Low Interest Rates Trigger a Stock Market Boom?", "original_title": "Tiền rẻ có quay lại , chứng khoán sáng cửa bứt phá ? ", "publish_date": "2026-04-12T14:39:07Z", "publish_timestamp": 1776004747, "source": "tinnhanhchungkhoan.vn", "url": "https://www.tinnhanhchungkhoan.vn/tien-re-co-quay-lai-chung-khoan-sang-cua-but-pha-post388709.html", "entities": ["Vietinbank", "Yuanta Việt Nam", "OCBS", "CTS"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 2}} diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-12/qdrant_macro_geopolitics_risk_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-12/qdrant_macro_geopolitics_risk_processed.jsonl new file mode 100644 index 0000000..67b31e7 --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-12/qdrant_macro_geopolitics_risk_processed.jsonl @@ -0,0 +1,5 @@ +{"id": "35805df8-e8b6-5883-8b68-1f2c12f439f0", "text": "Russia and Ukraine Trade Blame over Orthodox Easter Ceasefire Violations. The ongoing conflict between Russia and Ukraine has led to a breakdown in the Orthodox Easter ceasefire. Both sides have accused each other of violating the truce, with reports of shelling, drone strikes, and small arms fire. This escalation in violence is likely to increase market fear and volatility, potentially driving up gold prices as investors seek safe-haven assets. The USD may also strengthen as risk aversion increases.", "metadata": {"topic": "macro_geopolitics_risk", "title": "Russia and Ukraine Trade Blame over Orthodox Easter Ceasefire Violations", "original_title": "Russia and Ukraine trade blame for violating Orthodox Easter ceasefire", "publish_date": "2026-04-12T14:41:52Z", "publish_timestamp": 1776004912, "source": "readingchronicle.co.uk", "url": "https://www.readingchronicle.co.uk/news/national/26014084.russia-ukraine-trade-blame-violating-orthodox-easter-ceasefire/", "entities": ["Vladimir Putin", "Volodymyr Zelensky", "Russian President", "Ukrainian President"], "impacted_assets": ["Gold", "USD"], "volatility_implication": "Increase", "llm_tone_score": -2}} +{"id": "a43dd760-9cb8-5a0b-ab18-18f9b88e6177", "text": "UK Prime Minister Urges US and Iran to Find a Way Through After Peace Talks Fail. The UK Prime Minister has called for the US and Iran to find a way through after peace talks failed. The situation remains fragile, with the Strait of Hormuz still blocked by Iran, leading to soaring energy prices. The UK will host further talks next week to explore ways to support a sustainable end to the conflict and increase international diplomatic pressure on Iran.", "metadata": {"topic": "macro_geopolitics_risk", "title": "UK Prime Minister Urges US and Iran to Find a Way Through After Peace Talks Fail", "original_title": "Starmer urges US and Iran to find a way through after peace talks fail", "publish_date": "2026-04-12T14:41:52Z", "publish_timestamp": 1776004912, "source": "bordertelegraph.com", "url": "https://www.bordertelegraph.com/news/national/26014105.starmer-urges-us-iran-to-find-way-through-peace-talks-fail/", "entities": ["Sir Keir Starmer", "Donald Trump", "His Majesty Sultan Haitham bin Tarik al Said"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "5c326183-8136-5fca-b1ff-aef2bd329af5", "text": "China to Reestablish Some Ties with Taiwan after Opposition Leader Visit. The reestablishment of some ties between China and Taiwan is a neutral event for the gold/silver market. This development does not have a direct macro transmission mechanism to affect gold or silver prices, as it is primarily a diplomatic move without significant implications for global economic growth or inflation.", "metadata": {"topic": "macro_geopolitics_risk", "title": "China to Reestablish Some Ties with Taiwan after Opposition Leader Visit", "original_title": "China to reinstate some Taiwan ties after opposition leader visit", "publish_date": "2026-04-12T14:41:52Z", "publish_timestamp": 1776004912, "source": "article.wn.com", "url": "https://article.wn.com/view/2026/04/12/China_to_reinstate_some_Taiwan_ties_after_opposition_leaders/", "entities": ["China", "Taiwan", "Beijing-friendly opposition leader"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "5232d8b1-7f86-5f8d-9305-bcb5c0cd47ea", "text": "Russia-Ukraine Conflict: Ceasefire Breaches and Prisoner Exchange. The Russia-Ukraine conflict has seen a ceasefire breach, with both sides accusing each other of violating the agreement. Despite this, hundreds of prisoners were exchanged, and the situation remains tense at the front lines. The macro transmission mechanism is neutral, as there are no clear directional drivers for gold or silver prices.", "metadata": {"topic": "macro_geopolitics_risk", "title": "Russia-Ukraine Conflict: Ceasefire Breaches and Prisoner Exchange", "original_title": "Ukraine - Krieg : Tausende Verste bei Osterwaffenruhe beklagt", "publish_date": "2026-04-12T14:41:52Z", "publish_timestamp": 1776004912, "source": "muensterschezeitung.de", "url": "https://www.muensterschezeitung.de/nachrichten/schlagzeilen/ukraine-krieg-tausende-verstoesse-bei-osterwaffenruhe-beklagt-3530354", "entities": ["Vladimir Putin", "Volodymyr Zelensky", "Dmitri Peskow"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "e06b791b-28a4-5e4d-b465-e69cb4f9a816", "text": "Trump Announces Blockade of Strait of Hormuz for Those Paying Iran. US President Donald Trump has announced a blockade of the Strait of Hormuz for any vessel paying Iran to pass through. This move is likely to increase tensions in the region and boost gold prices as investors seek safe-haven assets. The strengthening of Russia's support for Iran may also lead to increased volatility in oil markets, while a weakening USD could further fuel inflation concerns.\n\nThe macro transmission mechanism at play here is the potential escalation of geopolitical tensions, which can drive up demand for safe-haven assets like gold and increase market fear, leading to higher VIX levels. The blockade announcement also has implications for global trade and commerce, particularly in the oil sector, as Iran is a significant player in global energy markets.", "metadata": {"topic": "macro_geopolitics_risk", "title": "Trump Announces Blockade of Strait of Hormuz for Those Paying Iran", "original_title": "Trump anuncia un bloqueo del Estrecho de Ormuz para todos aquellos que paguen a Irán", "publish_date": "2026-04-12T14:41:52Z", "publish_timestamp": 1776004912, "source": "diariocritico.com", "url": "https://www.diariocritico.com/internacional/trump-anuncia-bloqueo-estrecho-ormuz-paguen-a-iran", "entities": ["Donald Trump", "Irán", "Vladimir Putin", "Masud Pezeshkian"], "impacted_assets": ["Gold", "Oil", "USD"], "volatility_implication": "Increase", "llm_tone_score": 3}} diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-12/qdrant_macro_inflation_employment_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-12/qdrant_macro_inflation_employment_processed.jsonl new file mode 100644 index 0000000..acacf31 --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-12/qdrant_macro_inflation_employment_processed.jsonl @@ -0,0 +1,7 @@ +{"id": "49fb7d82-f0b7-5b32-9ea2-2e3a320a1259", "text": "Norwegian Labor Union and Industry Reach Agreement on Wage Increase. The Norwegian Labor Union and Industry have reached an agreement on a wage increase, with a 6.50 kr general addendum and additional 4 kr for the lowest-paid workers. This development is neutral for gold/silver prices, as it does not significantly impact macroeconomic drivers or global market sentiment.\n\nNote: As there are no explicit mentions of monetary policy, inflation, or currency movements in this article, the tone score is neutral. The agreement on wage increase may have some indirect effects on consumer spending and economic growth, but these are not directly relevant to gold/silver prices.", "metadata": {"topic": "macro_inflation_employment", "title": "Norwegian Labor Union and Industry Reach Agreement on Wage Increase", "original_title": "Lønnsforhandlinger , Arbeidsliv | Enighet med Fellesforbundet i frontfagsoppgjøret – Parat fortsatt i mekling", "publish_date": "2026-04-12T14:40:26Z", "publish_timestamp": 1776004826, "source": "ringblad.no", "url": "https://www.ringblad.no/enighet-med-fellesforbundet-i-frontfagsoppgjoret-parat-fortsatt-i-mekling/s/5-45-2209025", "entities": ["Fellesforbundet", "Parat", "Norsk Industri", "Riksmekleren"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "092a0a3c-8587-5774-8e43-edfd28e1794f", "text": "The US-Iran Talks Fail, Trump Considers Naval Blockade as Next Move. The US-Iran talks have failed to achieve any progress, and the US is considering a naval blockade as its next move. This development could lead to increased market volatility, particularly in oil prices, and potentially weigh on gold prices. The threat of resumed combat operations and the potential for supply chain disruptions could also contribute to higher inflation expectations, further supporting gold's safe-haven appeal.\n\nThe tone score is bearish due to the escalating tensions between the US and Iran, which could lead to increased market volatility and a decline in risk assets like equities and oil. The consideration of a naval blockade as a next move adds to the negative sentiment, suggesting that the situation may worsen before it improves.", "metadata": {"topic": "macro_inflation_employment", "title": "The US-Iran Talks Fail, Trump Considers Naval Blockade as Next Move", "original_title": "War On Iran : – Loser Tries Setting Terms – The Strange Idea Of Blockading Blockaders – Moon of Alabama", "publish_date": "2026-04-12T14:40:26Z", "publish_timestamp": 1776004826, "source": "moonofalabama.org", "url": "https://www.moonofalabama.org/2026/04/war-on-iran-loser-tries-setting-terms-the-strange-idea-of-blockading-blockaders.html/comment-page-2", "entities": ["Donald Trump", "Iran", "United States", "Jack Keane", "John Solomon"], "impacted_assets": ["Gold", "Oil", "USD"], "volatility_implication": "Increase", "llm_tone_score": -2}} +{"id": "a2c8f543-5fe4-5445-8230-3dc242f4ed3e", "text": "Zimbabwe Banks Hedge Against Global Shocks Amid Cautious Optimism. Zimbabwe's banking sector is cautiously optimistic about 2026 growth prospects, driven by stable macroeconomic indicators and improving economic fundamentals. However, banks are also hedging against global shocks and currency pressures. The sector's focus on stability in inflation, interest rates, and exchange rates is seen as critical for sustaining momentum after years of volatility.\n\nNote: The tone score is +1 because while the article mentions some risks and challenges, the overall sentiment is cautiously optimistic, which is slightly bullish for gold and silver prices.", "metadata": {"topic": "macro_inflation_employment", "title": "Zimbabwe Banks Hedge Against Global Shocks Amid Cautious Optimism", "original_title": "Zimbabwe lenders hedge against global shocks", "publish_date": "2026-04-12T14:40:26Z", "publish_timestamp": 1776004826, "source": "thestandard.co.zw", "url": "https://www.thestandard.co.zw/business/article/200053827/zimbabwes-lenders-hedge-against-global-shocks", "entities": ["Luxon Zembe", "CBZ Holdings Limited", "Tawanda Nyambirai", "TN CyberTech Bank", "Agnes Makamure", "ZB Financial Holdings Limited", "Herbert Nkala", "FBC Holdings Limited", "Pearson Gowero", "NMB Bank", "Patrick Devenish", "First Capital Bank Zimbabwe"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 1}} +{"id": "303c24bf-d4c3-5210-8ae2-a898e7d805dc", "text": "Immigration Crackdown Reaches Beyond Workplaces in Rural Missouri. The article highlights an immigration crackdown in rural Missouri, where ICE agents arrested three individuals, including two from Senegal and one from Guatemala. This expansion of enforcement beyond workplaces may increase uncertainty and potentially weigh on the USD, leading to a short-term boost for gold prices.", "metadata": {"topic": "macro_inflation_employment", "title": "Immigration Crackdown Reaches Beyond Workplaces in Rural Missouri", "original_title": "In rural Missouri , immigration crackdown reaches beyond the workplace", "publish_date": "2026-04-12T14:40:26Z", "publish_timestamp": 1776004826, "source": "newstribune.com", "url": "http://www.newstribune.com/news/2026/apr/12/in-rural-missouri-immigration-crackdown-reaches-beyond-the-workplace/", "entities": ["Eliseo Affholter", "U.S. Immigration and Customs Enforcement (ICE)", "President Donald Trump", "Axel Fuentes", "Kevin R. Johnson"], "impacted_assets": ["USD", "Equities", "Gold"], "volatility_implication": "Neutral", "llm_tone_score": -2}} +{"id": "c0875d6d-6d02-51c9-b031-b6bc716e756e", "text": "Chinese Tourism | Spring in China Beckons Foreign Visitors!. The article highlights the increasing popularity of Chinese tourism among foreign visitors, particularly during the spring season. With China's visa-free policy and social media platforms, overseas tourists are flocking to experience the country's vibrant culture and natural beauty. This trend is expected to drive growth in the tourism industry, with data showing a 21% increase in international arrivals in March. The article also touches on the cultural exchange between China and foreign visitors, highlighting the mutual understanding and appreciation that can be gained through travel.\n\nNote: As there are no direct macro-financial implications from this article, I have assigned a neutral tone score of 0.", "metadata": {"topic": "macro_inflation_employment", "title": "Chinese Tourism | Spring in China Beckons Foreign Visitors!", "original_title": "中国游记 | 春色不负万里客 ! 老外爱上 春日中国行 - 水母网", "publish_date": "2026-04-12T14:40:26Z", "publish_timestamp": 1776004826, "source": "news.shm.com.cn", "url": "https://news.shm.com.cn/2026-04/12/content_5482767.htm", "entities": ["China", "Overseas Tourists", "Shanghai", "Guizhou", "Jiangxi", "Xinjiang", "Kashgar", "Ili"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "0784abc8-2142-5e70-bb98-aa8a3a3ebeab", "text": "Who are the Toesca protagonists: The key players in Sanhattan's moment. Toesca S.A. Administradora de Fondos de Inversión, a specialized alternative assets manager, has been making headlines with its recent acquisitions and partnerships. The company's founders, Alejandro Reyes and Carlos Saieh, have a background in the financial industry, having worked at BTG Pactual and Celfin before starting Toesca. With over $2.5 billion in investments and managing around $1.5 billion in 25 funds, Toesca is gaining prominence in the market. The company's growth and expansion plans may have implications for the broader financial markets, particularly in the equities and gold sectors.\n\nNote: As there are no explicit macro-financial or geopolitical drivers mentioned in the article, I assigned a tone score of 0 (Neutral).", "metadata": {"topic": "macro_inflation_employment", "title": "Who are the Toesca protagonists: The key players in Sanhattan's moment", "original_title": "Quiénes son los Toesca : Los protagonistas del momento en Sanhattan", "publish_date": "2026-04-12T14:40:26Z", "publish_timestamp": 1776004826, "source": "latercera.com", "url": "https://www.latercera.com/pulso/noticia/quienes-son-los-toesca-los-protagonistas-del-momento-en-sanhattan/", "entities": ["Alejandro Reyes", "Carlos Saieh", "BTG Pactual", "Celfin", "Aetna", "ING", "Moneda Asset Management", "Frontal Trust", "TC Latin America Partners", "Primus Capital", "Ameris Capital"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "7f51aba0-52c7-515e-9478-a57755aefbd3", "text": "Haiti's Food and Fuel Crisis Deepens Amid Rising Oil Prices. The article highlights the devastating impact of rising oil prices on Haiti's already fragile economy. As fuel costs surge, food prices are expected to increase, exacerbating hunger and poverty in a country where nearly 40% of the population survives on less than $2.15 per day. This macro transmission mechanism is bearish for Gold/Silver prices, as it increases market fear/VIX, which may lead to increased demand for safe-haven assets like precious metals.", "metadata": {"topic": "macro_inflation_employment", "title": "Haiti's Food and Fuel Crisis Deepens Amid Rising Oil Prices", "original_title": "Haitians cut back on already scarce food and ask how theyll survive rising fuel prices – Sun Sentinel", "publish_date": "2026-04-12T14:40:26Z", "publish_timestamp": 1776004826, "source": "sun-sentinel.com", "url": "https://www.sun-sentinel.com/2026/04/12/haitians-cut-back-on-already-scarce-food-and-ask-how-theyll-survive-rising-fuel-prices/", "entities": ["Alexandre Joseph", "Erwan Rumen", "Emmline Toussaint", "Fedline Jean-Pierre", "Maxime Poulard"], "impacted_assets": ["Gold", "Silver", "USD"], "volatility_implication": "Increase", "llm_tone_score": -3}} diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-14/qdrant_asset_precious_metals_spot_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-14/qdrant_asset_precious_metals_spot_processed.jsonl new file mode 100644 index 0000000..b9828e0 --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-14/qdrant_asset_precious_metals_spot_processed.jsonl @@ -0,0 +1,6 @@ +{"id": "ad97a3a6-1567-57bd-855b-a68a12c65490", "text": "Silver Prices Surge in Vietnam and Globally Amid Geopolitical Developments. The article reports a surge in silver prices in Vietnam and globally, driven by geopolitical developments. The US and Iran are reportedly close to reaching a long-term ceasefire agreement, which has boosted market sentiment and led to increased demand for safe-haven assets like gold and silver. This development is expected to have a positive impact on the price of these precious metals.\n\nThe macro transmission mechanism at play here is the increase in risk appetite among investors, driven by the potential resolution of geopolitical tensions. As investors become more optimistic about the future, they are likely to seek out higher-risk assets like gold and silver, driving up their prices.", "metadata": {"topic": "asset_precious_metals_spot", "title": "Silver Prices Surge in Vietnam and Globally Amid Geopolitical Developments", "original_title": "Ngày 15 / 4 : Giá bạc trong nước và thế giới bật tăng mạnh", "publish_date": "2026-04-15T03:32:11Z", "publish_timestamp": 1776223931, "source": "thoibaotaichinhvietnam.vn", "url": "https://thoibaotaichinhvietnam.vn/ngay-154-gia-bac-trong-nuoc-va-the-gioi-bat-tang-manh-195669.html", "entities": ["Phú Quý", "Vàng bạc Đá quý Phú Quý", "Iran", "United States"], "impacted_assets": ["Gold", "Silver", "USD"], "volatility_implication": "Increase", "llm_tone_score": 3}} +{"id": "41747a6d-7e5d-5f42-b738-76980675bd44", "text": "Gold Price on April 15: Prices at Jewelry Companies. The gold price rose around 2% to $4,831.78 per ounce due to a weakening US dollar and expectations of renewed US-Iran negotiations. Analysts at Commerzbank believe that as long as the Fed doesn't signal rate hikes, gold prices will be difficult to drop significantly. Meanwhile, Vietnamese jewelry companies such as SJC listed their gold prices in Hanoi at 173-175.5 million VND per tael (buying and selling).\n\nThe macro transmission mechanism is that a weakening US dollar and expectations of renewed US-Iran negotiations are driving up the gold price, which is likely to continue as long as there is no indication of rate hikes from the Fed. This has a bullish tone for gold prices.", "metadata": {"topic": "asset_precious_metals_spot", "title": "Gold Price on April 15: Prices at Jewelry Companies", "original_title": "Giá vàng ngày 15 / 4 : Bảng giá tại các công ty vàng bạc đá quý", "publish_date": "2026-04-15T03:32:11Z", "publish_timestamp": 1776223931, "source": "baomoi.com", "url": "https://baomoi.com/gia-vang-ngay-15-4-bang-gia-tai-cac-cong-ty-vang-bac-da-quy-c54939126.epi", "entities": ["Bob Haberkorn", "RJO Futures", "Commerzbank", "Federal Reserve (Fed)", "SJC (Vàng bạc đá quý Sài Gòn)"], "impacted_assets": ["Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "f0a80642-d4ab-5fcb-bacc-737ac97be417", "text": "Alacant's Budget and Housing Crisis. The approved budget for 2026 in Alacant is the highest in history, but it reflects a concerning reality: investment in neighborhoods has hit historic lows. The inefficient execution of the budget by the government leads to a lack of municipalization, with funds ending up in the treasury instead of being used for public services. This crisis affects not only housing but also tourism, as thousands of apartments are dedicated to short-term rentals. To address this issue, a drastic measure is proposed: no new licenses or renewals for tourist apartments by 2028.\n\nThe macro transmission mechanism at play here is the impact on the local economy and the housing market. The lack of investment in neighborhoods and the inefficient use of funds can lead to a decrease in economic activity and a rise in unemployment, which can negatively affect gold and silver prices. Additionally, the crisis in the tourism sector can also have a negative impact on the overall economy and asset prices.", "metadata": {"topic": "asset_precious_metals_spot", "title": "Alacant's Budget and Housing Crisis", "original_title": " Pisos turístics ? Les cases , per als veïns i els turistes , als hotels ", "publish_date": "2026-04-15T03:32:11Z", "publish_timestamp": 1776223931, "source": "elpuntavui.cat", "url": "http://www.elpuntavui.cat/politica/article/17-politica/2635259-pisos-turistics-les-cases-per-als-veins-i-els-turistes-als-hotels.html", "entities": ["PP", "Vox", "Alacant", "Spain"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Decrease", "llm_tone_score": -2}} +{"id": "c4a6111c-1818-50a6-8d0d-c2687106f4a7", "text": "Wanda Commercial Properties Wins Arbitration Case Against Dalian Yunding, Wang Jianlin et al. to Pay 38.57 Billion Yuan in Damages. Wanda Commercial Properties won an arbitration case against Dalian Yunding and its related parties, including Wang Jianlin, for failing to pay damages totaling 38.57 billion yuan. This outcome may help Wanda Commercial Properties recover some of its losses, but the impact on gold/silver prices is limited. The company's financial performance has been under pressure due to declining revenue and increasing losses.", "metadata": {"topic": "asset_precious_metals_spot", "title": "Wanda Commercial Properties Wins Arbitration Case Against Dalian Yunding, Wang Jianlin et al. to Pay 38.57 Billion Yuan in Damages", "original_title": "永辉超市38亿追款获胜 , 王健林等承担连带保证责任", "publish_date": "2026-04-15T03:32:11Z", "publish_timestamp": 1776223931, "source": "stcn.com", "url": "https://www.stcn.com/article/detail/3750646.html", "entities": ["Wanda Commercial Properties", "Dalian Yunding", "Wang Jianlin", "Sun Xishuang", "One-way Group"], "impacted_assets": ["Equities", "Gold (indirectly)"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "ff95ca9a-5004-595b-98b0-5618198073e8", "text": "China's Pilot Free Trade Zone (FTZ) in Hainan Seeks to Boost Aviation Industry and Economic Growth. The article highlights the development of Hainan's Pilot Free Trade Zone (FTZ) and its efforts to boost the aviation industry and economic growth. The FTZ aims to create a high-efficiency logistics loop by building a 1-kilometer-long underground tunnel connecting the airport with the industrial park, allowing for streamlined customs clearance, warehousing, processing, and departure procedures. This initiative is expected to drive the development of aircraft maintenance, aviation logistics, low-altitude economy, and other related industries, ultimately contributing to China's economic growth.\n\nThe article also mentions the benefits of Hainan's FTZ, including tax exemptions on imported equipment, the seventh air rights, and visa-free policies for 86 countries. These advantages have attracted foreign companies, such as Boeing and Airbus, to set up operations in the region. The development of the aviation industry is expected to drive economic growth and create new job opportunities.\n\nThe tone score is +2 because while the article highlights the potential benefits of Hainan's FTZ, it does not explicitly mention any macroeconomic drivers that would significantly impact gold or silver prices. However, the initiative could potentially contribute to China's economic growth, which could have a positive impact on these assets.", "metadata": {"topic": "asset_precious_metals_spot", "title": "China's Pilot Free Trade Zone (FTZ) in Hainan Seeks to Boost Aviation Industry and Economic Growth", "original_title": "开局之年看中国 · 开放自贸港 : 从 机场流量 迈向 经济增量 - 千龙网 · 中国首都网", "publish_date": "2026-04-15T03:32:11Z", "publish_timestamp": 1776223931, "source": "china.qianlong.com", "url": "https://china.qianlong.com/2026/0415/8654785.shtml", "entities": ["Zhang Hao Peng", "Wang Hai Yue", "Hainan FTZ", "Hainan Provincial Government", "Civil Aviation Administration of China (CAAC)", "Boeing", "Airbus"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "ae9c2d8f-a65f-5e69-82af-dfa12478e3a8", "text": "Vietnam Develops Human Resources for the Semiconductor Industry to Prepare for the Future. Vietnam is accelerating the development of high-quality human resources for the semiconductor industry to capitalize on opportunities and enhance its competitiveness. The government has set a target to train 50,000 engineers by 2030, with 15,000 specializing in chip design, 35,000 in production, packaging, and testing, and 5,000 AI experts. This initiative aims to bridge the gap between supply and demand for skilled labor, supporting the growth of the industry.\n\nThe macro transmission mechanism is that a well-trained workforce will attract more foreign investment, drive economic growth, and increase Vietnam's competitiveness in the global semiconductor market. This could positively impact gold prices if investors become more optimistic about Vietnam's economic prospects.", "metadata": {"topic": "asset_precious_metals_spot", "title": "Vietnam Develops Human Resources for the Semiconductor Industry to Prepare for the Future", "original_title": "Phát triển nguồn nhân lực công nghiệp bán dẫn , sẵn sàng cho tương lai", "publish_date": "2026-04-15T03:32:11Z", "publish_timestamp": 1776223931, "source": "thanhtra.com.vn", "url": "https://thanhtra.com.vn/doanh-nghiep-70CE54C31/phat-trien-nguon-nhan-luc-cong-nghiep-ban-dan-san-sang-cho-tuong-lai-7632e8f4b.html", "entities": ["Vietnamese government", "Intel", "Samsung", "Amkor", "Hana Micron", "Viettel", "FPT", "VNChip", "Marvell", "Synopsys", "Cadence"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 2}} diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-14/qdrant_macro_central_banks_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-14/qdrant_macro_central_banks_processed.jsonl new file mode 100644 index 0000000..259b342 --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-14/qdrant_macro_central_banks_processed.jsonl @@ -0,0 +1,6 @@ +{"id": "41747a6d-7e5d-5f42-b738-76980675bd44", "text": "Gold Price on April 15: Prices at Jewelry Companies. The gold price rose around 2% to $4,831.78 per ounce due to a weakening US dollar and expectations of renewed US-Iran negotiations. Analysts at Commerzbank believe that as long as the Federal Reserve (Fed) does not signal rate hikes, gold prices will be difficult to fall significantly. Meanwhile, Vietnamese jewelry companies such as SJC listed their gold prices in Hanoi at 173-175.5 million VND per tael (buying and selling). The macro transmission mechanism is a weakening US dollar and expectations of renewed negotiations, which are bullish for gold prices.\n\nNote: The tone score is +2 because the article mentions a strengthening USD, which is bearish for gold prices, but also notes that Fed rate hikes are not expected, which is neutral.", "metadata": {"topic": "macro_central_banks", "title": "Gold Price on April 15: Prices at Jewelry Companies", "original_title": "Giá vàng ngày 15 / 4 : Bảng giá tại các công ty vàng bạc đá quý", "publish_date": "2026-04-15T03:28:27Z", "publish_timestamp": 1776223707, "source": "baomoi.com", "url": "https://baomoi.com/gia-vang-ngay-15-4-bang-gia-tai-cac-cong-ty-vang-bac-da-quy-c54939126.epi", "entities": ["Bob Haberkorn", "RJO Futures", "Commerzbank", "Federal Reserve (Fed)", "SJC (Vàng bạc đá quý Sài Gòn)"], "impacted_assets": ["Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "1b3c6216-eb7b-55cc-ab8d-8bc810335094", "text": "Producer Prices Rise Sharply Due to Energy Surge Linked to Iran War. Rising energy costs linked to the Iran war pushed US wholesale prices higher in March, adding to inflation concerns and complicating the Federal Reserve's policy outlook. The producer price index rose 0.5% from February and 4% year-on-year, driven by an 8.5% surge in energy prices. This adds pressure on the Fed to consider rate hikes or maintain a neutral stance, which may support gold and silver prices while increasing market fear/VIX.", "metadata": {"topic": "macro_central_banks", "title": "Producer Prices Rise Sharply Due to Energy Surge Linked to Iran War", "original_title": "Producer prices rise sharply on energy surge from Iran war", "publish_date": "2026-04-15T03:28:27Z", "publish_timestamp": 1776223707, "source": "europesun.com", "url": "http://www.europesun.com/news/278983984/producer-prices-rise-sharply-on-energy-surge-from-iran-war", "entities": ["Federal Reserve", "President Donald Trump", "International Energy Agency"], "impacted_assets": ["Gold", "Silver", "USD", "Oil"], "volatility_implication": "Increase", "llm_tone_score": 2}} +{"id": "fbb8885f-e47c-5c14-a49c-3a0f538c02d6", "text": "Mexican Bank's Economic Forecasts Criticized by Banamex. Banamex, a Mexican bank, has criticized the economic forecasts of the Bank of Mexico (Banxico) and the Ministry of Finance and Public Credit (SHCP), stating that their predictions are \"erratic\" and lack credibility. The criticism centers around Banxico's inability to effectively implement monetary policy, which may lead to reduced market confidence in the Mexican economy. This could have a negative impact on gold prices and the US dollar.\n\nThe macro transmission mechanism is as follows: Banamex's skepticism towards Banxico's economic forecasts may lead to increased uncertainty and decreased market confidence in Mexico's economic prospects. This could result in a decrease in gold prices, as investors seek safer assets, and a weakening of the US dollar, as the Mexican economy becomes less attractive to foreign investors.", "metadata": {"topic": "macro_central_banks", "title": "Mexican Bank's Economic Forecasts Criticized by Banamex", "original_title": "Banamex tacha de erráticos los pronósticos de Banxico y la SHCP sobre crecimiento e inflación", "publish_date": "2026-04-15T03:28:27Z", "publish_timestamp": 1776223707, "source": "zetatijuana.com", "url": "https://zetatijuana.com/2026/04/banamex-tacha-de-erraticos-los-pronosticos-de-banxico-y-la-shcp-sobre-crecimiento-e-inflacion/", "entities": ["Sergio Kurczyn", "Iván Arias", "Banco de México (Banxico)", "Secretaría de Hacienda y Crédito Público (SHCP)"], "impacted_assets": ["Gold", "USD"], "volatility_implication": "Decrease", "llm_tone_score": -2}} +{"id": "c134a64b-5f23-5e31-9200-811cf9b6ba6d", "text": "Gold Prices Surge in Vietnam as Global Rates Rise. Vietnamese gold prices surged today, tracking global rates, as the US dollar weakened amid rising expectations of a potential Iran-US deal. The market is cautious about the Federal Reserve's monetary policy stance, with some data indicating low inflation, but still expects interest rates to remain high in the long term.\n\nThe article highlights the strong correlation between Vietnamese gold prices and global rates, with the latter driving the former. The weakening US dollar also contributed to the increase in gold prices. While the market is uncertain about the Fed's next move, the overall tone remains bullish for gold prices.", "metadata": {"topic": "macro_central_banks", "title": "Gold Prices Surge in Vietnam as Global Rates Rise", "original_title": "Giá vàng hôm nay 15 / 4 đồng loạt tăng mạnh", "publish_date": "2026-04-15T03:28:27Z", "publish_timestamp": 1776223707, "source": "baotintuc.vn", "url": "https://baotintuc.vn/kinh-te/gia-vang-sang-154-dong-loat-tang-manh-20260415082802323.htm", "entities": ["SJC", "Bảo Tín Minh Châu", "DOJI", "Vietcombank", "Fed"], "impacted_assets": ["Gold", "USD"], "volatility_implication": "Increase", "llm_tone_score": 2}} +{"id": "846233f2-d115-5c70-b857-0de4c4c97442", "text": "Oil Shock is Here: Are Businesses Prepared?. The escalating Middle East conflict has sent shockwaves through global energy markets, driving oil prices higher and increasing operational costs for businesses. This surge in fuel prices poses significant risks to micro, small, and medium enterprises' (MSMEs) viability, with direct and indirect cost shocks, rising raw material costs, \"stagflation\" squeeze, margin compression, and cash flow tightness being the key concerns. The uncertainty surrounding the supply of raw materials and input prices has resulted in suppliers and manufacturers taking a cautious stance, leading to increased volatility in the market.\n\nNote: The tone score is bearish due to the negative impact on businesses' operating costs and profitability, which may lead to decreased consumer spending and ultimately affect gold and silver prices.", "metadata": {"topic": "macro_central_banks", "title": "Oil Shock is Here: Are Businesses Prepared?", "original_title": "Oil shock is here : Are businesses prepared ? ", "publish_date": "2026-04-15T03:28:27Z", "publish_timestamp": 1776223707, "source": "thestar.com.my", "url": "https://www.thestar.com.my/business/insight/2026/04/15/oil-shock-is-here-are-businessesprepared", "entities": ["Middle East conflict", "oil prices", "MSMEs (Micro", "Small and Medium Enterprises)", "global energy markets"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Increase", "llm_tone_score": -2}} +{"id": "aff5f7ce-32f7-5224-b3fe-52ba6bc7b911", "text": "Indonesian Rupiah Strengthens Against US Dollar on April 15th. The Indonesian Rupiah strengthened against the US Dollar on April 15th due to external pressures and market optimism. The Rupiah's appreciation is driven by a combination of factors, including the weakening US Dollar, rising oil prices, and improving market sentiment. This development may have a positive impact on gold and equity markets, while also influencing the direction of monetary policy in Indonesia.\n\nNote: The tone score is +2 because the article mentions external pressures and market optimism, which are generally bullish for gold and silver prices. However, the article also notes that domestic sentiment remains weak, which could temper the Rupiah's appreciation.", "metadata": {"topic": "macro_central_banks", "title": "Indonesian Rupiah Strengthens Against US Dollar on April 15th", "original_title": "Rupiah Hari Ini ( 15 / 4 ) Dibuka Menguat ke Rp17 . 126 per dolar AS", "publish_date": "2026-04-15T03:28:27Z", "publish_timestamp": 1776223707, "source": "market.bisnis.com", "url": "https://market.bisnis.com/read/20260415/93/1966735/rupiah-hari-ini-154-dibuka-menguat-ke-rp17126-per-dolar-as", "entities": ["Bank Indonesia", "Doo Financial Futures", "Lukman Leong"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 2}} diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-14/qdrant_macro_geopolitics_risk_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-14/qdrant_macro_geopolitics_risk_processed.jsonl new file mode 100644 index 0000000..c64ffde --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-14/qdrant_macro_geopolitics_risk_processed.jsonl @@ -0,0 +1,6 @@ +{"id": "ab952c09-e756-5f41-9d4a-4b5fb6c2b3b3", "text": "Trump's Feud with Pope Over AI Christ Image Intensifies Amid Controversy. The feud between US President Donald Trump and Pope Leo over an AI-generated image of Christ has escalated, with both sides trading barbs. While this controversy is unlikely to have a direct impact on gold or silver prices, it may contribute to increased market uncertainty and volatility in the short term.", "metadata": {"topic": "macro_geopolitics_risk", "title": "Trump's Feud with Pope Over AI Christ Image Intensifies Amid Controversy", "original_title": "Trump Bible - Thumper Assassination Fears Explode Amid Bust - Up With Pope", "publish_date": "2026-04-15T03:31:19Z", "publish_timestamp": 1776223879, "source": "radaronline.com", "url": "https://radaronline.com/p/trump-assassination-fears-pope-conflict-iran-war/", "entities": ["Donald Trump", "Pope Leo", "JD Vance"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "b434614a-e7c2-511c-99a2-3c16cc2fffcd", "text": "More Than Half of Households in Energy Credit at End of Winter – Poll. The survey by comparison site Uswitch found that more than half of UK households have credit in their energy accounts at the end of winter. This could be due to a milder winter and direct debits not changing as quickly as energy rates. While this may seem positive, it's essential for households to keep some credit for higher winter bills ahead. The predicted 18% hike in energy prices from July could impact gold and silver prices, but the overall tone is neutral.\n\nNote: As there are no explicit macro-financial drivers or market-moving events mentioned in the article, I assigned a tone score of 0 (Neutral).", "metadata": {"topic": "macro_geopolitics_risk", "title": "More Than Half of Households in Energy Credit at End of Winter – Poll", "original_title": "More than half of households in energy credit at end of winter – poll", "publish_date": "2026-04-15T03:31:19Z", "publish_timestamp": 1776223879, "source": "whtimes.co.uk", "url": "https://www.whtimes.co.uk/news/national/26021871.half-households-energy-credit-end-winter---poll/", "entities": ["Uswitch", "Ofgem", "Chancellor", "Cornwall Insight"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "919a7702-4dfc-533a-9faf-4bb5007ca67b", "text": "Chancellor to hold talks with US counterpart after strong criticism of Iran war. The escalating tensions between the US and Iran have led to a global economic shock, with the IMF slashing Britain's economic growth forecast. The conflict has also sent energy prices soaring, which could impact gold and oil prices. The Chancellor's criticism of the US actions in the Middle East may lead to increased market volatility, as investors become more risk-averse.\n\nThe macro transmission mechanism is as follows: The conflict in the Gulf has led to a global economic shock, which has impacted Britain's economic growth forecast. This has increased uncertainty and volatility in financial markets, making investors more cautious and potentially driving up gold prices.", "metadata": {"topic": "macro_geopolitics_risk", "title": "Chancellor to hold talks with US counterpart after strong criticism of Iran war", "original_title": "Chancellor to hold talks with US counterpart after strong criticism of Iran war", "publish_date": "2026-04-15T03:31:19Z", "publish_timestamp": 1776223879, "source": "wharfedaleobserver.co.uk", "url": "https://www.wharfedaleobserver.co.uk/news/national/26021877.chancellor-hold-talks-us-counterpart-strong-criticism-iran-war/", "entities": ["Scott Bessent", "Rishi Sunak", "Andrew Bailey", "Donald Trump", "Keir Starmer", "Xi Jinping"], "impacted_assets": ["Gold", "Oil", "USD"], "volatility_implication": "Increase", "llm_tone_score": -2}} +{"id": "20b30dcc-f607-5415-9aae-decf05fe1e0e", "text": "CENTCOM Reports Success in Blockading Iranian Ports on First Day. The US Central Command has reported a successful first day of blockading Iranian ports, with no ships entering or leaving the country. This development may put pressure on Iran to reconsider its claims of control over the Strait of Hormuz. However, Saudi Arabia is reportedly pressing the US to drop the blockade and return to negotiations, citing concerns about escalation from the Houthis. The situation remains fluid, with implications for global oil markets and currency fluctuations.\n\nNote: The tone score is neutral because while there are some macro-financial implications, the event itself does not have a clear directional impact on Gold/Silver prices.", "metadata": {"topic": "macro_geopolitics_risk", "title": "CENTCOM Reports Success in Blockading Iranian Ports on First Day", "original_title": "CENTCOM : 24 Hours And All Well On the Blockade Front ( Updated ) ", "publish_date": "2026-04-15T03:31:19Z", "publish_timestamp": 1776223879, "source": "hotair.com", "url": "https://hotair.com/ed-morrissey/2026/04/14/centcom-24-hours-and-alls-well-on-the-blockade-front-n3813891", "entities": ["US Central Command (CENTCOM)", "Iran", "Saudi Arabia", "Houthis", "China"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "41747a6d-7e5d-5f42-b738-76980675bd44", "text": "Gold Price on April 15: Prices at Jewelry Companies. The gold price rose around 2% to $4,831.78 per ounce due to a weakening US dollar and expectations of renewed US-Iran negotiations. Analysts at Commerzbank believe that as long as the Fed doesn't signal rate hikes, gold prices will be difficult to drop significantly. Meanwhile, Vietnamese jewelry companies such as SJC listed their gold prices in Hanoi at 173-175.5 million VND per tael (buying and selling).\n\nThe macro transmission mechanism is that a weakening US dollar and expectations of renewed US-Iran negotiations are driving up the gold price, which is likely to continue as long as there is no indication of rate hikes from the Fed. This has a bullish tone for gold prices.", "metadata": {"topic": "macro_geopolitics_risk", "title": "Gold Price on April 15: Prices at Jewelry Companies", "original_title": "Giá vàng ngày 15 / 4 : Bảng giá tại các công ty vàng bạc đá quý", "publish_date": "2026-04-15T03:31:19Z", "publish_timestamp": 1776223879, "source": "baomoi.com", "url": "https://baomoi.com/gia-vang-ngay-15-4-bang-gia-tai-cac-cong-ty-vang-bac-da-quy-c54939126.epi", "entities": ["Bob Haberkorn", "RJO Futures", "Commerzbank", "Federal Reserve (Fed)", "SJC (Vàng bạc đá quý Sài Gòn)"], "impacted_assets": ["Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "aa37052e-9108-5aa8-8970-65679c41f016", "text": "Italy Suspends Defense Agreement with Israel Amid Tensions Over War in Lebanon. The suspension of Italy's defense agreement with Israel amid escalating tensions over the war in Lebanon may lead to increased market uncertainty and a flight-to-safety bid for gold. This development could also put pressure on the US dollar as European countries continue to reevaluate their relationships with Israel. The macro transmission mechanism is driven by the potential for increased geopolitical risk, which can boost demand for safe-haven assets like gold and weaken the USD.", "metadata": {"topic": "macro_geopolitics_risk", "title": "Italy Suspends Defense Agreement with Israel Amid Tensions Over War in Lebanon", "original_title": "EU country suspends defense agreement with Israel", "publish_date": "2026-04-15T03:31:19Z", "publish_timestamp": 1776223879, "source": "europesun.com", "url": "http://www.europesun.com/news/278984446/eu-country-suspends-defense-agreement-with-israel", "entities": ["Giorgia Meloni", "Antonio Tajani", "Jonathan Peled", "Benjamin Netanyahu", "Pedro Sanchez"], "impacted_assets": ["Gold", "USD"], "volatility_implication": "Increase", "llm_tone_score": -2}} diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-14/qdrant_macro_inflation_employment_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-14/qdrant_macro_inflation_employment_processed.jsonl new file mode 100644 index 0000000..df6d2cd --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-14/qdrant_macro_inflation_employment_processed.jsonl @@ -0,0 +1,7 @@ +{"id": "919a7702-4dfc-533a-9faf-4bb5007ca67b", "text": "Chancellor to hold talks with US counterpart after strong criticism of Iran war. The escalating tensions between the US and Iran have led to a global economic shock, with the IMF slashing Britain's economic growth forecast. The conflict has also sent energy prices soaring, which could impact gold and oil prices. The Chancellor's criticism of the US actions in the Middle East may lead to increased market volatility, as investors become more risk-averse.\n\nThe macro transmission mechanism is as follows: The conflict in the Gulf has led to a global economic shock, which has impacted Britain's economic growth forecast. This has increased uncertainty and volatility in financial markets, making investors more cautious and potentially driving up gold prices.", "metadata": {"topic": "macro_inflation_employment", "title": "Chancellor to hold talks with US counterpart after strong criticism of Iran war", "original_title": "Chancellor to hold talks with US counterpart after strong criticism of Iran war", "publish_date": "2026-04-15T03:29:41Z", "publish_timestamp": 1776223781, "source": "wharfedaleobserver.co.uk", "url": "https://www.wharfedaleobserver.co.uk/news/national/26021877.chancellor-hold-talks-us-counterpart-strong-criticism-iran-war/", "entities": ["Scott Bessent", "Rishi Sunak", "Andrew Bailey", "Donald Trump", "Keir Starmer", "Xi Jinping"], "impacted_assets": ["Gold", "Oil", "USD"], "volatility_implication": "Increase", "llm_tone_score": -2}} +{"id": "df7fe02c-4e0a-5257-8759-980baa207a0c", "text": "Reality Check on the Introduction of the Euro in Hungary: A Very High Stakes Game for Those Who Hoped for 2030. The article discusses the feasibility of introducing the Euro in Hungary by 2030. The analysis highlights the country's significant distance from meeting the Maastricht criteria, particularly regarding inflation stability and public debt/GDP ratio. The Hungarian National Bank's data shows that the country's public debt is increasing, and its GDP-based public deficit remains above the 3% threshold. This suggests a challenging path ahead for Hungary to meet the Eurozone's requirements, which may lead to decreased market volatility and potentially negative sentiment for gold and silver prices.", "metadata": {"topic": "macro_inflation_employment", "title": "Reality Check on the Introduction of the Euro in Hungary: A Very High Stakes Game for Those Who Hoped for 2030", "original_title": "Kiderült a meztelen igazság az euró magyarországi bevezetéséről : nagyon ráfázhat , aki a 2030 - as dátumban reménykedett", "publish_date": "2026-04-15T03:29:41Z", "publish_timestamp": 1776223781, "source": "penzcentrum.hu", "url": "https://www.penzcentrum.hu/gazdasag/20260415/kiderult-a-meztelen-igazsag-az-euro-magyarorszagi-bevezeteserol-nagyon-rafazhat-aki-a-2030-as-datumban-remenykedett-1196964", "entities": ["Tisza Párt", "European Central Bank (ECB)", "Hungarian National Bank (MNB)"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Decrease", "llm_tone_score": -3}} +{"id": "dbf666e4-2f7a-56db-8895-426c56b871d0", "text": "How Much Do You Really Need to Retire?. The article discusses the importance of having a clear plan for retirement, including considering factors such as monthly expenses, expected lifespan, and investment returns. The author emphasizes that a simple rule-of-thumb approach may not be sufficient, especially in France where inflation and interest rates are lower than in some other countries. The article provides examples of how different monthly expenses and expected lifespans can affect the required retirement savings, highlighting the need for individualized planning. While the content is not directly related to Gold/Silver prices, it does touch on broader macroeconomic themes (inflation, interest rates) that could indirectly impact these assets.\n\nNote: The article's focus on French financial products and cultural context means that its relevance to global markets and asset classes may be limited.", "metadata": {"topic": "macro_inflation_employment", "title": "How Much Do You Really Need to Retire?", "original_title": " « Demain , jarrête ! » : quel montant faut - il vraiment avoir en banque pour tout quitter et vivre libre ? ", "publish_date": "2026-04-15T03:29:41Z", "publish_timestamp": 1776223781, "source": "sixactualites.fr", "url": "https://sixactualites.fr/retraites/demain-jarrete-quel-montant-faut-il-vraiment-avoir-en-banque-pour-tout-quitter-et-vivre-libre/106597/", "entities": ["None explicitly mentioned", "but references to France and French financial products (e.g.", "Livret A) are present."], "impacted_assets": ["Equities", "Gold/Silver (indirectly)", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "27f5d494-28f3-5db8-9211-43e18bb8750e", "text": "Italian Economy Growth Forecast Revised Downward Amid Global Uncertainty and Structural Challenges. The Italian economy is expected to slow down in 2026 and 2027 due to global uncertainty and structural challenges. The country's growth rate could stall at around 0.3% in 2026 and 0.4% in 2027, with the risk of a new decade of stagnation. The analysis highlights the need for structural reforms to address issues such as high taxes, lack of investment, and skills obsolescence. The report also notes that the Italian economy has been characterized by a decline in growth rates over the past few decades, from 3.7% between 1966 and 1980 to 1.8% between 1981 and 2007, with stagnation in recent years.", "metadata": {"topic": "macro_inflation_employment", "title": "Italian Economy Growth Forecast Revised Downward Amid Global Uncertainty and Structural Challenges", "original_title": "Confcom , crescita +0 , 3 % nel 2026 e rischio stagnazione – Padovanews", "publish_date": "2026-04-15T03:29:41Z", "publish_timestamp": 1776223781, "source": "padovanews.it", "url": "https://www.padovanews.it/2026/04/15/confcom-crescita-03-nel-2026-e-rischio-stagnazione/", "entities": ["Confcommercio", "Carlo Sangalli", "Mariano Bella"], "impacted_assets": ["Equities", "Gold", "Oil", "EURUSD"], "volatility_implication": "Increase", "llm_tone_score": -3}} +{"id": "1b3c6216-eb7b-55cc-ab8d-8bc810335094", "text": "Producer Prices Rise Sharply Due to Energy Surge Linked to Iran War. Rising energy costs linked to the Iran war pushed US wholesale prices higher in March, adding to inflation concerns and complicating the Federal Reserve's policy outlook. The producer price index rose 0.5% from February and 4% year-on-year, driven by an 8.5% surge in energy prices. This adds pressure on the Fed to consider rate hikes or maintain a neutral stance, which may support gold and silver prices while increasing market fear/VIX.", "metadata": {"topic": "macro_inflation_employment", "title": "Producer Prices Rise Sharply Due to Energy Surge Linked to Iran War", "original_title": "Producer prices rise sharply on energy surge from Iran war", "publish_date": "2026-04-15T03:29:41Z", "publish_timestamp": 1776223781, "source": "europesun.com", "url": "http://www.europesun.com/news/278983984/producer-prices-rise-sharply-on-energy-surge-from-iran-war", "entities": ["Federal Reserve", "President Donald Trump", "International Energy Agency"], "impacted_assets": ["Gold", "Silver", "USD", "Oil"], "volatility_implication": "Increase", "llm_tone_score": 2}} +{"id": "8b40ead8-47fb-5d09-a65f-6c4e298f521b", "text": "Prospects Of Iran Playing Ball With U.S. Causes Oil To Plunge By Nearly 8%. The oil market is buoyed by hopes of a de-escalation of hostilities between Iran and the US, leading to a 7% plunge in West Texas Intermediate prices. This development could temporarily add to oil outages but focus on the possibility of an agreement rather than short-term risks. The International Energy Agency expects global oil demand to contract this year due to the war's impact, with initial cuts coming from the Middle East and Asia Pacific.", "metadata": {"topic": "macro_inflation_employment", "title": "Prospects Of Iran Playing Ball With U.S. Causes Oil To Plunge By Nearly 8%", "original_title": "Prospects Of Iran Playing Ball With U . S . Causes Oil To Plunge By Nearly 8 % ", "publish_date": "2026-04-15T03:29:41Z", "publish_timestamp": 1776223781, "source": "shipandbunker.com", "url": "https://shipandbunker.com/news/world/571889-prospects-of-iran-playing-ball-with-us-causes-oil-to-plunge-by-nearly-8", "entities": ["Rachel Ziemba", "Peter Tuz", "International Energy Agency"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "8bacbbd1-1af3-5963-81a8-eed95e4a4f34", "text": "Colombian Retail Giant Makro Launches New Promotions for Essential Products. Colombian retail giant Makro has launched a new campaign called \"Precios Felices\" aimed at stimulating domestic consumption by offering aggressive discounts on essential products. The initiative focuses on democratizing savings for families and small businesses, allowing them to access high-quality products without compromising their monthly budgets. This move may have implications for inflation and consumer spending patterns in Colombia.\n\nThe campaign's emphasis on reducing prices for basic food items like fruits, vegetables, and proteins could potentially impact the local economy and consumer behavior. While this news does not directly affect gold or silver prices, it may contribute to a more stable economic environment in Colombia, which could have indirect effects on global markets.", "metadata": {"topic": "macro_inflation_employment", "title": "Colombian Retail Giant Makro Launches New Promotions for Essential Products", "original_title": "Supermercado en Colombia sigue pisando fuerte y lanzó nuevos remates en productos : de esto se trata", "publish_date": "2026-04-15T03:29:41Z", "publish_timestamp": 1776223781, "source": "noticiasrcn.com", "url": "https://www.noticiasrcn.com/economia/makro-anuncio-nuevo-remate-de-productos-1012163", "entities": ["Makro", "Colombia"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 1}} diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-16/qdrant_asset_metals_derivatives_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-16/qdrant_asset_metals_derivatives_processed.jsonl new file mode 100644 index 0000000..9f29ca8 --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-16/qdrant_asset_metals_derivatives_processed.jsonl @@ -0,0 +1,5 @@ +{"id": "520f060b-9c84-5d78-9423-ba3a7cdfbe43", "text": "Formation Metals Reports Positive Gold Drill Results at N2 Project. Formation Metals announced positive gold drill results at its N2 project in Quebec. The company reported multiple high-grade intercepts, including 1.8 g/t Au over 21.9 meters and 1.37 g/t Au over 24.0 meters. These results confirm the geological continuity of the A-Zone and suggest a significant open-pit target. With a strong working capital position and no debt, Formation Metals is well-positioned to continue exploring its N2 project and potentially unlocking value for shareholders. The positive drill results are likely to increase market volatility and boost gold prices.", "metadata": {"topic": "asset_metals_derivatives", "title": "Formation Metals Reports Positive Gold Drill Results at N2 Project", "original_title": "Formation Metals durchteuft 1 , 8 g / t Au auf 21 , 9 m , östlich von 1 , 75 g / t Au auf 30 , 4 m auf fortgeschrittenem Goldprojekt N2 : Bohrungen bestätigen Beständigkeit von 300 m innerhalb von 5 km entlang von mineralisiertem Streichen", "publish_date": "2026-04-16T12:32:28Z", "publish_timestamp": 1776342748, "source": "finanznachrichten.de", "url": "https://www.finanznachrichten.de/nachrichten-2026-04/68216726-formation-metals-durchteuft-1-8-g-t-au-auf-21-9-m-oestlich-von-1-75-g-t-au-auf-30-4-m-auf-fortgeschrittenem-goldprojekt-n2-bohrungen-bestaetigen-bestae-248.htm", "entities": ["Formation Metals Inc.", "Deepak Varshney", "Matagami", "Quebec"], "impacted_assets": ["Equities", "Gold"], "volatility_implication": "Increase", "llm_tone_score": 3}} +{"id": "1b451587-3a3c-5000-833c-4e1ea973ac0f", "text": "Oil Trades Lower on De-escalation Hopes; US Crude Exports Jump to Record Levels. The oil market is edging lower amid hopes of a ceasefire extension between the US and Iran. However, the physical market remains tight due to pipeline diversions and Strait of Hormuz disruptions. US crude exports jumped to record levels, while domestic production forecasts suggest little change this year. Meanwhile, European gas prices are easing, and copper prices rose on optimism about de-escalation. The macro transmission mechanism is driven by the impact of Middle East tensions on global energy markets, with a potential supply response from US producers if disruptions persist.\n\nNote: The tone score is neutral because there are no clear directional macro drivers that would significantly impact gold or silver prices.", "metadata": {"topic": "asset_metals_derivatives", "title": "Oil Trades Lower on De-escalation Hopes; US Crude Exports Jump to Record Levels", "original_title": "The Commodities Feed : Oil trades lower on de - escalation hopes | Hellenic Shipping News Worldwide", "publish_date": "2026-04-16T12:32:28Z", "publish_timestamp": 1776342748, "source": "hellenicshippingnews.com", "url": "https://www.hellenicshippingnews.com/the-commodities-feed-oil-trades-lower-on-de-escalation-hopes/", "entities": ["United States", "Iran", "Energy Information Administration (EIA)", "Baker Hughes", "European Union"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "485c2082-7e3f-5654-a98a-74ae082c56c0", "text": "The Sudanese Economy Under Two Wars. The article discusses the devastating impact of two wars on the Sudanese economy. The country's agricultural potential is significant, but it relies heavily on imported energy and lacks strategic reserves. The economic crisis has led to a 37.5% decline in GDP, with 4.6 million jobs lost and 64% of the population living in extreme poverty. The second war, triggered by tensions in the Strait of Hormuz, has further exacerbated the crisis, making Sudan one of the most vulnerable economies globally.", "metadata": {"topic": "asset_metals_derivatives", "title": "The Sudanese Economy Under Two Wars", "original_title": "الاقتصاد السوداني في ظل حربين", "publish_date": "2026-04-16T12:32:28Z", "publish_timestamp": 1776342748, "source": "sudanile.com", "url": "https://sudanile.com/%D8%A7%D9%84%D8%A7%D9%82%D8%AA%D8%B5%D8%A7%D8%AF-%D8%A7%D9%84%D8%B3%D9%88%D8%AF%D8%A7%D9%86%D9%8A-%D9%81%D9%8A-%D8%B8%D9%84-%D8%AD%D8%B1%D8%A8%D9%8A%D9%86/", "entities": ["Omar Sied Ahmed", "Sudan", "Libya", "Chad", "South Sudan", "Saudi Arabia"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Increase", "llm_tone_score": -4}} +{"id": "1d8aca9d-502c-5f6d-be55-ba2f7c0c6387", "text": "Greek Stock Market: Selective Moves and Increased Volatility. The Greek stock market is experiencing selective moves and increased volatility. While some blue chips are rising sharply, others are declining. The overall tone remains neutral, with no clear directional macro drivers. The global markets are also showing mixed signals, with the US and European indices moving in different directions.", "metadata": {"topic": "asset_metals_derivatives", "title": "Greek Stock Market: Selective Moves and Increased Volatility", "original_title": "Χρηματιστήριο : Επιλεκτικές κινήσεις και αυξημένη μεταβλητότητα", "publish_date": "2026-04-16T12:32:28Z", "publish_timestamp": 1776342748, "source": "capital.gr", "url": "https://www.capital.gr/agores/3985670/xrimatistirio-epilektikes-kiniseis-kai-auximeni-metablitotita/", "entities": ["Metlen", "ΓΕΚ ΤΕΡΝΑ", "Λάμδα", "Aegean", "Πειραιώς", "Alpha", "ΕΤΕ", "Eurobank", "Credia", "ΔΤΡ", "ΟΛΘ", "Alter Ego", "Qualco", "Intralot"], "impacted_assets": ["Equities", "Gold"], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "7cc24cf0-3355-5b7b-8bc8-3ccc77387d30", "text": "Formation Metals Inc. Reports Positive Gold Drill Results at N2 Project. Formation Metals Inc. announced positive gold drill results from its N2 project in Quebec, Canada. The company reported multiple high-grade gold intercepts, including 1.8 g/t Au over 21.9 meters and 1.37 g/t Au over 24.0 meters. These results confirm the geological continuity of the A-Zone, which is now considered a solid mineralized gold system with potential for further exploration and development. The company's working capital stands at approximately CAD 10.5 million, leaving it debt-free.", "metadata": {"topic": "asset_metals_derivatives", "title": "Formation Metals Inc. Reports Positive Gold Drill Results at N2 Project", "original_title": "newratings . de", "publish_date": "2026-04-16T12:32:28Z", "publish_timestamp": 1776342748, "source": "newratings.de", "url": "https://www.newratings.de/du/main/company_headline.m?nid=19666857", "entities": ["Formation Metals Inc.", "Quebec", "Matagami", "Canada"], "impacted_assets": ["Gold", "Equities"], "volatility_implication": "Neutral", "llm_tone_score": 1}} diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-16/qdrant_macro_central_banks_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-16/qdrant_macro_central_banks_processed.jsonl new file mode 100644 index 0000000..1273ab3 --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-16/qdrant_macro_central_banks_processed.jsonl @@ -0,0 +1,9 @@ +{"id": "76f45bb4-ab59-5f41-995e-ee4a5cf44362", "text": "Trump's Actions Against Powell and the Fed are Working Against Him. President Trump's actions against the Fed and its Chair Jerome Powell are having an unintended consequence - making rate cuts less likely. The recent war with Iran has driven up inflation, and the Fed is now more cautious about cutting rates. Additionally, Trump's attempts to push out Fed officials have been unsuccessful, which may keep Powell in place for longer. This development could lead to a hike in interest rates instead of a cut, negatively impacting gold and silver prices.", "metadata": {"topic": "macro_central_banks", "title": "Trump's Actions Against Powell and the Fed are Working Against Him", "original_title": "Trump own actions against Powell and the Fed are working against him", "publish_date": "2026-04-16T12:28:19Z", "publish_timestamp": 1776342499, "source": "edition.cnn.com", "url": "https://edition.cnn.com/2026/04/16/economy/powell-fed-trump-interest-rates", "entities": ["Donald Trump", "Jerome Powell", "Federal Reserve", "Iran", "United States", "Israel"], "impacted_assets": ["Gold", "Silver", "USD", "Equities", "Oil"], "volatility_implication": "Increase", "llm_tone_score": -3}} +{"id": "a92ccaec-5fd4-5789-861a-358e1123ac27", "text": "Eurozone Inflation Shifts Focus to ECB Signals Amid Escalating Iran Conflict. The escalating Iran conflict has driven energy prices higher, posing a structural problem for the global economy. Rising inflation pressures may lead to increased risks for interest rate cuts and market volatility. However, this crisis also presents opportunities for companies that profit from high energy prices, such as oil and gas producers, utilities, renewable energy providers, and select commodity and agricultural stocks. Our special report highlights three stocks with a solid business model, attractive valuation, and long-term potential.\n\nThe tone score is +2 because the article discusses the potential benefits of high energy prices for certain companies, which could lead to increased demand for gold and other safe-haven assets. The ECB's focus on inflation signals also suggests a more hawkish monetary policy stance, which could support gold prices.", "metadata": {"topic": "macro_central_banks", "title": "Eurozone Inflation Shifts Focus to ECB Signals Amid Escalating Iran Conflict", "original_title": "EUR / JPY gibt leicht nach , da die höhere Inflation in der Eurozone den Fokus auf EZB - Signale verlagert", "publish_date": "2026-04-16T12:28:19Z", "publish_timestamp": 1776342499, "source": "finanznachrichten.de", "url": "https://www.finanznachrichten.de/nachrichten-2026-04/68216751-eur-jpy-gibt-leicht-nach-da-die-hoehere-inflation-in-der-eurozone-den-fokus-auf-ezb-signale-verlagert-545.htm", "entities": ["European Central Bank (ECB)", "Iran", "Eurozone"], "impacted_assets": ["Equities", "Gold", "Oil", "EUR/JPY"], "volatility_implication": "Increase", "llm_tone_score": 2}} +{"id": "eb2f5e06-bd13-5064-af91-282bd7f2ae9a", "text": "VDSC's Chairman Discusses Relationship with KIDO Foods. The chairman of Vietnam's Dragon Securities Company (VDSC) discussed the company's relationship with KIDO Foods, a long-term shareholder. He emphasized that KIDO Foods is a supportive partner, providing financial resources and contributing to VDSC's capital base. The chairman also highlighted the challenges faced by VDSC due to high interest rates, but expressed optimism about the company's growth prospects driven by Vietnam's GDP targets, foreign investment flows, and corporate earnings.\n\nThe article does not have a direct impact on gold or silver prices, but it provides insights into the Vietnamese financial market and the country's economic outlook. The tone is neutral, as there are no significant macroeconomic drivers that would affect the precious metals markets.", "metadata": {"topic": "macro_central_banks", "title": "VDSC's Chairman Discusses Relationship with KIDO Foods", "original_title": "Chủ tịch Chứng khoán Rồng Việt nói về mối quan hệ với KIDO Foods", "publish_date": "2026-04-16T12:28:19Z", "publish_timestamp": 1776342499, "source": "dantri.com.vn", "url": "https://dantri.com.vn/kinh-doanh/chu-tich-chung-khoan-rong-viet-noi-ve-moi-quan-he-voi-kido-foods-20260416175340107.htm", "entities": ["Nguyễn Miên Tuấn", "KIDO Foods", "Nutifood", "VDSC"], "impacted_assets": ["Equities", "Gold"], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "7a99f7d9-a721-5abd-affe-fd9c2b4ca187", "text": "Why Gold and Silver Prices are Rising on a Weaker Dollar and Geopolitical Tensions?. The article highlights the rising prices of gold and silver due to a weaker US dollar, geopolitical tensions, and shifting expectations around global interest rates. The macro transmission mechanism is driven by the weakening dollar, which increases demand for safe-haven assets like gold and silver, while the geopolitical tensions surrounding the Iran conflict add to the upward momentum.", "metadata": {"topic": "macro_central_banks", "title": "Why Gold and Silver Prices are Rising on a Weaker Dollar and Geopolitical Tensions?", "original_title": "Why gold , silver are rising on weak dollar & geopolitical tensions ? ", "publish_date": "2026-04-16T12:28:19Z", "publish_timestamp": 1776342499, "source": "thehindubusinessline.com", "url": "https://www.thehindubusinessline.com/markets/gold/gold-silver-prices-rise-on-weak-dollar-geopolitical-cues-analysts-see-near-term-volatility/article70868399.ece", "entities": ["Gaurav Garg", "Ponmudi R", "Enrich Money", "Lemonn Markets Desk"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Increase", "llm_tone_score": 2}} +{"id": "10610233-3552-5d0c-bef0-76cf0686f8ec", "text": "AUD/USD Rally at Risk of Minor Mean Reversion Decline. The Australian dollar has rallied significantly since the US-Iran ceasefire agreement, mirroring risk-off movements in equities. While the RBA's hawkish guidance hasn't deterred the AUD/USD rally, a minor mean reversion decline below 0.7200 could be imminent before a new upleg begins.", "metadata": {"topic": "macro_central_banks", "title": "AUD/USD Rally at Risk of Minor Mean Reversion Decline", "original_title": "Chart alert : AUD / USD 360 pips rally at risk of a minor mean reversion decline below 0 . 7200 before new upleg", "publish_date": "2026-04-16T12:28:19Z", "publish_timestamp": 1776342499, "source": "marketpulse.com", "url": "https://www.marketpulse.com/markets/chart-alert-audusd-360-pips-rally-at-risk-of-a-minor-mean-reversion-decline-below-07200-before-new-upleg/", "entities": ["Australian dollar", "US-Iran war", "RBA (Reserve Bank of Australia)", "USD/EUR", "euro"], "impacted_assets": ["Equities", "Gold", "Oil", "AUD/USD"], "volatility_implication": "Neutral", "llm_tone_score": 1}} +{"id": "b02c9963-fc86-50ec-8c73-d0bf53918cd3", "text": "UAE Highlights Proactive Approach to Financial Resilience at Washington Meetings. The Central Bank of the UAE participated in international meetings, highlighting its proactive approach to financial resilience. Governor Khaled Mohamed Balama delivered a keynote address on global economic developments and geopolitical challenges, emphasizing the UAE's efforts to enhance financial sector efficiency. This event has no direct impact on Gold/Silver prices but may contribute to broader market sentiment.\n\nNote: The tone score is neutral as there are no clear directional macro drivers or significant events that would directly affect gold/silver prices.", "metadata": {"topic": "macro_central_banks", "title": "UAE Highlights Proactive Approach to Financial Resilience at Washington Meetings", "original_title": "CBUAE highlights UAE proactive approach to financial resilience in Washington", "publish_date": "2026-04-16T12:28:19Z", "publish_timestamp": 1776342499, "source": "irishsun.com", "url": "http://www.irishsun.com/news/278987031/cbuae-highlights-uae-proactive-approach-to-financial-resilience-in-washington", "entities": ["Central Bank of the UAE (CBUAE)", "International Monetary Fund (IMF)", "World Bank Group", "G20", "G24", "BRICS", "Eesti Pank", "National Bank of Georgia"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "79886d78-6f3a-5742-bdcb-ac6b5ea52df3", "text": "Senator Thom Tillis Vows to Block Jerome Powell's Replacement at Federal Reserve. Senator Thom Tillis has vowed to block the nomination of Kevin Warsh to replace Jerome Powell as head of the Federal Reserve. This is a principled political act aimed at forcing the Trump Department of Justice to drop its investigation into Powell or provide evidence of corruption. The move may have indirect implications for USD and Equities, but the macro transmission mechanism is unclear.", "metadata": {"topic": "macro_central_banks", "title": "Senator Thom Tillis Vows to Block Jerome Powell's Replacement at Federal Reserve", "original_title": "Say What You Mean", "publish_date": "2026-04-16T12:28:19Z", "publish_timestamp": 1776342499, "source": "dailykos.com", "url": "https://www.dailykos.com/stories/2026/4/16/800020794/community/this/", "entities": ["Senator Thom Tillis", "Kevin Warsh", "Jerome Powell", "Donald Trump", "Stephen Miller"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "8f92dbba-2454-5b29-a5f7-7c996405b9d7", "text": "Russian Inflation Expectations Fall to 12.9% in April. Russian inflation expectations have decreased to 12.9% in April, with those having savings expecting a slightly lower rate of 11.4%. This moderation in inflationary pressures may lead to a slight increase in gold and silver prices as investors seek safe-haven assets. The USD might also benefit from the reduced inflation concerns, potentially leading to a minor decrease in precious metal values.", "metadata": {"topic": "macro_central_banks", "title": "Russian Inflation Expectations Fall to 12.9% in April", "original_title": "Инфляционные ожидания россиян в апреле сократились до 12 , 9 % ", "publish_date": "2026-04-16T12:28:19Z", "publish_timestamp": 1776342499, "source": "vedomosti.ru", "url": "https://www.vedomosti.ru/economics/news/2026/04/16/1190832-inflyatsionnie-ozhidaniya", "entities": ["Russia", "citizens with savings", "citizens without savings"], "impacted_assets": ["Gold", "Silver", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 1}} +{"id": "d869cdb8-a8fb-5012-9522-0f277de07fcd", "text": "Brazilian Government Projects GDP Growth of 2.56% and Inflation of 3.04% in 2027. The Brazilian government projects GDP growth of 2.56% in 2027, with inflation expected to remain stable at 3.04%. The report also forecasts moderate wage growth and a gradual reduction in interest rates. These projections suggest a positive economic outlook for Brazil, which may have a neutral impact on global markets.", "metadata": {"topic": "macro_central_banks", "title": "Brazilian Government Projects GDP Growth of 2.56% and Inflation of 3.04% in 2027", "original_title": "Governo projeta crescimento de 2 , 56 % do PIB e inflao de 3 , 04 % em 2027", "publish_date": "2026-04-16T12:28:19Z", "publish_timestamp": 1776342499, "source": "brasil247.com", "url": "https://www.brasil247.com:443/economia/governo-projeta-crescimento-de-2-56-do-pib-e-inflacao-de-3-04-em-2027-u72b8zti", "entities": ["Brazilian government", "Ministry of Finance", "Ministry of Planning and Budget", "Congress National"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 1}} diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-16/qdrant_macro_geopolitics_risk_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-16/qdrant_macro_geopolitics_risk_processed.jsonl new file mode 100644 index 0000000..28ce508 --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-16/qdrant_macro_geopolitics_risk_processed.jsonl @@ -0,0 +1,4 @@ +{"id": "475add2f-79b9-58e2-a4f5-34afabc0651c", "text": "Three Misconceptions About the $402B Semiconductor Foundry Industry. This article discusses the semiconductor foundry industry's growth to $402 billion in 2026, highlighting its complexity and connection to geopolitics and AI capex. The piece also clarifies TSMC's market share, emphasizing that its dominance at the leading edge is often understated due to inconsistent definitions of \"advanced.\"", "metadata": {"topic": "macro_geopolitics_risk", "title": "Three Misconceptions About the $402B Semiconductor Foundry Industry", "original_title": "Three Misconceptions About the $402B Semiconductor Foundry Industry", "publish_date": "2026-04-16T12:30:54Z", "publish_timestamp": 1776342654, "source": "design-reuse.com", "url": "https://www.design-reuse.com/news/202530378-three-misconceptions-about-the-402b-semiconductor-foundry-industry/", "entities": ["Pierre Cambou", "Yole Développement", "TSMC"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "7a448934-3774-5828-97e2-4774fb255b8f", "text": "Pakistani Army Chief Visits Tehran in Hopes of Renewed US-Iran Talks. The Pakistani army chief's visit to Tehran aims to extend the ceasefire between Israel and Iran-backed Hezbollah. While this development may lead to a deal, uncertainty remains as both sides continue exchanging fire across the border. The meeting comes amid progress in US-Iran talks, with regional officials reporting an \"in-principle agreement\" to extend the ceasefire. This event is unlikely to have a significant impact on gold or silver prices, but it may contribute to market volatility if tensions escalate or de-escalate.", "metadata": {"topic": "macro_geopolitics_risk", "title": "Pakistani Army Chief Visits Tehran in Hopes of Renewed US-Iran Talks", "original_title": "Pakistani army chief visits Tehran in hopes of renewed US - Iran talks", "publish_date": "2026-04-16T12:30:54Z", "publish_timestamp": 1776342654, "source": "redlandsdailyfacts.com", "url": "https://www.redlandsdailyfacts.com/2026/04/16/us-iran-war-israel/", "entities": ["Pakistan", "Iran", "United States", "Israel", "Lebanon"], "impacted_assets": ["Equities", "Oil", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "43cfb012-8a21-5232-9ad4-874857ec06b1", "text": "Eurozone Inflation Surges to 2.6% in March Due to Energy Price Increase Following Iran Conflict. The eurozone inflation rate surged to 2.6% in March, driven by a 5.1% increase in energy prices following the Iran conflict. This is the highest inflation rate since July 2024 and reflects the immediate impact of the war on oil prices. The rise in energy costs has also led to higher food prices, with fresh foods increasing by 4.2%. The underlying inflation rate, excluding energy and food, remained stable at 2.3%. This development is likely to support gold and silver prices, while also increasing market fear and volatility.\n\nNote: The tone score of +3 reflects the bullish impact on gold and silver prices due to the increase in energy costs and potential for higher inflation.", "metadata": {"topic": "macro_geopolitics_risk", "title": "Eurozone Inflation Surges to 2.6% in March Due to Energy Price Increase Following Iran Conflict", "original_title": "La inflación de la eurozona repunta al 2 , 6 % en marzo por el encarecimiento de la energía tras la guerra en Irán", "publish_date": "2026-04-16T12:30:54Z", "publish_timestamp": 1776342654, "source": "laprovincia.es", "url": "https://www.laprovincia.es/economia/2026/04/16/inflacion-eurozona-repunta-2-6-marzo-encarecimiento-energia-guerra-iran-129169885.html", "entities": ["European Union", "Eurostat", "Iran", "United States", "Israel", "Russia", "Ukraine"], "impacted_assets": ["Gold", "Silver", "Oil", "USD"], "volatility_implication": "Increase", "llm_tone_score": 3}} +{"id": "b32397d3-13bf-5a0d-9585-a485899b107c", "text": "TSMC Raises Revenue Forecast for 2026 Due to AI Demand. TSMC, a leading semiconductor manufacturer, has raised its revenue forecast for 2026 due to strong demand for AI-related chips. The company expects a 30%+ increase in revenues, driven by the growing demand for advanced chips used in AI systems. This news is bullish for gold and silver prices as it suggests a continued strong demand for technology and innovation, which can support higher precious metal prices.\n\nThe macro transmission mechanism at play here is the increasing demand for AI-related technologies, which drives up demand for semiconductors and other related components. This, in turn, supports the overall tech sector and potentially leads to increased investment and consumption, which can benefit gold and silver prices.", "metadata": {"topic": "macro_geopolitics_risk", "title": "TSMC Raises Revenue Forecast for 2026 Due to AI Demand", "original_title": "TSMC alza le previsioni : nel 2026 i ricavi aumenteranno ancora grazie allIA", "publish_date": "2026-04-16T12:30:54Z", "publish_timestamp": 1776342654, "source": "multiplayer.it", "url": "https://multiplayer.it/notizie/tsmc-alza-previsioni-2026-ricavi-aumenteranno-ia.html", "entities": ["Taiwan Semiconductor Manufacturing Company (TSMC)", "C.C. Wei", "Samsung"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 2}} diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-16/qdrant_macro_yields_dollar_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-16/qdrant_macro_yields_dollar_processed.jsonl new file mode 100644 index 0000000..513a5aa --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-16/qdrant_macro_yields_dollar_processed.jsonl @@ -0,0 +1,8 @@ +{"id": "79815fab-8a22-5468-8836-a9fe35dd4de4", "text": "Indian Stock Market Update: Sensex and Nifty End Marginally Lower Amid Profit-Booking and Geopolitical Uncertainty. The Indian stock market ended marginally lower on Thursday due to profit-booking and lingering uncertainty around US-Iran talks. Despite this, metals emerged as top performers, supported by firm global commodity prices and a softer dollar. IT stocks also showed resilience, while banking, auto, and consumption stocks came under pressure.", "metadata": {"topic": "macro_yields_dollar", "title": "Indian Stock Market Update: Sensex and Nifty End Marginally Lower Amid Profit-Booking and Geopolitical Uncertainty", "original_title": "Sensex , Nifty pare gains to end marginally lower , Adani Enterprises , Hindalco lead gainers", "publish_date": "2026-04-16T12:30:02Z", "publish_timestamp": 1776342602, "source": "thehindubusinessline.com", "url": "https://www.thehindubusinessline.com/markets/stock-markets-close-lower-on-profit-taking-in-financial-shares/article70868922.ece", "entities": ["Adani Enterprises", "Hindalco", "Vinod Nair", "Ponmudi R", "Sudeep Shah", "Hariprasad K"], "impacted_assets": ["Equities", "Metals", "IT Stocks", "Banking", "Auto", "Consumption"], "volatility_implication": "Neutral", "llm_tone_score": 1}} +{"id": "f7aa4839-a32f-50bb-b164-d96f852547c5", "text": "Cable Eyes 1.3696 After Reclaiming Key Moving Averages, Bulls Defend 1.3500. The GBP/USD has broken out of its descending trendline and reclaimed its 100-day and 200-day moving averages, indicating a shift in macro bias from \"sell the rallies\" to \"buy the dips.\" This development suggests that bulls are defending the 1.3500 level and eyeing the next major structural hurdle at 1.3696. The Daily RSI is showing healthy bullish momentum with plenty of runway before hitting the overbought threshold, indicating a potential continuation of the uptrend.", "metadata": {"topic": "macro_yields_dollar", "title": "Cable Eyes 1.3696 After Reclaiming Key Moving Averages, Bulls Defend 1.3500", "original_title": "Cable eyes 1 . 3696 after reclaiming key moving averages , bulls defend 1 . 3500", "publish_date": "2026-04-16T12:30:02Z", "publish_timestamp": 1776342602, "source": "marketpulse.com", "url": "https://www.marketpulse.com/markets/cable-eyes-13696-after-reclaiming-key-moving-averages-bulls-defend-13500/", "entities": ["GBP/USD", "Federal Reserve"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "f5356de4-9e9b-5dc9-b691-c8af5f132cae", "text": "3 Absurdly Cheap Stocks to Buy With $1,000 While the Market Is Nervous. The article highlights three undervalued stocks that can thrive in any market environment. Domino's Pizza has a competitive advantage through its delivery model and technology, while Clorox is a consumer staples conglomerate with a discounted stock price due to past struggles. Target, despite its challenges, offers an attractive valuation. These stocks are considered safe and undervalued, making them suitable for investors seeking dividend income and potential growth.\n\nNote: As the article does not explicitly mention macroeconomic or financial market drivers that would directly impact gold or silver prices, I assigned a tone score of 0 (Neutral).", "metadata": {"topic": "macro_yields_dollar", "title": "3 Absurdly Cheap Stocks to Buy With $1,000 While the Market Is Nervous", "original_title": "3 Absurdly Cheap Stocks to Buy With $1 , 000 While the Market Is This Nervous", "publish_date": "2026-04-16T12:30:02Z", "publish_timestamp": 1776342602, "source": "fool.com", "url": "https://www.fool.com/investing/2026/04/16/3-absurdly-cheap-stocks-to-buy-with-1000-while-the/?source=iedfolrf0000001", "entities": ["Domino's Pizza", "Clorox", "Target"], "impacted_assets": ["Equities", "Consumer Discretionary", "Consumer Staples"], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "720da795-3ef5-508e-a82c-22a3030dc4b3", "text": "Trump Blocks Strait of Hormuz: Mullah Regime Runs Out of Money for Iran War. The US blockade of the Strait of Hormuz will severely impact Iran's economy by cutting off its main oil export route. This could lead to a financial and inflationary crisis in Iran, making it difficult for the regime to pay its soldiers and paramilitary groups. As a result, protests may resume, potentially with fewer people willing to defend the regime. The US strategy aims to weaken Iran's economy and force the regime to negotiate a deal that addresses US concerns about nuclear weapons and long-range missiles.\n\nNote: The tone score is +3 because the event has a clear bullish impact on gold prices due to increased market fear and uncertainty, which tends to drive up gold demand as a safe-haven asset.", "metadata": {"topic": "macro_yields_dollar", "title": "Trump Blocks Strait of Hormuz: Mullah Regime Runs Out of Money for Iran War", "original_title": "Trump blockiert Straße von Hormus : Mullah - Regime igeht das Geld aus", "publish_date": "2026-04-16T12:30:02Z", "publish_timestamp": 1776342602, "source": "kreiszeitung.de", "url": "http://www.kreiszeitung.de/politik/trump-koennte-mit-genialer-strategie-den-krieg-im-iran-gewinnen-zr-94264746.html", "entities": ["Donald Trump", "Iran", "United States", "Israel"], "impacted_assets": ["Gold", "Oil", "USD"], "volatility_implication": "Increase", "llm_tone_score": 3}} +{"id": "7a99f7d9-a721-5abd-affe-fd9c2b4ca187", "text": "Why Gold and Silver Prices are Rising on a Weaker Dollar and Geopolitical Tensions?. The article highlights the rising prices of gold and silver due to a weaker US dollar, geopolitical tensions, and shifting expectations around global interest rates. The macro transmission mechanism is driven by the weakening dollar, which increases demand for safe-haven assets like gold and silver, while the geopolitical tensions surrounding the Iran conflict add to the upward momentum.", "metadata": {"topic": "macro_yields_dollar", "title": "Why Gold and Silver Prices are Rising on a Weaker Dollar and Geopolitical Tensions?", "original_title": "Why gold , silver are rising on weak dollar & geopolitical tensions ? ", "publish_date": "2026-04-16T12:30:02Z", "publish_timestamp": 1776342602, "source": "thehindubusinessline.com", "url": "https://www.thehindubusinessline.com/markets/gold/gold-silver-prices-rise-on-weak-dollar-geopolitical-cues-analysts-see-near-term-volatility/article70868399.ece", "entities": ["Gaurav Garg", "Ponmudi R", "Enrich Money", "Lemonn Markets Desk"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Increase", "llm_tone_score": 2}} +{"id": "1d8aca9d-502c-5f6d-be55-ba2f7c0c6387", "text": "Greek Stock Market: Selective Moves and Increased Volatility. The Greek stock market is experiencing selective moves and increased volatility. While some blue chips are rising sharply, others are declining. The overall tone remains neutral, with no clear directional macro drivers. The global markets are also showing mixed signals, with the US and European indices moving in different directions.", "metadata": {"topic": "macro_yields_dollar", "title": "Greek Stock Market: Selective Moves and Increased Volatility", "original_title": "Χρηματιστήριο : Επιλεκτικές κινήσεις και αυξημένη μεταβλητότητα", "publish_date": "2026-04-16T12:30:02Z", "publish_timestamp": 1776342602, "source": "capital.gr", "url": "https://www.capital.gr/agores/3985670/xrimatistirio-epilektikes-kiniseis-kai-auximeni-metablitotita/", "entities": ["Metlen", "ΓΕΚ ΤΕΡΝΑ", "Λάμδα", "Aegean", "Πειραιώς", "Alpha", "ΕΤΕ", "Eurobank", "Credia", "ΔΤΡ", "ΟΛΘ", "Alter Ego", "Qualco", "Intralot"], "impacted_assets": ["Equities", "Gold"], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "10610233-3552-5d0c-bef0-76cf0686f8ec", "text": "AUD/USD Rally at Risk of Minor Mean Reversion Decline. The Australian dollar has rallied significantly since the US-Iran ceasefire agreement, mirroring risk-off movements in equities. While the RBA's hawkish guidance hasn't deterred the AUD/USD rally, a minor mean reversion decline below 0.7200 could be imminent before a new upleg begins.", "metadata": {"topic": "macro_yields_dollar", "title": "AUD/USD Rally at Risk of Minor Mean Reversion Decline", "original_title": "Chart alert : AUD / USD 360 pips rally at risk of a minor mean reversion decline below 0 . 7200 before new upleg", "publish_date": "2026-04-16T12:30:02Z", "publish_timestamp": 1776342602, "source": "marketpulse.com", "url": "https://www.marketpulse.com/markets/chart-alert-audusd-360-pips-rally-at-risk-of-a-minor-mean-reversion-decline-below-07200-before-new-upleg/", "entities": ["Australian dollar", "US-Iran war", "RBA (Reserve Bank of Australia)", "USD/EUR", "euro"], "impacted_assets": ["Equities", "Gold", "Oil", "AUD/USD"], "volatility_implication": "Neutral", "llm_tone_score": 1}} +{"id": "7ff6d5db-cafe-5769-a577-c74e8bf0d384", "text": "British Legacy: Occident Meets Orient - The Architecture of Jerusalem is Strongly Influenced by the British Mandate Era.. The article discusses various news stories related to Israel, including the strengthening of the Israeli shekel against the US dollar, Germany's alleged arms exports to Israel, and Apple TV's release of a trailer for an Israeli thriller series. Additionally, Time magazine includes Israeli Prime Minister Benjamin Netanjahu in its list of the 100 most influential people. These events do not have a direct impact on Gold/Silver prices but may contribute to market volatility due to their geopolitical implications.\n\nNote: The tone score is neutral because there are no clear directional macro drivers that would significantly affect Gold/Silver prices.", "metadata": {"topic": "macro_yields_dollar", "title": "British Legacy: Occident Meets Orient - The Architecture of Jerusalem is Strongly Influenced by the British Mandate Era.", "original_title": "16 . 04 . 2026 - Israelnetz", "publish_date": "2026-04-16T12:30:02Z", "publish_timestamp": 1776342602, "source": "israelnetz.com", "url": "https://www.israelnetz.com/2026/04/16/", "entities": ["Benjamin Netanjahu", "Israel", "Iran", "Lebanon", "Germany", "Friedrich Merz", "Apple TV", "Talia Lynne Ronn", "Liras Chamami", "Adam Bizanski", "Dana Idisis"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-18/qdrant_asset_precious_metals_spot_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-18/qdrant_asset_precious_metals_spot_processed.jsonl new file mode 100644 index 0000000..e4ddc52 --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-18/qdrant_asset_precious_metals_spot_processed.jsonl @@ -0,0 +1,6 @@ +{"id": "e7372f0f-783d-5d90-b59d-eeba96e6a72d", "text": "Life jacket worn by a passenger who survived the Titanic auctioned off for over $900,000. This news article reports on the auction of a life jacket worn by Laura Mabel Francatelli, a first-class passenger who survived the Titanic disaster. The item sold for over $1.24 million CAD, setting a record price for a piece of Titanic memorabilia. While this event does not have any direct macro-financial implications, it may contribute to a sense of nostalgia and fascination with the Titanic story, which could indirectly influence market sentiment and volatility.", "metadata": {"topic": "asset_precious_metals_spot", "title": "Life jacket worn by a passenger who survived the Titanic auctioned off for over $900,000", "original_title": "Life jacket worn by a passenger who survived the Titanic auctioned off for over $900 , 000", "publish_date": "2026-04-18T22:04:31Z", "publish_timestamp": 1776549871, "source": "castanetkamloops.net", "url": "https://www.castanetkamloops.net/news/Entertainment/609632/Life-jacket-worn-by-a-passenger-who-survived-the-Titanic-auctioned-off-for-over-900-000", "entities": ["Laura Mabel Francatelli", "Lucy Duff Gordon", "Cosmo Duff Gordon", "RMS Carpathia"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "9f94ca40-5eb0-54cd-a87e-7adf48f44297", "text": "Survivor's Signed Titanic Life Jacket Fetches Record Price. The sale of a life jacket worn by a Titanic survivor for $906,000 is a record-breaking price for a piece of Titanic memorabilia. This event has no direct macro-financial implications and does not affect the prices of Gold or Silver. The story's focus on human interest and historical significance rather than economic drivers keeps the tone neutral.", "metadata": {"topic": "asset_precious_metals_spot", "title": "Survivor's Signed Titanic Life Jacket Fetches Record Price", "original_title": "Survivor signed Titanic life jacket fetches $906 , 000 at united kingdom sale", "publish_date": "2026-04-18T22:04:31Z", "publish_timestamp": 1776549871, "source": "kxlf.com", "url": "https://www.kxlf.com/world/europe/survivors-signed-titanic-life-jacket-fetches-906-000-at-uk-sale", "entities": ["Laura Mabel Francatelli", "Lucy Duff Gordon", "Cosmo Duff Gordon"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "ebbc1c05-5950-54d4-8375-b4e66a16cd10", "text": "Life Jacket Worn by Passenger Who Survived Titanic Auctioned Off for Over $900,000. The auction of a life jacket worn by a passenger who survived the Titanic's sinking has set a new record price. The item sold for over $906,000, with the proceeds likely going to its buyer. This event does not have any direct macro-financial implications or transmission mechanisms that would impact gold or silver prices.", "metadata": {"topic": "asset_precious_metals_spot", "title": "Life Jacket Worn by Passenger Who Survived Titanic Auctioned Off for Over $900,000", "original_title": "Life jacket worn by a passenger who survived the Titanic auctioned off for over $900 , 000", "publish_date": "2026-04-18T22:04:31Z", "publish_timestamp": 1776549871, "source": "pressdemocrat.com", "url": "https://www.pressdemocrat.com/2026/04/18/life-jacket-worn-by-a-passenger-who-survived-the-titanic-auctioned-off-for-over-900000/", "entities": ["Laura Mabel Francatelli", "Lucy Duff Gordon", "Cosmo Duff Gordon"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "1c1d01da-2e7e-51d6-aeb1-9c58dad7e1df", "text": "Cursor Aims to Raise $2 Billion at $50 Billion Valuation, Targeting $6 Billion Revenue Run Rate by 2026. The article highlights Cursor's plans to raise $2 billion at a valuation of $50 billion, driven by its rapid growth and increasing investor confidence. This news is bullish for the market, as it indicates a strong demand for AI-powered coding tools and a potential increase in revenue run rate. The company's focus on building its own models and reducing dependence on third-party providers also reduces risk and increases its chances of long-term success.", "metadata": {"topic": "asset_precious_metals_spot", "title": "Cursor Aims to Raise $2 Billion at $50 Billion Valuation, Targeting $6 Billion Revenue Run Rate by 2026", "original_title": "Cursor Looks to Double Down with $2B Raise at $50B Valuation", "publish_date": "2026-04-18T22:04:31Z", "publish_timestamp": 1776549871, "source": "techstory.in", "url": "https://techstory.in/cursor-looks-to-double-down-with-2b-raise-at-50b-valuation/", "entities": ["Cursor", "Thrive Capital", "Andreessen Horowitz", "Battery Ventures", "NVIDIA", "Anthropic", "OpenAI"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Increase", "llm_tone_score": 3}} +{"id": "735a9a8f-e3e2-5aae-ae6e-9fc43d3a9793", "text": "Taiwan-listed companies' dividend payouts surge to a record high of NT$2.5 trillion, with 118 firms expected to pay out over NT$10 million each.. The surge in dividend payouts by Taiwan-listed companies is expected to reach a record high of NT$2.5 trillion, driven by the strong performance of the Taiwanese economy and the increasing confidence of investors. This trend is likely to boost investor sentiment and drive up demand for equities and gold, leading to increased market volatility.", "metadata": {"topic": "asset_precious_metals_spot", "title": "Taiwan-listed companies' dividend payouts surge to a record high of NT$2.5 trillion, with 118 firms expected to pay out over NT$10 million each.", "original_title": "上市櫃股利發放衝2 . 5兆再創歷史新高 權王5 , 705億元稱冠 | 股市要聞 | 股市", "publish_date": "2026-04-18T22:04:31Z", "publish_timestamp": 1776549871, "source": "udn.com", "url": "https://udn.com/news/story/7251/9450364", "entities": ["Taiwan-listed companies", "National Taiwan Bank (2882)", "First Commercial Bank (2881)", "Taiwan Semiconductor Manufacturing Company (2330)", "Hon Hai Precision Industry Co. Ltd. (2317)", "United Microelectronics Corporation (2303)", "etc."], "impacted_assets": ["Equities", "Gold"], "volatility_implication": "Increase", "llm_tone_score": 3}} +{"id": "7c27b988-5ee6-5c98-b887-1b1c64da9802", "text": "Gold Prices Reach 4-Week High on Global Markets. Gold prices surged to a four-week high as tensions between the US and Iran escalated, driving oil prices above $100 per barrel. The Fed's potential rate decision also contributed to the volatility. As investors seek safe-haven assets amid economic and geopolitical uncertainty, gold demand is expected to remain strong.\n\nThe macro transmission mechanism is that rising tensions in the Middle East and potential interest rate decisions by the Federal Reserve are driving investors towards safe-haven assets like gold, which tends to perform well during times of market stress.", "metadata": {"topic": "asset_precious_metals_spot", "title": "Gold Prices Reach 4-Week High on Global Markets", "original_title": "الذهب يسجل أعلى قمة له خلال 4 أسابيع في البورصة العالمية", "publish_date": "2026-04-18T22:04:31Z", "publish_timestamp": 1776549871, "source": "new-today.co", "url": "https://new-today.co/%D8%A7%D9%84%D8%B0%D9%87%D8%A8-%D9%8A%D8%B3%D8%AC%D9%84-%D8%A3%D8%B9%D9%84%D9%89-%D9%82%D9%85%D8%A9-%D9%84%D9%87-%D8%AE%D9%84%D8%A7%D9%84-4-%D8%A3%D8%B3%D8%A7%D8%A8%D9%8A%D8%B9-%D9%81%D9%8A-%D8%A7/", "entities": ["Iran", "United States", "Federal Reserve"], "impacted_assets": ["Gold", "Oil"], "volatility_implication": "Increase", "llm_tone_score": 2}} diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-18/qdrant_macro_central_banks_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-18/qdrant_macro_central_banks_processed.jsonl new file mode 100644 index 0000000..8b716eb --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-18/qdrant_macro_central_banks_processed.jsonl @@ -0,0 +1,8 @@ +{"id": "4742d43b-f2f6-5229-b2a6-6c1c87579bd0", "text": "Federal Reserve Probe Intensifies Amid Trump's Threats to Fire Powell. The intensifying Federal Reserve probe into the $2.5 billion headquarters renovation project has sparked concerns about political interference in monetary policy. President Trump's threats to fire Fed Chair Jerome Powell have added fuel to the fire, potentially undermining the central bank's independence and increasing market uncertainty. The macro transmission mechanism is a potential increase in USD volatility, which could negatively impact Gold prices.", "metadata": {"topic": "macro_central_banks", "title": "Federal Reserve Probe Intensifies Amid Trump's Threats to Fire Powell", "original_title": "Fed probe intensifies as Trump threatens to fire Powell", "publish_date": "2026-04-18T22:02:16Z", "publish_timestamp": 1776549736, "source": "hongkongherald.com", "url": "http://www.hongkongherald.com/news/278988532/fed-probe-intensifies-as-trump-threatens-to-fire-powell", "entities": ["Jerome Powell", "Donald Trump", "Jeanine Pirro", "Robert Hur", "Thom Tillis", "Kevin Warsh", "Lisa Cook"], "impacted_assets": ["USD", "Equities", "Gold"], "volatility_implication": "Increase", "llm_tone_score": -2}} +{"id": "5f128886-304d-5a01-9435-f597544b1b33", "text": "Trump Backs Fed Probe as Prosecutors Visit HQ Renovation Site. The ongoing investigation into the Federal Reserve's headquarters renovation project has intensified, with prosecutors seeking access to the construction site. President Trump has backed the probe, framing it as a necessary scrutiny of government spending. However, Fed Chair Jerome Powell has argued that the investigation is a pretext to undermine the central bank's independence, raising broader concerns about political interference in U.S. monetary policy. The situation may lead to increased market uncertainty and potentially impact USD and equity markets.", "metadata": {"topic": "macro_central_banks", "title": "Trump Backs Fed Probe as Prosecutors Visit HQ Renovation Site", "original_title": "Trump backs Fed probe as prosecutors visit HQ renovation site", "publish_date": "2026-04-18T22:02:16Z", "publish_timestamp": 1776549736, "source": "myanmarnews.net", "url": "http://www.myanmarnews.net/news/278988532/trump-backs-fed-probe-as-prosecutors-visit-hq-renovation-site", "entities": ["Jerome Powell", "Donald Trump", "Jeanine Pirro", "Kevin Warsh", "Thom Tillis", "Josh Hawley", "Lisa Cook"], "impacted_assets": ["USD", "Equities"], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "da136ffa-b8df-5d9a-a4f2-4ed315b17419", "text": "Mark Carney Named to Time's Most Influential People List for 2026. The article reports that Canadian Prime Minister Mark Carney has been named to Time's Most Influential People List for 2026. This recognition is largely based on his speech at the World Economic Forum in Davos, where he emphasized the need for international cooperation and multilateralism. While this event may not have a direct impact on Gold/Silver prices, it could potentially influence market sentiment and macroeconomic conditions, which may indirectly affect precious metals.", "metadata": {"topic": "macro_central_banks", "title": "Mark Carney Named to Time's Most Influential People List for 2026", "original_title": "Carney lands on Time most influential people list for 2026", "publish_date": "2026-04-18T22:02:16Z", "publish_timestamp": 1776549736, "source": "lethbridgeherald.com", "url": "https://lethbridgeherald.com/news/national-news/2026/04/18/carney-lands-on-times-most-influential-people-list-for-2026/", "entities": ["Mark Carney", "Christine Lagarde", "Justin Trudeau", "Donald Trump", "Mette Frederiksen", "Benjamin Netanyahu", "Pope Leo XIV"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "3f193548-4ac6-5f7a-9abc-cc538e35cf46", "text": "Larry Fink's Double Role as WEF Co-President: Swiss Government Supports Him Despite Conflicts of Interest. The Swiss government has given its backing to Larry Fink as WEF co-president despite concerns about his dual role as CEO of Blackrock. This decision may not have a direct impact on gold or silver prices, but it could contribute to a more stable macro environment, which might lead to increased market confidence and potentially stabilize precious metals.", "metadata": {"topic": "macro_central_banks", "title": "Larry Fink's Double Role as WEF Co-President: Swiss Government Supports Him Despite Conflicts of Interest", "original_title": "Doppelrolle von Larry Fink : Bund stärkt dem WEF - Co - Präsidenten den Rücken", "publish_date": "2026-04-18T22:02:16Z", "publish_timestamp": 1776549736, "source": "nzz.ch", "url": "https://www.nzz.ch/wirtschaft/naechster-nackenschlag-fuer-klaus-schwab-der-bund-laesst-larry-fink-als-wef-praesidenten-gewaehren-trotz-doppelrolle-ld.1933724", "entities": ["Klaus Schwab", "Larry Fink", "André Hoffmann", "World Economic Forum (WEF)", "Eidgenössische Stiftungsaufsicht (ESA)"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "c9a8b110-ab13-56fd-a204-cd8aa26600ea", "text": "Banks in New Zealand Offer Loans for Electric Vehicles Amid Growing Demand. New Zealand's major banks are responding to growing demand for electric vehicles by offering specialized loans. This trend could lead to increased investment in sustainable energy and infrastructure, potentially benefiting gold prices as investors seek safe-haven assets. The article highlights the growth in demand for EVs and related financial products, which could have a positive impact on the overall economy.", "metadata": {"topic": "macro_central_banks", "title": "Banks in New Zealand Offer Loans for Electric Vehicles Amid Growing Demand", "original_title": "So you want to buy an EV - here what your bank could offer", "publish_date": "2026-04-18T22:02:16Z", "publish_timestamp": 1776549736, "source": "rnz.co.nz", "url": "https://www.rnz.co.nz/news/business/592773/so-you-want-to-buy-an-ev-here-s-what-your-bank-could-offer", "entities": ["ASB", "BNZ", "ANZ", "Kiwibank", "Meridian"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 1}} +{"id": "43bc87ab-054a-5f74-8af0-52be544c57a4", "text": "Former Economy Minister Paulo Guedes Criticizes Lula Government and Rules Out Return to Politics. Former Economy Minister Paulo Guedes criticized the economic policy of President Lula's government, citing increased public spending and fiscal flexibility as contributing to rising debt and pressure on interest rates. This commentary may increase market fear/VIX as it implies a potential for higher inflation and interest rates, which could negatively impact gold prices and strengthen the US dollar.", "metadata": {"topic": "macro_central_banks", "title": "Former Economy Minister Paulo Guedes Criticizes Lula Government and Rules Out Return to Politics", "original_title": "Paulo Guedes critica governo Lula e descarta voltar à política", "publish_date": "2026-04-18T22:02:16Z", "publish_timestamp": 1776549736, "source": "bahianoticias.com.br", "url": "https://www.bahianoticias.com.br/noticia/315961-paulo-guedes-critica-governo-lula-e-descarta-voltar-a-politica", "entities": ["Paulo Guedes", "Luiz Inácio Lula da Silva", "Jair Bolsonaro"], "impacted_assets": ["Gold", "USD"], "volatility_implication": "Increase", "llm_tone_score": -2}} +{"id": "75770ef6-0a35-5d85-b147-a8cfc3d55a63", "text": "Differences in Loans for Electric and Gasoline Vehicles at Expomóvil 2026. The article discusses the loan conditions offered by three major banks in Costa Rica for electric and gasoline vehicles at Expomóvil 2026. The banks offer varying interest rates, down payments, and commissions depending on the type of vehicle. This could lead to a shift towards eco-friendly technologies, which may positively impact gold/silver prices if investors perceive a growing demand for sustainable energy solutions.\n\nNote: The tone score is +2 because while the article does not explicitly mention macroeconomic drivers that would directly impact gold/silver prices, it highlights the increasing importance of eco-friendly technologies, which could contribute to a bullish sentiment in the long term.", "metadata": {"topic": "macro_central_banks", "title": "Differences in Loans for Electric and Gasoline Vehicles at Expomóvil 2026", "original_title": "Expomóvil 2026 : estas son las diferencias en los préstamos para vehículos eléctricos y de combustión", "publish_date": "2026-04-18T22:02:16Z", "publish_timestamp": 1776549736, "source": "elfinancierocr.com", "url": "https://www.elfinancierocr.com/finanzas/expomovil-2026-estas-son-las-diferencias-en-los/PNOTGD3HG5HRFIHR7QT63MQ5PU/story/", "entities": ["Banco Nacional", "Banco Popular y de Desarrollo Comunal", "Banco de Costa Rica"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "b6a38d85-dd90-5d74-93c2-d211aad95950", "text": "Pakistan Repays $2 Billion Debt to UAE, Reduces Dependence on Gulf Nation. Pakistan has repaid a $2 billion debt to the UAE, reducing its dependence on the Gulf nation. The repayment was facilitated by taking a new loan from Saudi Arabia. This development is unlikely to have a significant impact on gold or silver prices, but it may contribute to a neutral tone in the market.", "metadata": {"topic": "macro_central_banks", "title": "Pakistan Repays $2 Billion Debt to UAE, Reduces Dependence on Gulf Nation", "original_title": "Pakistan returns $2 billion more to UAE", "publish_date": "2026-04-18T22:02:16Z", "publish_timestamp": 1776549736, "source": "tribune.com.pk", "url": "https://tribune.com.pk/story/2603481/pakistan-returns-2-billion-more-to-uae", "entities": ["Pakistan", "United Arab Emirates (UAE)", "Saudi Arabia", "International Monetary Fund (IMF)", "China", "Standard Chartered"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 1}} diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-18/qdrant_macro_geopolitics_risk_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-18/qdrant_macro_geopolitics_risk_processed.jsonl new file mode 100644 index 0000000..8227c0e --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-18/qdrant_macro_geopolitics_risk_processed.jsonl @@ -0,0 +1,5 @@ +{"id": "b7cc5e15-1274-5f83-ba2a-f1bcf9cf0640", "text": "Israeli Actor Eli Finiush's Comments Spark Controversy and Outrage. Israeli actor Eli Finiush's comments praising the Israeli military and government have sparked widespread outrage and controversy. The article suggests that Finiush's words are not only divisive but also perpetuate a toxic atmosphere in Israel. The macro transmission mechanism is likely to be negative for Gold/Silver prices, as increased market volatility and uncertainty may lead to safe-haven buying.", "metadata": {"topic": "macro_geopolitics_risk", "title": "Israeli Actor Eli Finiush's Comments Spark Controversy and Outrage", "original_title": "עמית סגל מגיב לסערה ועוקץ : זה פשע חמור , אין התיישנות ", "publish_date": "2026-04-18T22:03:55Z", "publish_timestamp": 1776549835, "source": "srugim.co.il", "url": "https://www.srugim.co.il/1302343-%D7%A2%D7%9E%D7%99%D7%AA-%D7%A1%D7%92%D7%9C-%D7%9E%D7%92%D7%99%D7%91-%D7%9C%D7%A1%D7%A2%D7%A8%D7%94-%D7%95%D7%A2%D7%95%D7%A7%D7%A5-%D7%A4%D7%A9%D7%A2-%D7%97%D7%9E%D7%95%D7%A8", "entities": ["Eli Finiush", "Israel", "Iran", "Netanyahu"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Increase", "llm_tone_score": -2}} +{"id": "1be0afb1-8fe5-5c42-b34d-450563b6392b", "text": "Pentagon Says Ukraine Support in Current Form Not Sustainable. The Pentagon's statement suggests that the current form of Ukraine support is not sustainable. This implies a potential decrease in military aid and a shift in responsibility to European allies. As a result, this news may lead to a decrease in market fear/VIX, which could negatively impact gold prices.\n\nThe macro transmission mechanism is as follows: The Pentagon's statement indicates a potential reduction in military aid to Ukraine, which could lead to a decrease in global uncertainty and market fear. This, in turn, may cause investors to become less risk-averse, leading to a decrease in the demand for safe-haven assets like gold. Additionally, the shift in responsibility to European allies may lead to a strengthening of the USD, further pressuring gold prices.", "metadata": {"topic": "macro_geopolitics_risk", "title": "Pentagon Says Ukraine Support in Current Form Not Sustainable", "original_title": "A Pentagon szerint Ukrajna támogatása ebben a formában nem biztosítható", "publish_date": "2026-04-18T22:03:55Z", "publish_timestamp": 1776549835, "source": "magyarnemzet.hu", "url": "https://magyarnemzet.hu/kulfold/2026/04/pentagon-szerint-ukrajna-tamogatasa-nem-biztosithato", "entities": ["Elbridge Colby", "Pentagon", "Ukraine", "Europe", "Donald Trump"], "impacted_assets": ["Gold", "USD"], "volatility_implication": "Decrease", "llm_tone_score": -2}} +{"id": "9f5b7285-3b76-5ba9-8a7b-c65e921f61d2", "text": "Matteo Salvini and European Patriots Rally in Milan's Duomo Square. The rally by European Patriots and Italian politician Matteo Salvini in Milan's Duomo Square highlights growing anti-EU sentiment. Salvini criticized the EU's response to the energy crisis and lockdown measures, echoing concerns about economic sovereignty. This event may increase market fear/VIX as it reinforces the narrative of a weakening EU and potentially boosts gold and silver prices.\n\nNote: The tone score is +2 because while the event does not directly impact monetary policy or inflation, it contributes to a broader narrative of anti-EU sentiment, which can be bullish for precious metals.", "metadata": {"topic": "macro_geopolitics_risk", "title": "Matteo Salvini and European Patriots Rally in Milan's Duomo Square", "original_title": "Salvini e i patrioti in piazza I leader europei sul palco del Duomo", "publish_date": "2026-04-18T22:03:55Z", "publish_timestamp": 1776549835, "source": "zazoom.it", "url": "https://www.zazoom.it/2026-04-18/salvini-e-i-patrioti-in-piazza-i-leader-europei-sul-palco-del-duomo/19027651/", "entities": ["Matteo Salvini", "European Patriots", "Ursula von der Leyen"], "impacted_assets": ["Gold", "Silver", "EURUSD"], "volatility_implication": "Increase", "llm_tone_score": 2}} +{"id": "d6a9d874-6f1d-5116-9a87-d1cc9b05b2ec", "text": "Man kills five people in shooting spree in Kiev, Ukraine. A shooting spree in Kiev, Ukraine resulted in the death of at least five people and injured 10 others. The incident has sparked concerns about potential instability in the region, which may lead to increased demand for safe-haven assets like gold and a strengthening of the USD. The macro transmission mechanism is through increased market fear and uncertainty, driving investors towards perceived safer assets.\n\nNote: The tone score is bearish due to the potential increase in market fear and uncertainty following this violent incident, which may drive investors away from riskier assets and towards safe-haven assets like gold.", "metadata": {"topic": "macro_geopolitics_risk", "title": "Man kills five people in shooting spree in Kiev, Ukraine", "original_title": "Ukraine . Un homme tue cinq personnes lors dune fusillade", "publish_date": "2026-04-18T22:03:55Z", "publish_timestamp": 1776549835, "source": "laseyne.maville.com", "url": "https://laseyne.maville.com/actu/actudet_-ukraine.-un-homme-tue-cinq-personnes-lors-d-une-fusillade-_fil-7285733_actu.Htm", "entities": ["Volodymyr Zelensky", "Igor Klymenko", "Rouslan Kravtchenko"], "impacted_assets": ["Gold", "USD"], "volatility_implication": "Increase", "llm_tone_score": -2}} +{"id": "0c3bb672-7622-59eb-8967-5fe63c9de109", "text": "Unexpected US Decision on Russia Sanctions. The unexpected US decision to ease sanctions on Russian oil has been met with disappointment from EU officials. Despite earlier predictions of increased pressure on Russia, the move is seen as a likely outcome by security expert Mark Episcopos. The relaxation of sanctions may lead to increased market volatility and potentially impact gold prices, while oil prices may stabilize.", "metadata": {"topic": "macro_geopolitics_risk", "title": "Unexpected US Decision on Russia Sanctions", "original_title": "На Западе сделали неожиданное заявление о решении США по России", "publish_date": "2026-04-18T22:03:55Z", "publish_timestamp": 1776549835, "source": "lenta.ru", "url": "https://lenta.ru/news/2026/04/19/na-zapade-sdelali-neozhidannoe-zayavlenie-o-reshenii-ssha-po-rossii/", "entities": ["Mark Episcopos", "European Union (EU)", "United States", "Russian Federation", "Kirill Dmitriev"], "impacted_assets": ["Gold", "Oil", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 0}} diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-19/qdrant_asset_metals_derivatives_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-19/qdrant_asset_metals_derivatives_processed.jsonl new file mode 100644 index 0000000..7f85281 --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-19/qdrant_asset_metals_derivatives_processed.jsonl @@ -0,0 +1,8 @@ +{"id": "452e0e09-ced0-5a21-9377-ecd1b4a40858", "text": "Spanish Cyclist Paula Blasi Makes History by Winning Amstel Gold Race. Spanish cyclist Paula Blasi made history by becoming the first Spanish woman to win a UCI Women's World Tour event. Her victory in the Amstel Gold Race is a significant achievement for women's cycling in Spain.", "metadata": {"topic": "asset_metals_derivatives", "title": "Spanish Cyclist Paula Blasi Makes History by Winning Amstel Gold Race", "original_title": "CICLISMO FEMENINO | La barcelonesa Paula Blasi gana la Amstel Gold Race y hace historia en el ciclismo español", "publish_date": "2026-04-19T16:33:14Z", "publish_timestamp": 1776616394, "source": "laopiniondezamora.es", "url": "https://www.laopiniondezamora.es/deportes/2026/04/19/barcelonesa-paula-blasi-gana-amstel-gold-race-129279564.html", "entities": ["Paula Blasi", "Mavi García", "Dori Ruano", "Joane Somarriba"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "6039a0a7-64c7-545e-9aad-55ac86f3ae4a", "text": "A Rare Koenigsegg Jesko Absolut Spotted in an Amsterdam Parking Garage. A rare Koenigsegg Jesko Absolut was spotted in an Amsterdam parking garage, showcasing its unique features and luxurious options. The car's owner, Zach Lewis, has a collection of high-end vehicles, including Ferraris and Lamborghinis. This event does not have any direct impact on the macro-financial landscape or the gold/silver market.\n\nNote: As per the critical instructions, I did not translate the original title as it is already in English. The tone score is neutral since there are no significant macro-financial implications from this article.", "metadata": {"topic": "asset_metals_derivatives", "title": "A Rare Koenigsegg Jesko Absolut Spotted in an Amsterdam Parking Garage", "original_title": "Deze Koenigsegg kan een Amsterdamse parkeergarage wél betalen", "publish_date": "2026-04-19T16:33:14Z", "publish_timestamp": 1776616394, "source": "autoblog.nl", "url": "https://www.autoblog.nl:443/nieuws/deze-koenigsegg-kan-een-amsterdamse-parkeergarage-w-l-betalen", "entities": ["Zach Lewis", "Koenigsegg Jesko Absolut", "Ferrari 488 Pista", "Mercedes 300 SL", "Lamborghini 400GT", "Countach 25th Anniversary", "Aventador", "Ferrari 365 GTC/4"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "d9f5cba0-8a4c-52e9-a49b-a198bb04cec2", "text": "Home Wrapping Techniques for Lymphatic Drainage and Skin Toning. The article discusses the benefits of home wrapping techniques for lymphatic drainage and skin toning. Dermatologist Ilya Rudnev shares his expertise on how to perform these procedures correctly, highlighting the importance of regularity and proper preparation. The article also provides recipes for homemade wraps using natural ingredients like coffee, ginger, and menthol.\n\nNote: As this article is not related to macro-financial news or events, it does not have a direct impact on Gold/Silver prices.", "metadata": {"topic": "asset_metals_derivatives", "title": "Home Wrapping Techniques for Lymphatic Drainage and Skin Toning", "original_title": "Дерматокосметолог Илья Руднев о правилах проведения домашних обертываний для лимфодренажа", "publish_date": "2026-04-19T16:33:14Z", "publish_timestamp": 1776616394, "source": "pravda.ru", "url": "https://www.pravda.ru/beauty/2345819-domashnie-obertyvaniya-uhod/", "entities": ["Ilya Rudnev", "Ksenia Anisimova"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "bb29d2c8-352e-5102-9f4e-930b3cbb8582", "text": "Colorado farmers scale back crops amid drought, tariffs, and war. A severe drought in Colorado is forcing farmers to scale back production, change crop priorities, and question their long-term survival. Tariffs and war-related supply chain disruptions are exacerbating the issue, leading to increased costs and uncertainty for agricultural labor. The impact on local food production will likely be felt by grocery shoppers.\n\nThe tone score of -3 reflects the bearish sentiment due to the combination of drought, tariffs, and war-related challenges, which could lead to decreased gold prices as investors seek safer assets. The decrease in volatility implication suggests that market fear may subside temporarily as investors become more risk-averse.", "metadata": {"topic": "asset_metals_derivatives", "title": "Colorado farmers scale back crops amid drought, tariffs, and war", "original_title": "Colorado farmers scale back crops amid drought , tariffs and war", "publish_date": "2026-04-19T16:33:14Z", "publish_timestamp": 1776616394, "source": "denverpost.com", "url": "https://www.denverpost.com/2026/04/19/colorado-farms-crops-drought-water/", "entities": ["Praxie Vigil", "Brian Crites", "Bruce Talbott", "Jared Polis"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Decrease", "llm_tone_score": -3}} +{"id": "c1bff1ec-ecc9-5c70-9f73-9f8e339b864e", "text": "BYDFi Marks 6th Anniversary with Month-Long Celebration, Built for Reliability. BYDFi, a global crypto trading platform, is celebrating its 6th anniversary with a month-long celebration. The company has expanded its product offerings, strengthened user safeguards, and extended access across both centralized and on-chain trading. This event does not have a significant impact on the macroeconomic environment or gold/silver prices, hence a neutral tone score.", "metadata": {"topic": "asset_metals_derivatives", "title": "BYDFi Marks 6th Anniversary with Month-Long Celebration, Built for Reliability", "original_title": "BYDFi Marks 6th Anniversary with Month - Long Celebration , Built for Reliability", "publish_date": "2026-04-19T16:33:14Z", "publish_timestamp": 1776616394, "source": "newsonjapan.com", "url": "http://www.newsonjapan.com/article/148967.php", "entities": ["BYDFi", "Newcastle United", "TradingView"], "impacted_assets": ["Cryptocurrencies", "Equities", "Gold", "Silver"], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "957deb23-6823-5c84-8ff6-9a3fe5bc3749", "text": "Deportes Tolima Confirms Quarterfinal Spot in Liga BetPlay I of 2026, Cali and Fortaleza Maintain Options. The Liga BetPlay I of 2026 has seen Deportes Tolima confirm its quarterfinal spot after defeating Deportivo Pereira. Meanwhile, Deportivo Cali and Fortaleza maintain their options for qualification. This event does not have a direct impact on the macro-financial landscape or the gold/silver markets.\n\nNote: As this article is about a sports tournament, it has no relevance to the financial market or the trading desk's focus on Gold/Silver Options.", "metadata": {"topic": "asset_metals_derivatives", "title": "Deportes Tolima Confirms Quarterfinal Spot in Liga BetPlay I of 2026, Cali and Fortaleza Maintain Options", "original_title": "Tabla de posiciones de la Liga BetPlay : Tolima clasifica , Cali cede y Fortaleza mantiene opciones", "publish_date": "2026-04-19T16:33:14Z", "publish_timestamp": 1776616394, "source": "vanguardia.com", "url": "https://www.vanguardia.com/deportes/futbol/2026/04/19/tabla-de-posiciones-de-la-liga-betplay-tolima-clasifica-cali-cede-y-fortaleza-mantiene-opciones/", "entities": ["Deportes Tolima", "Deportivo Pereira", "Deportivo Cali", "Fortaleza", "Atlético Nacional", "Deportivo Pasto", "Jaguares"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "90a69068-ae0b-5fce-b4e0-4a7deb4d153c", "text": "German Startup Nevermined Produces Lab-Grown Diamonds in Essen, Germany. Nevermined, a German startup, produces lab-grown diamonds in Essen using the chemical vapor deposition (CVD) process. The company emphasizes transparency, conflict-free, and sustainable practices. While lab-grown diamonds are optically, chemically, and physically identical to mined diamonds, their production requires significant energy consumption. This development may not have a direct impact on gold or silver prices but could influence the jewelry market and consumer preferences.\n\nNote: As this article is primarily focused on the startup's business model and practices, it does not have a significant macro-financial impact. The tone score is neutral as there are no clear directional macro drivers mentioned in the article.", "metadata": {"topic": "asset_metals_derivatives", "title": "German Startup Nevermined Produces Lab-Grown Diamonds in Essen, Germany", "original_title": "Diamanten - Labor : Hier wachsen Einkaräter in 2 Wochen – wie natürlich sind sie ? ", "publish_date": "2026-04-19T16:33:14Z", "publish_timestamp": 1776616394, "source": "morgenpost.de", "url": "https://www.morgenpost.de/wirtschaft/article411610677/nevermined-setzt-auf-labordiamanten-der-markt-ringt-um-bedeutung-und-preis.html", "entities": ["Christine Marhofer", "Dennis Oing", "Joachim Dünkelmann", "Bundesverbands der Juweliere", "Schmuck- und Uhrenfachgeschäfte"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "a9b35864-e4a9-560c-9f5b-1f1fbb0174a4", "text": "North Korea Launches Multiple Ballistic Missiles into Offshore Waters. The launch of multiple ballistic missiles by North Korea has heightened tensions in the region and increased market fear. This event is likely to have a negative impact on gold prices as investors seek safe-haven assets amid rising uncertainty. The strengthening of the US dollar may also be a consequence, as investors flock to the currency for its perceived safety.\n\nThe macro transmission mechanism at play here is the increase in global risk aversion and market fear, which can lead to increased demand for safe-haven assets like gold and a stronger USD.", "metadata": {"topic": "asset_metals_derivatives", "title": "North Korea Launches Multiple Ballistic Missiles into Offshore Waters", "original_title": "North Korea Launches Multiple Ballistic Missiles Into Offshore Waters - Jowhar News Leader", "publish_date": "2026-04-19T16:33:14Z", "publish_timestamp": 1776616394, "source": "jowhar.com", "url": "https://jowhar.com/north-korea-launches-multiple-ballistic-missiles-into-offshore-waters/", "entities": ["North Korea", "South Korea", "United States"], "impacted_assets": ["Gold", "USD"], "volatility_implication": "Increase", "llm_tone_score": -2}} diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-19/qdrant_macro_central_banks_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-19/qdrant_macro_central_banks_processed.jsonl new file mode 100644 index 0000000..a46fc4c --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-19/qdrant_macro_central_banks_processed.jsonl @@ -0,0 +1,8 @@ +{"id": "f62d8939-62c2-5b5b-a122-234d93cf4401", "text": "Dalal Street Week Ahead: Key Factors to Watch for Indian Equity Markets. The Indian equity market is expected to remain positive in the coming week, driven by progress in peace talks, crude oil prices stabilizing below $100, and Q4 earnings. The IMF has raised India's FY27 GDP growth forecast to 6.5%, highlighting the country's macroeconomic resilience. However, global uncertainties may lead to selective market action.", "metadata": {"topic": "macro_central_banks", "title": "Dalal Street Week Ahead: Key Factors to Watch for Indian Equity Markets", "original_title": "Dalal Street Week Ahead : Strait of Hormuz , Iran peace talks progress , Q4 earnings , oil prices , FII flow among 10 key factors to watch", "publish_date": "2026-04-19T16:29:12Z", "publish_timestamp": 1776616152, "source": "moneycontrol.com", "url": "https://www.moneycontrol.com/news/business/markets/dalal-street-week-ahead-strait-of-hormuz-iran-peace-talks-progress-q4-earnings-oil-prices-fii-flow-among-10-key-factors-to-watch-13893301.html", "entities": ["IMF", "India", "Iran", "US"], "impacted_assets": ["Equities (Indian)", "Crude Oil", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "bfd107fa-856a-5f55-b1d2-93b0fc7709ad", "text": "Thousands of Executives Aren't Seeing AI Productivity Boom, Reminding Economists of IT-Era Paradox. The article highlights the disconnect between AI adoption and productivity gains in the workplace. Despite widespread implementation of AI by executives, there is no corresponding increase in productivity or employment growth. This echoes Solow's \"productivity paradox\" from the IT era, where technological advancements did not lead to expected productivity boosts. The lack of tangible benefits from AI investments may lead to decreased expectations and potentially impact market sentiment.\n\nNote: As the tone score is 0 (Neutral), it does not have a significant impact on Gold/Silver prices.", "metadata": {"topic": "macro_central_banks", "title": "Thousands of Executives Aren't Seeing AI Productivity Boom, Reminding Economists of IT-Era Paradox", "original_title": "Thousands of executives arent seeing AI productivity boom , reminding economists of IT - era paradox", "publish_date": "2026-04-19T16:29:12Z", "publish_timestamp": 1776616152, "source": "fortune.com", "url": "https://fortune.com/article/why-do-thousands-of-ceos-believe-ai-not-having-impact-productivity-employment-study/", "entities": ["Robert Solow", "Torsten Slok", "Daron Acemoglu"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "450b03ea-4385-589d-b012-bb8f13578405", "text": "Allu Arjun's Unconventional Salary Structure in Indian Cinema. Allu Arjun, a prominent Indian actor, has adopted an unconventional revenue-sharing model for his films. He charges 30 paise per rupee of the movie's revenue, which reduces pressure on producers and lowers overall budgets. This approach has contributed to his significant earnings from recent films like Pushpa: The Rise and Pushpa 2: The Rule.", "metadata": {"topic": "macro_central_banks", "title": "Allu Arjun's Unconventional Salary Structure in Indian Cinema", "original_title": "Not a fixed salary : The 30 paise per rupee deal that makes Allu Arjun one of India highest - paid actors | Telugu News", "publish_date": "2026-04-19T16:29:12Z", "publish_timestamp": 1776616152, "source": "indianexpress.com", "url": "https://indianexpress.com/article/entertainment/telugu/allu-arjun-salary-revenue-sharing-model-explained-by-g-dhananjheyan-10645201/", "entities": ["Allu Arjun", "G Dhananjheyan", "Mythri Movie Makers", "Sukumar Writings", "Sun Pictures"], "impacted_assets": ["Equities", "Gold"], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "6e7527fd-2f18-5e6f-9832-f055ed0fd6de", "text": "Security Federal Share Price Crosses Above 200-Day Moving Average. Security Federal's share price has crossed above its 200-day moving average, indicating a potential upward trend. The company operates as a bank holding company and provides various banking products and services. This event does not have any significant macro-financial implications for the gold/silver market.", "metadata": {"topic": "macro_central_banks", "title": "Security Federal Share Price Crosses Above 200-Day Moving Average", "original_title": "Security Federal ( OTCMKTS : SFDL ) Share Price Crosses Above 200 - Day Moving Average – Here What Happened", "publish_date": "2026-04-19T16:29:12Z", "publish_timestamp": 1776616152, "source": "themarketsdaily.com", "url": "https://www.themarketsdaily.com/2026/04/19/security-federal-otcmktssfdl-share-price-crosses-above-200-day-moving-average-heres-what-happened.html", "entities": ["Security Federal Corp.", "SFDL", "OTCMKTS"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "63de4f7a-bbde-5344-bc45-dc5fac30c13a", "text": "Argentina's Economy Minister Predicts 18 Best Months Ahead Amid Inflation Concerns and Credit Negotiations. Argentine Economy Minister Luis Caputo predicts a period of 18 best months ahead, citing a slowdown in inflation and an expected increase in economic growth. This comes as the country negotiates with international organizations for a credit line exceeding $3 billion. Meanwhile, concerns about microeconomic issues, such as rising mora and stagnant salaries, persist. The macro transmission mechanism is driven by the government's efforts to stabilize the economy and attract foreign investment.\n\nNote: The tone score of +2 reflects the bullish sentiment expressed by Caputo regarding Argentina's economic prospects, which could positively impact gold and silver prices. However, the overall market volatility implication remains neutral due to the mixed signals from macroeconomic indicators.", "metadata": {"topic": "macro_central_banks", "title": "Argentina's Economy Minister Predicts 18 Best Months Ahead Amid Inflation Concerns and Credit Negotiations", "original_title": "Los 18 mejores meses y una fábrica cerrada que no cierra", "publish_date": "2026-04-19T16:29:12Z", "publish_timestamp": 1776616152, "source": "clarin.com", "url": "https://www.clarin.com/economia/18-mejores-meses-fabrica-cerrada-cierra_0_iEYGHy9mnA.html", "entities": ["Luis Caputo", "Argentina", "Fondo Monetario Internacional (FMI)", "Banco Mundial"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "4ddc5d10-d5ac-5074-bceb-cc42ec6204cc", "text": "Underconsumption Becomes a Trend as Americans Cut Back on Spending Amid High Inflation and Cost-of-Living Crisis. The article highlights the growing trend of underconsumption in America, where individuals are intentionally buying less and making items last as long as possible due to high inflation and a persistent cost-of-living crisis. This movement is driven by concerns about waste generation, environmental sustainability, and the impact of consumerism on society. While this trend may not have a direct impact on Gold/Silver prices, it could indirectly influence consumer spending habits, which might affect broader market sentiment.", "metadata": {"topic": "macro_central_banks", "title": "Underconsumption Becomes a Trend as Americans Cut Back on Spending Amid High Inflation and Cost-of-Living Crisis", "original_title": "How underconsumption became the word of the year", "publish_date": "2026-04-19T16:29:12Z", "publish_timestamp": 1776616152, "source": "independent.co.uk", "url": "https://www.independent.co.uk/us/money/underconsumption-tips-consumer-spending-b2956834.html", "entities": ["Resume Now", "Census Bureau", "Environmental Protection Agency", "Ladder", "Kuru"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "5fb38d59-0ede-5558-8706-ace6795958d0", "text": "Meeting between Governor of the National Bank and Deputy General Director of the IMF: Strong Support for Central Banks' Independence. The meeting between the Governor of the National Bank and the Deputy General Director of the IMF emphasizes the importance of central banks' independence in maintaining macroeconomic stability. This highlights the need for careful monitoring of risks and timely policy responses to ensure price stability. The discussion also underscores the significance of stable institutional frameworks, particularly during periods of increased external shocks and rapid changes in the global environment.", "metadata": {"topic": "macro_central_banks", "title": "Meeting between Governor of the National Bank and Deputy General Director of the IMF: Strong Support for Central Banks' Independence", "original_title": "Славески на средба со заменик - генералниот директор на ММФ Бо Ли : Потврдена силна поддршка за независноста на централните банки", "publish_date": "2026-04-19T16:29:12Z", "publish_timestamp": 1776616152, "source": "sitel.com.mk", "url": "https://sitel.com.mk/slaveski-na-sredba-so-zamenik-generalniot-direktor-na-mmf-bo-li-potvrdena-silna-poddrshka-za", "entities": ["Trajko Slaveski (Governor of the National Bank)", "Bo Li (Deputy General Director of the IMF)", "Dimitrievska-Kochoska (Minister of Finance)"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "f073686f-09f8-50a3-afb8-08b291d57cec", "text": "Brazilian Minister Wellington Dias Expects Easier Presidential Election in 2026 Compared to 2022. Brazilian Minister of Social Development and Hunger Combat Wellington Dias expects the 2026 presidential election to be less challenging than the 2022 election. He attributes this to the government's stronger political alliances and regional support. However, he also acknowledges communication challenges and the need for better public perception. The minister highlights positive social indicators, such as reduced poverty and job creation, but notes that these gains are being offset by high interest rates and endowment levels.\n\nThe macro transmission mechanism is that a more favorable political environment could lead to increased investor confidence, potentially benefiting gold and silver prices. However, the impact on USD is uncertain, as it depends on the overall market sentiment and the government's economic policies.", "metadata": {"topic": "macro_central_banks", "title": "Brazilian Minister Wellington Dias Expects Easier Presidential Election in 2026 Compared to 2022", "original_title": "Wellington Dias projeta eleies mais fáceis que em 2022 ", "publish_date": "2026-04-19T16:29:12Z", "publish_timestamp": 1776616152, "source": "brasil247.com", "url": "https://www.brasil247.com:443/brasil/wellington-dias-projeta-eleicoes-mais-faceis-que-em-2022-vvb9om4h", "entities": ["Wellington Dias", "Luiz Inácio Lula da Silva", "Rodrigo Pacheco", "Eduardo Paes", "Fernando Haddad", "Flávio Bolsonaro"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 1}} diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-19/qdrant_macro_geopolitics_risk_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-19/qdrant_macro_geopolitics_risk_processed.jsonl new file mode 100644 index 0000000..c8ddc97 --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-19/qdrant_macro_geopolitics_risk_processed.jsonl @@ -0,0 +1,9 @@ +{"id": "6a4136c3-be37-53a8-82cd-c1f4a52c19e7", "text": "Ford-class aircraft carrier deployment breaks record, Iran opens Hormuz Strait to shipping. The deployment of the Ford-class aircraft carrier has broken a record, while Iran has opened the Hormuz Strait to shipping. This development may increase market fear and volatility, as it suggests a potential escalation in tensions between the US and Iran. The increased military presence in the region could lead to higher oil prices and a stronger USD, which may negatively impact gold prices.\n\nThe macro transmission mechanism is as follows: an increase in military tension and deployment in the Middle East can lead to higher oil prices, which can strengthen the USD and negatively impact gold prices. Additionally, the potential for conflict escalation can increase market fear and volatility, leading to increased demand for safe-haven assets like gold.", "metadata": {"topic": "macro_geopolitics_risk", "title": "Ford-class aircraft carrier deployment breaks record, Iran opens Hormuz Strait to shipping", "original_title": " 【 馬克時空 】 霍爾木茲開放 福特號創紀錄 | 伊斯蘭革命衛隊 | 胡塞武裝 | 美國反封鎖", "publish_date": "2026-04-19T16:31:50Z", "publish_timestamp": 1776616310, "source": "ntdtv.com", "url": "https://www.ntdtv.com/b5/2026/04/19/a104088187.html", "entities": ["United States", "Iran", "Islamic Revolutionary Guard Corps", "Houthis", "Hezbollah"], "impacted_assets": ["Gold", "Oil", "USD"], "volatility_implication": "Increase", "llm_tone_score": 2}} +{"id": "304f15a7-e4bf-5e2c-8d49-c8cd57a47cb7", "text": "Ukrainian Police Chief Resigns Amid Officer Abandonment During Shooting Incident in Kiev. The resignation of the Ukrainian Police Chief follows a shooting incident in Kiev where police officers abandoned their posts, leaving a child unattended. Six people were killed and 15 injured in the incident. This event may increase market fear and volatility, potentially benefiting safe-haven assets like gold and weighing on the US dollar.\n\nThe macro transmission mechanism is as follows: The incident highlights concerns about law and order in Ukraine, which could negatively impact investor sentiment and lead to increased demand for safe-haven assets like gold. Additionally, the incident may reinforce existing market fears about the stability of the Ukrainian government, further pressuring the US dollar.", "metadata": {"topic": "macro_geopolitics_risk", "title": "Ukrainian Police Chief Resigns Amid Officer Abandonment During Shooting Incident in Kiev", "original_title": "Начальник патрульной полиции Украины ушел с поста после побега правоохранителей", "publish_date": "2026-04-19T16:31:50Z", "publish_timestamp": 1776616310, "source": "vesti.ru", "url": "https://www.vesti.ru/ns/nachalnik-patrulnoj-policii-ukrainy-ushel-s-posta-posle-pobega-pravookhranitelej", "entities": ["Ukraine", "Kiev", "Ministry of Internal Affairs", "Dmitriy Vasilchenko"], "impacted_assets": ["Gold", "USD"], "volatility_implication": "Increase", "llm_tone_score": -1}} +{"id": "b3d4aed0-2acf-576f-9a0b-daeb26257050", "text": "Russian attacks kill at least 2 as Ukraine strikes a Russian drone factory. The ongoing conflict between Russia and Ukraine has escalated with reports of Russian attacks killing at least two people in Ukraine. In response, Ukraine struck a Russian drone factory, sparking a fire and damaging commercial infrastructure. This development increases market fear and volatility, potentially driving investors towards safe-haven assets like gold and the US dollar.\n\nThe macro transmission mechanism is as follows: The conflict between Russia and Ukraine has led to increased tensions and uncertainty, which can drive investors towards safe-haven assets like gold and the US dollar. The strikes on Russian targets may also lead to a strengthening of the USD, as investors seek refuge in the currency.", "metadata": {"topic": "macro_geopolitics_risk", "title": "Russian attacks kill at least 2 as Ukraine strikes a Russian drone factory", "original_title": "Russian attacks kill at least 2 as Ukraine strikes a Russian drone factory", "publish_date": "2026-04-19T16:31:50Z", "publish_timestamp": 1776616310, "source": "toronto.citynews.ca", "url": "https://toronto.citynews.ca/2026/04/19/russian-attacks-kill-at-least-2-as-ukraine-strikes-a-russian-drone-factory/", "entities": ["Russia", "Ukraine", "Volodymyr Zelenskyy", "Ihor Klymenko"], "impacted_assets": ["Gold", "USD"], "volatility_implication": "Increase", "llm_tone_score": -1}} +{"id": "37713572-6899-5268-996f-486c5c443b33", "text": "\"Year-Long Transformation: Robots Go from Wobbly Steps to Marathon Pace, Outpacing Humans\". The article highlights the rapid progress in robotics, with a robot named \"Flash\" setting a new record for completing a half-marathon in 50 minutes and 26 seconds, surpassing human records. This achievement is attributed to advancements in AI and robotics technology, which have led to increased investment and funding in the sector. However, the industry still faces challenges such as high data collection costs and the need for standardization. The article suggests that the key to success lies in balancing technological innovation with cost control.\n\nThe macro transmission mechanism at play here is the increasing investment in AI and robotics, which could lead to a surge in demand for these technologies, potentially driving up prices of related assets such as equities and gold. However, the neutral tone score reflects the lack of clear directional macro drivers, as the article primarily focuses on the technological advancements rather than any specific policy or economic developments that would impact the market.", "metadata": {"topic": "macro_geopolitics_risk", "title": "\"Year-Long Transformation: Robots Go from Wobbly Steps to Marathon Pace, Outpacing Humans\"", "original_title": "一年蜕变 : 人形机器人从 步履蹒跚 到马拉松赛道 碾压 人类 - 人工智能 - ITBear比尔科技", "publish_date": "2026-04-19T16:31:50Z", "publish_timestamp": 1776616310, "source": "itbear.com.cn", "url": "https://www.itbear.com.cn/html/2026-04/1287794.html", "entities": ["Beijing", "Honor Technology", "USTech", "Shangai City Data Science Key Laboratory"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "6196c727-bdcc-5c58-a403-1fda3b93a9d8", "text": "Russia and Ukraine, Night of Drones: Deaths in Chernihiv and Kherson. The ongoing conflict between Russia and Ukraine has escalated with a night of drone attacks, resulting in deaths and injuries on both sides. The Ukrainian military claims to have shot down 203 Russian drones, while Russia reports that 274 Ukrainian drones were destroyed. The tension is fueled by the US decision to extend sanctions relief for Russian oil imports, which Ukraine sees as supporting Moscow's war efforts. This development increases market fear and volatility, potentially benefiting safe-haven assets like gold.\n\nThe macro transmission mechanism at play here is the ongoing conflict between Russia and Ukraine, which continues to drive uncertainty and risk aversion in financial markets. The US decision to extend sanctions relief for Russian oil imports adds to the tension, as it may be seen as supporting Moscow's war efforts and potentially prolonging the conflict. This increases the likelihood of market volatility and a flight to safety, benefiting assets like gold.", "metadata": {"topic": "macro_geopolitics_risk", "title": "Russia and Ukraine, Night of Drones: Deaths in Chernihiv and Kherson", "original_title": "Russia e Ucraina , notte di droni : morti a Chernihiv e Kherson", "publish_date": "2026-04-19T16:31:50Z", "publish_timestamp": 1776616310, "source": "ottopagine.it", "url": "https://www.ottopagine.it/mondo/attualita/425025/russia-e-ucraina-notte-di-droni-morti-a-chernihiv-e-kherson.shtml", "entities": ["Russia", "Ukraine", "Volodymyr Zelensky", "Donald Trump"], "impacted_assets": ["Gold", "USD"], "volatility_implication": "Increase", "llm_tone_score": -2}} +{"id": "bb9cb9d1-0b73-58da-93b3-90c25a2e9f3c", "text": "US Negotiators Prepare for More Peace Talks with Iran Amid Threats from Trump. The ongoing conflict between the US and Iran continues to escalate, with President Trump threatening to take further action if negotiations fail. This rhetoric may lead to increased market fear and volatility, potentially benefiting safe-haven assets like gold and oil. The situation remains uncertain, but a potential breakthrough in peace talks could lead to a decrease in tensions and a subsequent decline in these assets.\n\nNote: The tone score is +2 because while the conflict is ongoing, President Trump's threats are not necessarily a guarantee of immediate action, which keeps the tone slightly bullish for gold and oil.", "metadata": {"topic": "macro_geopolitics_risk", "title": "US Negotiators Prepare for More Peace Talks with Iran Amid Threats from Trump", "original_title": "U . S . negotiators prepare for more peace talks as Trump repeats threats to Iran", "publish_date": "2026-04-19T16:31:50Z", "publish_timestamp": 1776616310, "source": "kunc.org", "url": "https://www.kunc.org/npr-news/2026-04-19/u-s-negotiators-prepare-for-more-peace-talks-as-trump-repeats-threats-to-iran", "entities": ["President Trump", "Vice President Vance", "Steve Witkoff", "Jared Kushner", "Mohammed Bagher Qalibaf"], "impacted_assets": ["Gold", "Oil", "USD"], "volatility_implication": "Increase", "llm_tone_score": 2}} +{"id": "634ae36a-4dfd-57ae-92a4-10a7fb993032", "text": "Pope Calls for Dialogue to End War in Middle East. The Pope's appeal for dialogue to end the war in the Middle East is a neutral macro event that does not have a direct impact on Gold/Silver prices. While the Pope's words may contribute to a sense of hope and stability, they do not alter the fundamental macroeconomic landscape or create new market drivers.", "metadata": {"topic": "macro_geopolitics_risk", "title": "Pope Calls for Dialogue to End War in Middle East", "original_title": "Pope calls for dialogue to end war in Middle East – Shafaqna English | International Shia News & Fatwas", "publish_date": "2026-04-19T16:31:50Z", "publish_timestamp": 1776616310, "source": "en.shafaqna.com", "url": "https://en.shafaqna.com/447164/pope-calls-for-dialogue-to-end-war-in-middle-east/", "entities": ["Pope Leo XIV", "Lebanon", "Middle East"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "25e31e71-77ed-5226-a021-4d1a5be728c6", "text": "Ukrainian Hydrometeorological Center Warns of Possible Ground Frost on April 20. The Ukrainian Hydrometeorological Center has issued a warning about possible ground frost on April 20 in certain regions of Ukraine. This weather forecast may have a neutral to slightly bullish impact on gold and silver prices, as it could lead to increased demand for safe-haven assets amid potential market volatility. The USD may also be affected, potentially strengthening if the event leads to increased risk aversion.", "metadata": {"topic": "macro_geopolitics_risk", "title": "Ukrainian Hydrometeorological Center Warns of Possible Ground Frost on April 20", "original_title": "Укргідрометцентр попередив про можливі заморозки на поверхні ґрунту 20 квітня", "publish_date": "2026-04-19T16:31:50Z", "publish_timestamp": 1776616310, "source": "mig.com.ua", "url": "https://mig.com.ua/ukrhidromettsentr-poperedyv-pro-mozhlyvi-zamorozky-na-poverkhni-gruntu-20-kvitnia/", "entities": ["Ukrainian Hydrometeorological Center", "Ukraine"], "impacted_assets": ["Gold", "Silver", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 1}} +{"id": "b1b6304d-2c82-5afd-bd1b-f481e1e75573", "text": "Over 5% of job openings in Taiwan's Central Science Park offer salaries above NT$400,000; 27 companies release over 1,200 job vacancies.. The Central Science Park in Taiwan has seen significant growth, with 114-year revenue reaching NT$113 billion and a 9.29% year-over-year increase. To meet the growing demand for talent, the park's management bureau is actively recruiting and providing various services to job seekers. This event is bullish for gold prices as it indicates a strong economy and potential inflationary pressures.", "metadata": {"topic": "macro_geopolitics_risk", "title": "Over 5% of job openings in Taiwan's Central Science Park offer salaries above NT$400,000; 27 companies release over 1,200 job vacancies.", "original_title": "逾五成職缺起薪4萬元以上 中科27家廠商徵才釋出逾1200個職缺", "publish_date": "2026-04-19T16:31:50Z", "publish_timestamp": 1776616310, "source": "n.yam.com", "url": "https://n.yam.com/Article/20260419898137", "entities": ["中科管理局 (Taiwan's Central Science Park Management Bureau)", "臺中市政府勞工局 (Taichung City Government Labor Department)", "台積電 (Taiwan Semiconductor Manufacturing Company)", "美光 (Everlight Electronics Co.", "Ltd.)", "友達光電 (Largan Precision Co.", "Ltd.)", "矽品精密 (Siliconware Precision Industries Co.", "Ltd.)", "永勝光學 (Everbright Optoelectronics Technology Co.", "Ltd.)"], "impacted_assets": ["Equities", "Gold"], "volatility_implication": "Neutral", "llm_tone_score": 2}} diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-19/qdrant_macro_inflation_employment_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-19/qdrant_macro_inflation_employment_processed.jsonl new file mode 100644 index 0000000..e521994 --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-19/qdrant_macro_inflation_employment_processed.jsonl @@ -0,0 +1,9 @@ +{"id": "76147c8c-e7e3-5860-963c-01cfcdb405f5", "text": "Venezuela's INVELECAR Urges Swift Action to Eradicate Aftosa Fever. The Venezuelan Institute of Milk and Meat (INVELECAR) has issued a statement emphasizing the need for swift action to eradicate Aftosa fever in Venezuela. The institute highlights the importance of conducting a national census of livestock units and vaccination efforts to ensure food security and open up international markets. INVELECAR also notes that Venezuela is the only country in Latin America without official recognition as \"free from aftosa with vaccination\" by the World Organization for Animal Health (OMSA), limiting access to international markets.", "metadata": {"topic": "macro_inflation_employment", "title": "Venezuela's INVELECAR Urges Swift Action to Eradicate Aftosa Fever", "original_title": "INVELECAR exige acciones urgentes para erradicar la fiebre aftosa en Venezuela", "publish_date": "2026-04-19T16:30:01Z", "publish_timestamp": 1776616201, "source": "acn.com.ve", "url": "https://acn.com.ve/fiebre-aftosa-en-venezuela/", "entities": ["INVELECAR", "Ministerio de Agricultura Productiva y Tierras", "FUNVESSA", "FEDENAGA", "CONVECAR", "CONFAGAN", "PANAFTOSA", "Organización Mundial de Sanidad Animal (OMSA)", "COSALFA", "PHEFA"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "57507e3b-a4dc-5298-a0a2-25a83f5cd4b2", "text": "Trump's Approval Rating Falls to New Low, According to NBC News Survey. The decline in Trump's approval rating is likely to weigh on market sentiment, particularly for gold and equities. As the president's popularity falls, investors may become more risk-averse, driving demand for safe-haven assets like gold. The weakening of Trump's support also increases the likelihood of a divided government, which could lead to policy gridlock and further uncertainty.\n\nThe macro transmission mechanism is as follows: A decline in presidential approval ratings can lead to increased market volatility, as investors become more cautious and seek safer assets. This, in turn, can drive down equities and boost gold prices. Additionally, the potential for a divided government can create uncertainty around policy decisions, leading to further market volatility.", "metadata": {"topic": "macro_inflation_employment", "title": "Trump's Approval Rating Falls to New Low, According to NBC News Survey", "original_title": "Aprobación de Trump cae a su nivel más bajo , según encuesta – Telemundo Puerto Rico", "publish_date": "2026-04-19T16:30:01Z", "publish_timestamp": 1776616201, "source": "telemundopr.com", "url": "https://www.telemundopr.com/noticias/eeuu/aprobacion-trump-nivel-bajo-segundo-mandato-encuesta/2804256/", "entities": ["Donald Trump", "NBC News Decision Desk", "SurveyMonkey"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Decrease", "llm_tone_score": -3}} +{"id": "340ddb7a-5e12-53bb-b301-4949ddea6331", "text": "Stubborn Inflation is the Root Cause of Sluggish Economy. The article highlights the persistence of high inflation in the UK, averaging 3% since 2010, which has hindered economic growth and competitiveness. The author attributes this to expensive land use, energy consumption, and capital deployment, leading to higher costs for businesses and households. This diagnosis suggests that addressing these upstream causes is crucial to reducing inflation and stimulating economic expansion.\n\nThe tone score of -2 reflects the bearish sentiment towards the UK economy due to persistent high inflation, which may lead to decreased investor confidence and potentially lower gold prices. The article's focus on the root causes of inflation rather than downstream solutions implies a more nuanced approach to addressing the issue, which could have a stabilizing effect on markets.", "metadata": {"topic": "macro_inflation_employment", "title": "Stubborn Inflation is the Root Cause of Sluggish Economy", "original_title": "Stubborn inflation is the root cause of our sluggish economy", "publish_date": "2026-04-19T16:30:01Z", "publish_timestamp": 1776616201, "source": "thetimes.com", "url": "https://www.thetimes.com/business/economics/article/stubborn-inflation-root-cause-uk-sluggish-economy-dslhwqzbq", "entities": ["UK Government", "Labour Party", "Conservative Party", "G7 countries"], "impacted_assets": ["Equities", "Gold", "Oil", "GBP"], "volatility_implication": "Decrease", "llm_tone_score": -2}} +{"id": "05a035bd-09ec-5a31-be26-686f7eb596df", "text": "Morocco: Eid Sacrifice Goat Prices to Increase. The price of goats in Morocco is expected to increase ahead of the Eid al-Adha festival due to a complex balance between rising diesel prices and improved climate conditions. The expert notes that this situation is close to stability, but regional disparities persist due to transportation costs, farm availability, and distance from production to consumption areas. The market reflects broader economic and social dynamics, with energy costs impacting the entire value chain and agriculture helping to mitigate inflation and support purchasing power in both urban and rural areas.\n\nNote: As there are no explicit macro-financial implications or directional drivers for Gold/Silver prices, I assigned a Neutral tone score of 0.", "metadata": {"topic": "macro_inflation_employment", "title": "Morocco: Eid Sacrifice Goat Prices to Increase", "original_title": "Maroc : le mouton de lAïd sera plus cher", "publish_date": "2026-04-19T16:30:01Z", "publish_timestamp": 1776616201, "source": "bladi.net", "url": "https://www.bladi.net/maroc-mouton-aid-sera-cher,120772.html", "entities": ["Amine Sami", "Goud", "Bladi.net"], "impacted_assets": ["Livestock", "Agricultural Products", "Energy (Diesel)", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "2e83108c-4131-54ab-b19c-f2d4f8f95d19", "text": "Trump's Approval Rating Hits New Low in Second Term, Only 37% Approve His Performance. A recent NBC survey shows a significant decline in President Trump's approval rating, with only 37% of Americans approving his performance. This is the lowest level since his second term began. The majority of respondents disapprove of Trump's handling of inflation and war, which could lead to increased market volatility and potentially weigh on gold and silver prices.", "metadata": {"topic": "macro_inflation_employment", "title": "Trump's Approval Rating Hits New Low in Second Term, Only 37% Approve His Performance", "original_title": "Sondaggio , solo 37 % degli americani promuove Trump , minimo in secondo mandato - Ultima ora", "publish_date": "2026-04-19T16:30:01Z", "publish_timestamp": 1776616201, "source": "ansa.it", "url": "https://www.ansa.it/sito/notizie/topnews/2026/04/19/sondaggio-solo-37-degli-americani-promuove-trump-minimo-in-secondo-mandato_85712e13-7341-4322-84a9-fe9a864f7e10.html", "entities": ["Donald Trump", "NBC", "United States"], "impacted_assets": ["Equities", "Gold", "USD"], "volatility_implication": "Increase", "llm_tone_score": -4}} +{"id": "ed746705-ad47-5aa4-b94a-4350d806b885", "text": "Argentine Government Official's Presence at Congress to be a \"Show\" Amidst Scandal. The presence of Argentine Government Official Manuel Adorni at Congress is expected to be a \"show\" amidst scandal surrounding his alleged enrichment. This event may not have a direct impact on Gold/Silver prices, but the tone of the article suggests that it could contribute to market uncertainty and potentially affect asset prices indirectly.", "metadata": {"topic": "macro_inflation_employment", "title": "Argentine Government Official's Presence at Congress to be a \"Show\" Amidst Scandal", "original_title": "Cristian Ritondo , sobre la presencia de Manuel Adorni en el Congreso : Va a ser un show y eso no ayuda para nada ", "publish_date": "2026-04-19T16:30:01Z", "publish_timestamp": 1776616201, "source": "clarin.com", "url": "https://www.clarin.com/politica/cristian-ritondo-presencia-manuel-adorni-congreso-va-show-ayuda_0_cae1nCm1KV.html", "entities": ["Cristian Ritondo", "Manuel Adorni", "Javier Milei", "Martín Menem", "Miguel Ángel Pichetto", "Nicolás Massot", "Emilio Monzó", "Marcos Galperín", "Jorge Brito"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "fedaabac-a51f-5333-b433-fdd1e6dc87bc", "text": "Calabrian Families Spend 1.76 Billion Euros on Durable Goods in 2025; Used Goods Market Supports Local Economy. The article reports that Calabrian families spent approximately 1.76 billion euros on durable goods in 2025, with a slight decrease of 0.1% compared to the previous year. The used goods market played a crucial role in supporting the local economy, which experienced a moderate contraction. This data suggests that Calabria's consumer spending habits are relatively stable and resilient, despite the overall economic slowdown.\n\nNote: As there is no explicit macro-financial or geopolitical content in this article, I did not assign any tone score or volatility implication. The summary focuses on the local economy and consumer spending trends in Calabria.", "metadata": {"topic": "macro_inflation_employment", "title": "Calabrian Families Spend 1.76 Billion Euros on Durable Goods in 2025; Used Goods Market Supports Local Economy", "original_title": "Calabria spesa familiare a 1 , 7 miliardi | lusato salva il mercato", "publish_date": "2026-04-19T16:30:01Z", "publish_timestamp": 1776616201, "source": "zazoom.it", "url": "https://www.zazoom.it/2026-04-19/calabria-spesa-familiare-a-17-miliardi-lusato-salva-il-mercato/19031519/", "entities": ["Calabria", "Italian families", "used goods market"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "f62d8939-62c2-5b5b-a122-234d93cf4401", "text": "Dalal Street Week Ahead: Key Factors to Watch for Indian Equity Markets. The Indian equity market is expected to remain positive in the coming week, driven by progress in peace talks, crude oil prices stabilizing below $100, and Q4 earnings. The IMF has raised India's FY27 GDP growth forecast to 6.5%, highlighting the country's macroeconomic resilience. However, global uncertainties may lead to selective market action.", "metadata": {"topic": "macro_inflation_employment", "title": "Dalal Street Week Ahead: Key Factors to Watch for Indian Equity Markets", "original_title": "Dalal Street Week Ahead : Strait of Hormuz , Iran peace talks progress , Q4 earnings , oil prices , FII flow among 10 key factors to watch", "publish_date": "2026-04-19T16:30:01Z", "publish_timestamp": 1776616201, "source": "moneycontrol.com", "url": "https://www.moneycontrol.com/news/business/markets/dalal-street-week-ahead-strait-of-hormuz-iran-peace-talks-progress-q4-earnings-oil-prices-fii-flow-among-10-key-factors-to-watch-13893301.html", "entities": ["IMF", "India", "Iran", "US"], "impacted_assets": ["Equities (Indian)", "Crude Oil", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "06764251-7044-5ee0-bfe4-d4a217e9de6b", "text": "Is There an Exit in Sight?. The article highlights the escalating conflict between the US and Iran, with Israel playing a significant role in fueling the tensions. The author suggests that Trump's desire to re-open the Strait of Hormuz is crucial for global oil supplies and economic stability. The piece also touches on the potential impact of the conflict on global markets, including inflation concerns in the US and recessionary risks globally. The tone is bearish due to the escalating tensions and the potential for a prolonged conflict.\n\nMacro transmission mechanism: The article suggests that the conflict could lead to increased market volatility, higher oil prices, and potentially even a global recession if the Strait of Hormuz remains blocked. This could have negative implications for gold prices, as investors seek safe-haven assets during times of uncertainty.", "metadata": {"topic": "macro_inflation_employment", "title": "Is There an Exit in Sight?", "original_title": "OPINIÓN DE JORGE DEZCALLAR | ¿ Hay salida a la vista ? ", "publish_date": "2026-04-19T16:30:01Z", "publish_timestamp": 1776616201, "source": "lne.es", "url": "https://www.lne.es/opinion/2026/04/19/hay-salida-vista-eeuu-iran-israel-libano-articulo-jorge-dezcallar-129279620.html", "entities": ["Trump", "Netanyahu", "Iran", "Israel", "Washington", "Pakistan", "United States", "Europe", "Asia", "FMI", "Pope Leo XIV"], "impacted_assets": ["Gold", "Oil", "USD", "Equities"], "volatility_implication": "Increase", "llm_tone_score": -2}} diff --git a/Data/3_Gold_Semantic/News_Qdrant/2026-04-19/qdrant_macro_yields_dollar_processed.jsonl b/Data/3_Gold_Semantic/News_Qdrant/2026-04-19/qdrant_macro_yields_dollar_processed.jsonl new file mode 100644 index 0000000..95db083 --- /dev/null +++ b/Data/3_Gold_Semantic/News_Qdrant/2026-04-19/qdrant_macro_yields_dollar_processed.jsonl @@ -0,0 +1,7 @@ +{"id": "11122531-30db-51dd-979f-7533b3590e11", "text": "15-Year-Old Girl Asks Elon Musk 8 Questions Before Her Death; He Answers Them. A 15-year-old girl named Liv, who was battling cancer, had the opportunity to ask Elon Musk eight questions before her passing. After her death, her mother shared the handwritten list of questions with Glenn Beck, who then posted it online. Musk responded directly to the post, answering each question. This heartwarming story highlights the impact that people can have on one another, even in the face of adversity.\n\nNote: As there is no macro-financial or geopolitical content in this article, the tone score is neutral. The event does not have a direct impact on gold or silver prices.", "metadata": {"topic": "macro_yields_dollar", "title": "15-Year-Old Girl Asks Elon Musk 8 Questions Before Her Death; He Answers Them", "original_title": "15 - Jährige stellte Elon Musk 8 Fragen vor ihrem Tod – der beantwortet sie", "publish_date": "2026-04-19T16:31:05Z", "publish_timestamp": 1776616265, "source": "focus.de", "url": "https://www.focus.de/panorama/welt/15-jaehrige-stellte-elon-musk-8-fragen-vor-ihrem-tod-der-beantwortet-sie_10ab5d50-13c0-427c-8a3e-2ff98404480f.html", "entities": ["Liv Perrotto", "Elon Musk", "Glenn Beck", "Rebecca Perrotto", "Igor Babuschkin"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "2381d3bb-f84f-571f-9f09-7a0eece18490", "text": "Greenhouse Revolution: How Controlled Farming is Transforming Global Produce Markets. The article discusses the growth of greenhouse farming as a sustainable and efficient way to produce fruits and vegetables. While this trend has positive implications for food security, it does not have a direct impact on gold or silver prices. However, the global supply chain disruption alert mentioned at the end may have some indirect effects on commodity prices.\n\nNote: The tone score is neutral because there are no macroeconomic drivers that would directly affect gold or silver prices. The article focuses on the agricultural sector and its growth, which does not have a significant impact on the precious metals market.", "metadata": {"topic": "macro_yields_dollar", "title": "Greenhouse Revolution: How Controlled Farming is Transforming Global Produce Markets", "original_title": "Greenhouse Revolution : How Controlled Farming is Transforming Global Produce Markets", "publish_date": "2026-04-19T16:31:05Z", "publish_timestamp": 1776616265, "source": "briefingwire.com", "url": "https://www.briefingwire.com/pr/greenhouse-revolution-how-controlled-farming-is-transforming-global-produce-markets", "entities": ["None explicitly mentioned"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "f62d8939-62c2-5b5b-a122-234d93cf4401", "text": "Dalal Street Week Ahead: Key Factors to Watch for Indian Equity Markets. The Indian equity market is expected to remain positive in the coming week, driven by progress in peace talks, crude oil prices stabilizing below $100, and Q4 earnings. The IMF has raised India's FY27 GDP growth forecast to 6.5%, highlighting the country's macroeconomic resilience. However, global uncertainties may lead to selective market action.", "metadata": {"topic": "macro_yields_dollar", "title": "Dalal Street Week Ahead: Key Factors to Watch for Indian Equity Markets", "original_title": "Dalal Street Week Ahead : Strait of Hormuz , Iran peace talks progress , Q4 earnings , oil prices , FII flow among 10 key factors to watch", "publish_date": "2026-04-19T16:31:05Z", "publish_timestamp": 1776616265, "source": "moneycontrol.com", "url": "https://www.moneycontrol.com/news/business/markets/dalal-street-week-ahead-strait-of-hormuz-iran-peace-talks-progress-q4-earnings-oil-prices-fii-flow-among-10-key-factors-to-watch-13893301.html", "entities": ["IMF", "India", "Iran", "US"], "impacted_assets": ["Equities (Indian)", "Crude Oil", "USD"], "volatility_implication": "Neutral", "llm_tone_score": 2}} +{"id": "0d18ced9-2f0f-5375-bfa0-87a7dce9ff89", "text": "Creating Sustainable Food Systems for Human and Planetary Health. The article discusses the need for sustainable food systems that prioritize human and planetary health. It highlights the significant environmental impact of agriculture, including greenhouse gas emissions, water usage, and deforestation. The authors emphasize the importance of addressing Scope 3 emissions, which account for a large portion of a company's carbon footprint. While this topic may not have a direct impact on gold or silver prices, it could indirectly influence commodity markets through its focus on sustainable practices and environmental concerns.\n\nNote: As per the instructions, I did not assign a tone score based on the expected impact on Gold/Silver prices since there is no clear directional macro driver in this article.", "metadata": {"topic": "macro_yields_dollar", "title": "Creating Sustainable Food Systems for Human and Planetary Health", "original_title": "We Can Create Food Systems That Enhance Human & Planetary Health", "publish_date": "2026-04-19T16:31:05Z", "publish_timestamp": 1776616265, "source": "cleantechnica.com", "url": "https://cleantechnica.com/2026/04/19/we-can-create-food-systems-that-enhance-human-planetary-health/", "entities": ["World Resources Institute", "Elena Bou", "Forbes", "Advances in Nutrition"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "957deb23-6823-5c84-8ff6-9a3fe5bc3749", "text": "Deportes Tolima Confirms Quarterfinal Spot in Liga BetPlay I of 2026, Cali and Fortaleza Maintain Options. The Liga BetPlay I of 2026 has seen Deportes Tolima confirm its quarterfinal spot after defeating Deportivo Pereira. Meanwhile, Deportivo Cali and Fortaleza maintain their options for qualification. This event does not have a direct impact on the macro-financial landscape or the gold/silver markets.\n\nNote: As this article is about a sports tournament, it has no relevance to the financial market or the trading desk's focus on Gold/Silver Options.", "metadata": {"topic": "macro_yields_dollar", "title": "Deportes Tolima Confirms Quarterfinal Spot in Liga BetPlay I of 2026, Cali and Fortaleza Maintain Options", "original_title": "Tabla de posiciones de la Liga BetPlay : Tolima clasifica , Cali cede y Fortaleza mantiene opciones", "publish_date": "2026-04-19T16:31:05Z", "publish_timestamp": 1776616265, "source": "vanguardia.com", "url": "https://www.vanguardia.com/deportes/futbol/2026/04/19/tabla-de-posiciones-de-la-liga-betplay-tolima-clasifica-cali-cede-y-fortaleza-mantiene-opciones/", "entities": ["Deportes Tolima", "Deportivo Pereira", "Deportivo Cali", "Fortaleza", "Atlético Nacional", "Deportivo Pasto", "Jaguares"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} +{"id": "1ece9a16-9a7f-54a1-a0a0-f96978080a3f", "text": "Warning: This War Will Also Affect Your Portfolio - And Many Won't Realize It Until Too Late. The escalating conflict in the Middle East is driving up energy prices and posing a structural risk to the global economy. Rising energy costs will increase inflationary pressure, threaten rate cuts, and shake equity markets. However, this crisis also presents opportunities for companies that profit from higher energy prices, such as oil and gas producers, utilities, renewable energy providers, and select commodity and agricultural stocks.", "metadata": {"topic": "macro_yields_dollar", "title": "Warning: This War Will Also Affect Your Portfolio - And Many Won't Realize It Until Too Late", "original_title": "Stefan Schrader warnt : Dieser Krieg trifft auch Ihr Depot - und viele merken es zu spät", "publish_date": "2026-04-19T16:31:05Z", "publish_timestamp": 1776616265, "source": "finanznachrichten.de", "url": "https://www.finanznachrichten.de/nachrichten-2026-04/68236172-stefan-schrader-warnt-dieser-krieg-trifft-auch-ihr-depot-und-viele-merken-es-zu-spaet-049.htm", "entities": ["Stefan Schrader", "Iran", "Hormuz Strait", "LNG", "Oil"], "impacted_assets": ["Equities", "Gold", "Oil", "USD"], "volatility_implication": "Increase", "llm_tone_score": 2}} +{"id": "aec76206-9966-5f05-9a99-3cfcb0eb8ab7", "text": "Ponte Mobile for Porto di Livorno Repaired, Fragility Remains. The ponte mobile connecting the Fi-Pi-Li highway to the Porto di Livorno has been repaired after a structural failure on March 6. Although the repair is complete, the structure remains fragile, according to authorities. This event does not have a direct impact on gold or silver prices but may indirectly affect regional economic activity and port operations, which could influence market sentiment.", "metadata": {"topic": "macro_yields_dollar", "title": "Ponte Mobile for Porto di Livorno Repaired, Fragility Remains", "original_title": "Fipili | ponte mobile per il Porto di Livorno ripristinato Autorità Portuale | Resta la fragilità Ma Giani è soddisfatto", "publish_date": "2026-04-19T16:31:05Z", "publish_timestamp": 1776616265, "source": "zazoom.it", "url": "https://www.zazoom.it/2026-04-19/fipili-ponte-mobile-per-il-porto-di-livorno-ripristinato-autorita-portuale-resta-la-fragilita-ma-giani-e-soddisfatto/19031572/", "entities": ["Fipili", "Autorità Portuale", "Città Metropolitana di Firenze", "Regione", "Avr spa"], "impacted_assets": [], "volatility_implication": "Neutral", "llm_tone_score": 0}} diff --git a/Data/3_Gold_Semantic/SEC_Insider_Trades/2026-04-08/qdrant_ready.jsonl b/Data/3_Gold_Semantic/SEC_Insider_Trades/2026-04-08/qdrant_ready.jsonl new file mode 100644 index 0000000..84369a1 --- /dev/null +++ b/Data/3_Gold_Semantic/SEC_Insider_Trades/2026-04-08/qdrant_ready.jsonl @@ -0,0 +1,59 @@ +{"text": "O'Toole Amie Thuener (Vp, Chief Accounting Officer) of GOOG sold 617 shares worth $178,701.71.", "metadata": {"ticker": "GOOG", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001193125-26-142372", "url": "https://www.sec.gov/Archives/edgar/data/1652044/000119312526142372/xslF345X06/ownership.xml", "ingested_at": "2026-04-08T12:48:30.190015", "transaction_date": "2026-04-01", "tone_score": -5, "action_direction": "SELL", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:28.348352"}} +{"text": "O'Toole Amie Thuener (Vp, Chief Accounting Officer) of GOOGL sold 617 shares worth $178,701.71.", "metadata": {"ticker": "GOOGL", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001193125-26-142372", "url": "https://www.sec.gov/Archives/edgar/data/1652044/000119312526142372/xslF345X06/ownership.xml", "ingested_at": "2026-04-08T12:48:29.315822", "transaction_date": "2026-04-01", "tone_score": -5, "action_direction": "SELL", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:28.347635"}} +{"text": "Lilak Stephanie (Evp And Chief People Officer) of MDLZ acquired (via RSU vesting) 3,218 shares worth $0.00.", "metadata": {"ticker": "MDLZ", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023648", "url": "https://www.sec.gov/Archives/edgar/data/1103982/000162828026023648/xslF345X06/wk-form4_1775247097.xml", "ingested_at": "2026-04-08T12:48:53.535143", "transaction_date": "2026-04-01", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:28.348741"}} +{"text": "Kuhn Volker (Evp And President, Europe) of MDLZ acquired (via RSU vesting) 90 shares worth $0.00.", "metadata": {"ticker": "MDLZ", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023646", "url": "https://www.sec.gov/Archives/edgar/data/1103982/000162828026023646/xslF345X06/wk-form4_1775247057.xml", "ingested_at": "2026-04-08T12:48:53.778010", "transaction_date": "2026-04-01", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:28.348769"}} +{"text": "Sanders Adam (Corp. Controller & Cao) of AMAT acquired (via RSU vesting) 125 shares worth $0.00.", "metadata": {"ticker": "AMAT", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001628280-26-023379", "url": "https://www.sec.gov/Archives/edgar/data/6951/000162828026023379/xslF345X06/wk-form4_1775169858.xml", "ingested_at": "2026-04-08T12:48:46.179586", "transaction_date": "2026-04-01", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:28.348296"}} +{"text": "LEWIS AYLWIN B (Other) of MAR acquired (via RSU vesting) 11 shares worth $0.00.", "metadata": {"ticker": "MAR", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0001225208-26-004132", "url": "https://www.sec.gov/Archives/edgar/data/1048286/000122520826004132/xslF345X06/doc4.xml", "ingested_at": "2026-04-08T12:49:02.493404", "transaction_date": "2026-03-31", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:28.347263"}} +{"text": "Broadcom and Google entered into a Long Term Agreement for custom TPUs and Supply Assurance Agreement for networking components. Anthropic will access approximately 3.5 gigawatts of next-generation TPU-based AI compute capacity starting in 2027, dependent on commercial success.", "metadata": {"ticker": "AVGO", "form_type": "8-K", "filed_at": "2026-04-06", "accession_no": "0001193125-26-144028", "url": "https://www.sec.gov/Archives/edgar/data/1730168/000119312526144028/d87999d8k.htm", "ingested_at": "2026-04-08T12:48:32.383033", "transaction_date": "2023-02-14", "tone_score": 0, "action_direction": "NONE", "topics": ["Mergers and Acquisitions", "Partnership", "Technology", "Forward-Looking Statements"], "processed_at": "2026-04-08T17:12:40.429912"}} +{"text": "O'BRIEN DEIRDRE (Senior Vice President) of AAPL sold 128,634 shares worth $7,660,875.04 under a pre-planned 10b5-1 trading plan.", "metadata": {"ticker": "AAPL", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001140361-26-013192", "url": "https://www.sec.gov/Archives/edgar/data/320193/000114036126013192/xslF345X06/form4.xml", "ingested_at": "2026-04-08T12:48:26.662928", "transaction_date": "2026-04-01", "tone_score": -1, "action_direction": "SELL", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:40.430018"}} +{"text": "Khan Sabih (Coo) of AAPL acquired (via RSU vesting) 97,634 shares worth $0.00.", "metadata": {"ticker": "AAPL", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001140361-26-013191", "url": "https://www.sec.gov/Archives/edgar/data/320193/000114036126013191/xslF345X06/form4.xml", "ingested_at": "2026-04-08T12:48:26.888609", "transaction_date": "2026-04-01", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:40.430044"}} +{"text": "COOK TIMOTHY D (Chief Executive Officer) of AAPL sold 263,152 shares worth $16,512,197.73 under a pre-planned 10b5-1 trading plan.", "metadata": {"ticker": "AAPL", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001140361-26-013190", "url": "https://www.sec.gov/Archives/edgar/data/320193/000114036126013190/xslF345X06/form4.xml", "ingested_at": "2026-04-08T12:48:27.106687", "transaction_date": "2026-04-01", "tone_score": -1, "action_direction": "SELL", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:40.430068"}} +{"text": "Liu Joy (Evp And Chief Legal Officer) of VRTX sold 978 shares worth $439,288.26 under a pre-planned 10b5-1 trading plan.", "metadata": {"ticker": "VRTX", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0000875320-26-000157", "url": "https://www.sec.gov/Archives/edgar/data/875320/000087532026000157/xslF345X06/wk-form4_1775249628.xml", "ingested_at": "2026-04-08T12:48:51.663358", "transaction_date": "2026-04-01", "tone_score": -1, "action_direction": "SELL", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:40.430084"}} +{"text": "Herrington Douglas J (Ceo Worldwide Amazon Stores) of AMZN sold 1,000 shares worth $210,500.00 under a pre-planned 10b5-1 trading plan.", "metadata": {"ticker": "AMZN", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001018724-26-000010", "url": "https://www.sec.gov/Archives/edgar/data/1018724/000101872426000010/xslF345X06/wk-form4_1775248886.xml", "ingested_at": "2026-04-08T12:48:28.351458", "transaction_date": "2026-04-01", "tone_score": -1, "action_direction": "SELL", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:40.430099"}} +{"text": "Broadcom Inc. announces the departure of Chief Financial Officer Kirsten M. Spears and her replacement by Amie Thuener, effective June 12, 2026.", "metadata": {"ticker": "AVGO", "form_type": "8-K", "filed_at": "2026-04-02", "accession_no": "0001193125-26-140574", "url": "https://www.sec.gov/Archives/edgar/data/1730168/000119312526140574/d109450d8k.htm", "ingested_at": "2026-04-08T12:48:32.628969", "transaction_date": "2026-03-30", "tone_score": 0, "action_direction": "NONE", "topics": ["Executive Changes", "Financial Officers", "Compensation"], "processed_at": "2026-04-08T17:12:43.230569"}} +{"text": "Paul Josh D. (Chief Accounting Officer) of PANW sold 2,047 shares worth $177,540.00 under a pre-planned 10b5-1 trading plan.", "metadata": {"ticker": "PANW", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001882285-26-000007", "url": "https://www.sec.gov/Archives/edgar/data/1327567/000188228526000007/xslF345X06/ownership.xml", "ingested_at": "2026-04-08T12:48:52.842465", "transaction_date": "2026-04-01", "tone_score": -1, "action_direction": "SELL", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:43.230647"}} +{"text": "Golechha Dipak (Evp, Chief Financial Officer) of PANW sold 5,000 shares worth $802,076.70 under a pre-planned 10b5-1 trading plan.", "metadata": {"ticker": "PANW", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001852540-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/1327567/000185254026000002/xslF345X06/ownership.xml", "ingested_at": "2026-04-08T12:48:53.042265", "transaction_date": "2026-04-01", "tone_score": -1, "action_direction": "SELL", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:43.230671"}} +{"text": "ARNZEN APRIL S (Evp And Chief People Officer) of MU sold 40,000 shares worth $13,895,761.74 under a pre-planned 10b5-1 trading plan.", "metadata": {"ticker": "MU", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001632063-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/723125/000163206326000002/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-08T12:48:57.862487", "transaction_date": "2026-04-01", "tone_score": -1, "action_direction": "SELL", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:43.230689"}} +{"text": "Liu Teyin M (Director) of MU acquired (via RSU vesting) 97 shares worth $0.00.", "metadata": {"ticker": "MU", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0002058769-26-000003", "url": "https://www.sec.gov/Archives/edgar/data/723125/000205876926000003/xslF345X06/primarydocument.xml", "ingested_at": "2026-04-08T12:48:58.070656", "transaction_date": "2026-03-31", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:43.230706"}} +{"text": "Alphabet Inc.'s Vice President, Corporate Controller and Principal Accounting Officer Amie Thuener O'Toole resigned effective April 9, 2026, to pursue another opportunity. The resignation was not due to any disagreement with the company.", "metadata": {"ticker": "GOOG", "form_type": "8-K", "filed_at": "2026-04-02", "accession_no": "0001652044-26-000031", "url": "https://www.sec.gov/Archives/edgar/data/1652044/000165204426000031/goog-20260330.htm", "ingested_at": "2026-04-08T12:48:30.394411", "transaction_date": "2026-03-30", "tone_score": 0, "action_direction": "NONE", "topics": ["Executive Departure", "Accounting"], "processed_at": "2026-04-08T17:12:46.150798"}} +{"text": "Goodarzi Sasan K (Ceo, President And Director) of INTU acquired (via RSU vesting) 4,521 shares worth $0.00.", "metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023706", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023706/xslF345X06/wk-form4_1775249487.xml", "ingested_at": "2026-04-08T12:48:40.705654", "transaction_date": "2026-04-01", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:46.151014"}} +{"text": "McLean Kerry J (Evp, Gen. Counsel & Corp. Sec.) of INTU acquired (via RSU vesting) 1,151 shares worth $0.00.", "metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023704", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023704/xslF345X06/wk-form4_1775249417.xml", "ingested_at": "2026-04-08T12:48:40.933207", "transaction_date": "2026-04-01", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:46.151034"}} +{"text": "Hotz Lauren D (Svp, Chief Accounting Officer) of INTU acquired (via RSU vesting) 451 shares worth $0.00.", "metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023701", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023701/xslF345X06/wk-form4_1775249278.xml", "ingested_at": "2026-04-08T12:48:41.133725", "transaction_date": "2026-04-01", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:46.151053"}} +{"text": "Hilliard Caryl Lyn (Evp, People And Places) of INTU acquired (via RSU vesting) 681 shares worth $0.00.", "metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023698", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023698/xslF345X06/wk-form4_1775249186.xml", "ingested_at": "2026-04-08T12:48:41.343578", "transaction_date": "2026-04-01", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:46.151070"}} +{"text": "Hanebrink Anton (Evp, Corp Strategy And Dev) of INTU acquired (via RSU vesting) 1,242 shares worth $0.00.", "metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023696", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023696/xslF345X06/wk-form4_1775249122.xml", "ingested_at": "2026-04-08T12:48:41.573994", "transaction_date": "2026-04-01", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:46.151087"}} +{"text": "Aujla Sandeep (Evp And Cfo) of INTU acquired (via RSU vesting) 5,085 shares worth $0.00.", "metadata": {"ticker": "INTU", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001628280-26-023690", "url": "https://www.sec.gov/Archives/edgar/data/896878/000162828026023690/xslF345X06/wk-form4_1775248743.xml", "ingested_at": "2026-04-08T12:48:41.795152", "transaction_date": "2026-04-01", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:46.151102"}} +{"text": "Neumann Spencer Adam (Chief Financial Officer) of NFLX sold 57,260 shares worth $2,805,740.00 under a pre-planned 10b5-1 trading plan.", "metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001543133-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000154313326000002/xslF345X06/wk-form4_1775246849.xml", "ingested_at": "2026-04-08T12:48:34.271973", "transaction_date": "2026-04-02", "tone_score": -1, "action_direction": "SELL", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:46.151119"}} +{"text": "HASTINGS REED (Other) of NFLX sold 841,100 shares worth $40,156,465.06 under a pre-planned 10b5-1 trading plan.", "metadata": {"ticker": "NFLX", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001065280-26-000134", "url": "https://www.sec.gov/Archives/edgar/data/1065280/000106528026000134/xslF345X06/wk-form4_1775167354.xml", "ingested_at": "2026-04-08T12:48:34.906612", "transaction_date": "2026-04-01", "tone_score": -1, "action_direction": "SELL", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:46.151150"}} +{"text": "Frates Caton (Executive Vice President) of COST sold 700 shares worth $695,100.00.", "metadata": {"ticker": "COST", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0000909832-26-000039", "url": "https://www.sec.gov/Archives/edgar/data/909832/000090983226000039/xslF345X06/form4.xml", "ingested_at": "2026-04-08T12:48:33.357291", "transaction_date": "2026-04-01", "tone_score": -3, "action_direction": "SELL", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:46.151234"}} +{"text": "Alphabet Inc.'s Vice President, Corporate Controller and Principal Accounting Officer Amie Thuener O'Toole resigned effective April 9, 2026, to pursue another opportunity. The resignation was not due to any disagreement with the company.", "metadata": {"ticker": "GOOGL", "form_type": "8-K", "filed_at": "2026-04-02", "accession_no": "0001652044-26-000031", "url": "https://www.sec.gov/Archives/edgar/data/1652044/000165204426000031/goog-20260330.htm", "ingested_at": "2026-04-08T12:48:29.521443", "transaction_date": "2026-03-30", "tone_score": 0, "action_direction": "NONE", "topics": ["Executive Departure", "Accounting Officer"], "processed_at": "2026-04-08T17:12:49.085630"}} +{"text": "Murdock Daniel C. (Evp & Chief Accounting Officer) of CMCSA acquired (via RSU vesting) 7,341 shares worth $0.00.", "metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001225208-26-004342", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004342/xslF345X06/doc4.xml", "ingested_at": "2026-04-08T12:48:43.821475", "transaction_date": "2026-04-03", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:49.085719"}} +{"text": "Smith Gordon (Other) of CMCSA acquired (via RSU vesting) 1,176 shares worth $0.00.", "metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001225208-26-004203", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004203/xslF345X06/doc4.xml", "ingested_at": "2026-04-08T12:48:44.045592", "transaction_date": "2026-03-31", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:49.085742"}} +{"text": "Honickman Jeffrey A (Other) of CMCSA acquired (via RSU vesting) 1,524 shares worth $0.00.", "metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001225208-26-004202", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004202/xslF345X06/doc4.xml", "ingested_at": "2026-04-08T12:48:44.268546", "transaction_date": "2026-03-31", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:49.085761"}} +{"text": "BREEN EDWARD D (Other) of CMCSA acquired (via RSU vesting) 697 shares worth $0.00.", "metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001225208-26-004201", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004201/xslF345X06/doc4.xml", "ingested_at": "2026-04-08T12:48:44.473523", "transaction_date": "2026-03-31", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:49.085778"}} +{"text": "Brady Louise F. (Other) of CMCSA acquired (via RSU vesting) 1,176 shares worth $0.00.", "metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001225208-26-004200", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004200/xslF345X06/doc4.xml", "ingested_at": "2026-04-08T12:48:44.697700", "transaction_date": "2026-03-31", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:49.085793"}} +{"text": "Baltimore Thomas J Jr (Other) of CMCSA acquired (via RSU vesting) 1,176 shares worth $0.00.", "metadata": {"ticker": "CMCSA", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001225208-26-004199", "url": "https://www.sec.gov/Archives/edgar/data/1166691/000122520826004199/xslF345X06/doc4.xml", "ingested_at": "2026-04-08T12:48:44.896983", "transaction_date": "2026-03-31", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:49.085808"}} +{"text": "Establishment of performance goals under the 2026 Bonus Program and adoption of the 2026 Long Term Retention Program.", "metadata": {"ticker": "MELI", "form_type": "8-K", "filed_at": "2026-04-03", "accession_no": "0001999371-26-007656", "url": "https://www.sec.gov/Archives/edgar/data/1099590/000199937126007656/meli_8k-033126.htm", "ingested_at": "2026-04-08T12:48:59.995354", "transaction_date": "2026-03-31", "tone_score": 0, "action_direction": "NONE", "topics": ["Compensation", "Executive Management", "Performance Goals"], "processed_at": "2026-04-08T17:12:51.679444"}} +{"text": "RYAN ARTHUR F (Other) of REGN sold 100 shares worth $77,727.28 under a pre-planned 10b5-1 trading plan.", "metadata": {"ticker": "REGN", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001104659-26-039613", "url": "https://www.sec.gov/Archives/edgar/data/872589/000110465926039613/xslF345X06/tm2611142-1_4seq1.xml", "ingested_at": "2026-04-08T12:48:54.906167", "transaction_date": "2026-04-01", "tone_score": -1, "action_direction": "SELL", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:51.679523"}} +{"text": "Zhu Xiaotong (Svp) of TSLA acquired (via RSU vesting) 20,000 shares worth $0.00.", "metadata": {"ticker": "TSLA", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0001972928-26-000002", "url": "https://www.sec.gov/Archives/edgar/data/1318605/000197292826000002/xslF345X06/edgardoc.xml", "ingested_at": "2026-04-08T12:48:31.110524", "transaction_date": "2026-03-31", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:51.679545"}} +{"text": "Micron Technology, Inc. issued press releases announcing the pricing of its cash tender offers for outstanding senior notes and the expiration of those offers.", "metadata": {"ticker": "MU", "form_type": "8-K", "filed_at": "2026-04-01", "accession_no": "0001104659-26-038249", "url": "https://www.sec.gov/Archives/edgar/data/723125/000110465926038249/tm2610810d1_8k.htm", "ingested_at": "2026-04-08T12:48:58.540588", "transaction_date": "2026-04-01", "tone_score": 0, "action_direction": "NONE", "topics": ["Tender Offer", "Financial Statement"], "processed_at": "2026-04-08T17:12:54.131398"}} +{"text": "Wilson-Thompson Kathleen (Other) of TSLA sold 65,809 shares worth $9,273,888.40 under a pre-planned 10b5-1 trading plan.", "metadata": {"ticker": "TSLA", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0001104659-26-038682", "url": "https://www.sec.gov/Archives/edgar/data/1318605/000110465926038682/xslF345X06/tm2610684-1_4seq1.xml", "ingested_at": "2026-04-08T12:48:31.571595", "transaction_date": "2026-03-30", "tone_score": -1, "action_direction": "SELL", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:12:54.131501"}} +{"text": "CrowdStrike announces $500 million additional share repurchase authorization, bringing total to $1.5 billion.", "metadata": {"ticker": "CRWD", "form_type": "8-K", "filed_at": "2026-04-06", "accession_no": "0001535527-26-000013", "url": "https://www.sec.gov/Archives/edgar/data/1535527/000153552726000013/crwd-20260406.htm", "ingested_at": "2026-04-08T12:49:01.938568", "transaction_date": "2026-04-06", "tone_score": 0, "action_direction": "NONE", "topics": ["M&A", "Share Repurchase"], "processed_at": "2026-04-08T17:12:56.338764"}} +{"text": "Regeneron Pharmaceuticals, Inc. expects an acquired in-process research and development charge of approximately $102 million on a pre-tax basis for the first quarter 2026, which will negatively impact GAAP and non-GAAP net income per diluted share by approximately $0.81.", "metadata": {"ticker": "REGN", "form_type": "8-K", "filed_at": "2026-04-08", "accession_no": "0001104659-26-040661", "url": "https://www.sec.gov/Archives/edgar/data/872589/000110465926040661/tm2611354d1_8k.htm", "ingested_at": "2026-04-08T12:48:54.660815", "transaction_date": "2023-04-28", "tone_score": 0, "action_direction": "NONE", "topics": ["Financial Results", "Guidance", "Forward-Looking Statements", "Non-GAAP Financial Measures"], "processed_at": "2026-04-08T17:13:00.103784"}} +{"text": "Cunningham Paul (Sr. Vice President) of CDNS sold 1,000 shares worth $280,190.00 under a pre-planned 10b5-1 trading plan.", "metadata": {"ticker": "CDNS", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0000813672-26-000040", "url": "https://www.sec.gov/Archives/edgar/data/813672/000081367226000040/xslF345X06/wk-form4_1775243708.xml", "ingested_at": "2026-04-08T12:48:59.459023", "transaction_date": "2026-04-01", "tone_score": -1, "action_direction": "SELL", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:13:00.103886"}} +{"text": "ROCHE VINCENT (Chair & Ceo) of ADI sold 20,000 shares worth $3,181,400.00 under a pre-planned 10b5-1 trading plan.", "metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-03", "accession_no": "0001201872-26-000008", "url": "https://www.sec.gov/Archives/edgar/data/6281/000120187226000008/xslF345X06/wk-form4_1775247205.xml", "ingested_at": "2026-04-08T12:48:56.199337", "transaction_date": "2026-04-01", "tone_score": -1, "action_direction": "SELL", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:13:00.103904"}} +{"text": "Sondel Michael (Cao (Principal Acct. Officer)) of ADI acquired (via RSU vesting) 406 shares worth $0.00.", "metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0001768266-26-000004", "url": "https://www.sec.gov/Archives/edgar/data/6281/000176826626000004/xslF345X06/wk-form4_1775074685.xml", "ingested_at": "2026-04-08T12:48:56.418972", "transaction_date": "2026-03-30", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:13:00.103920"}} +{"text": "ROCHE VINCENT (Chair & Ceo) of ADI acquired (via RSU vesting) 27,027 shares worth $0.00.", "metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0001201872-26-000006", "url": "https://www.sec.gov/Archives/edgar/data/6281/000120187226000006/xslF345X06/wk-form4_1775074650.xml", "ingested_at": "2026-04-08T12:48:56.676905", "transaction_date": "2026-03-30", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:13:00.103943"}} +{"text": "Nakamura Katsufumi (Svp, Chief Customer Officer) of ADI acquired (via RSU vesting) 121 shares worth $0.00.", "metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0002044259-26-000007", "url": "https://www.sec.gov/Archives/edgar/data/6281/000204425926000007/xslF345X06/wk-form4_1775074599.xml", "ingested_at": "2026-04-08T12:48:56.894938", "transaction_date": "2026-03-30", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:13:00.103957"}} +{"text": "Jain Vivek (Evp, Global Operations) of ADI acquired (via RSU vesting) 6,386 shares worth $0.00.", "metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0000006281-26-000037", "url": "https://www.sec.gov/Archives/edgar/data/6281/000000628126000037/xslF345X06/wk-form4_1775074566.xml", "ingested_at": "2026-04-08T12:48:57.102825", "transaction_date": "2026-03-30", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:13:00.103972"}} +{"text": "Cotter Martin (Svp, Vertical Business Units) of ADI acquired (via RSU vesting) 3,881 shares worth $0.00.", "metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-01", "accession_no": "0001685760-26-000004", "url": "https://www.sec.gov/Archives/edgar/data/6281/000168576026000004/xslF345X06/wk-form4_1775074528.xml", "ingested_at": "2026-04-08T12:48:57.316644", "transaction_date": "2026-03-30", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:13:00.103984"}} +{"text": "Shimer Peter A (Other) of CSCO acquired (via RSU vesting) 2,333 shares worth $0.00.", "metadata": {"ticker": "CSCO", "form_type": "4", "filed_at": "2026-04-07", "accession_no": "0000858877-26-000052", "url": "https://www.sec.gov/Archives/edgar/data/858877/000085887726000052/xslF345X06/wk-form4_1775592372.xml", "ingested_at": "2026-04-08T12:48:37.663506", "transaction_date": "2026-04-06", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:13:00.103997"}} +{"text": "Tesla publishes press release on April 2, 2026, announcing results of operations and financial condition. No additional information provided.", "metadata": {"ticker": "TSLA", "form_type": "8-K", "filed_at": "2026-04-02", "accession_no": "0001628280-26-022956", "url": "https://www.sec.gov/Archives/edgar/data/1318605/000162828026022956/tsla-20260402.htm", "ingested_at": "2026-04-08T12:48:31.313708", "transaction_date": "2026-04-02", "tone_score": 0, "action_direction": "NONE", "topics": ["financials", "operations"], "processed_at": "2026-04-08T17:13:02.245396"}} +{"text": "Intel's Executive Vice President and Chief Legal Officer, April Miller Boise, will separate from the company effective June 1, 2026, and receive severance benefits in accordance with the Intel Corporation Executive Severance Plan.", "metadata": {"ticker": "INTC", "form_type": "8-K", "filed_at": "2026-04-03", "accession_no": "0000050863-26-000069", "url": "https://www.sec.gov/Archives/edgar/data/50863/000005086326000069/intc-20260330.htm", "ingested_at": "2026-04-08T12:48:45.429994", "transaction_date": "2026-03-30", "tone_score": 0, "action_direction": "NONE", "topics": ["Executive Departure", "Severance Benefits"], "processed_at": "2026-04-08T17:13:05.107708"}} +{"text": "Starbucks completed the transaction to form a joint venture with Boyu Capital, acquiring a 60% interest in its retail operations in China.", "metadata": {"ticker": "SBUX", "form_type": "8-K", "filed_at": "2026-04-02", "accession_no": "0000829224-26-000064", "url": "https://www.sec.gov/Archives/edgar/data/829224/000082922426000064/sbux-20260402.htm", "ingested_at": "2026-04-08T12:48:52.264984", "transaction_date": "2026-04-02", "tone_score": 0, "action_direction": "NONE", "topics": ["Mergers and Acquisitions", "China Operations"], "processed_at": "2026-04-08T17:13:07.495474"}} +{"text": "Cisco Systems, Inc. announces the departure of Director Daniel H. Schulman due to his new role at Verizon Communications Inc., and the appointment of Peter A. Shimer as a member of the Board effective April 6, 2026.", "metadata": {"ticker": "CSCO", "form_type": "8-K", "filed_at": "2026-04-06", "accession_no": "0000858877-26-000048", "url": "https://www.sec.gov/Archives/edgar/data/858877/000085887726000048/csco-20260331.htm", "ingested_at": "2026-04-08T12:48:37.896486", "transaction_date": "2026-04-04", "tone_score": 0, "action_direction": "NONE", "topics": ["Departure of Directors or Certain Officers; Election of Directors; Appointment of Certain Officers; Compensatory Arrangements of Certain Officers", "Indemnity Agreement"], "processed_at": "2026-04-08T17:13:11.452983"}} +{"text": "Grech Patricia Y (Svp, Chief Accounting Officer) of QCOM sold 85 shares worth $10,667.50 under a pre-planned 10b5-1 trading plan.", "metadata": {"ticker": "QCOM", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0000804328-26-000051", "url": "https://www.sec.gov/Archives/edgar/data/804328/000080432826000051/xslF345X06/edgardoc.xml", "ingested_at": "2026-04-08T12:48:39.267926", "transaction_date": "2026-04-02", "tone_score": -1, "action_direction": "SELL", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:13:11.453080"}} +{"text": "MCLAUGHLIN MARK D (Other) of QCOM acquired (via RSU vesting) 538 shares worth $0.00.", "metadata": {"ticker": "QCOM", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0000804328-26-000049", "url": "https://www.sec.gov/Archives/edgar/data/804328/000080432826000049/xslF345X06/edgardoc.xml", "ingested_at": "2026-04-08T12:48:39.472942", "transaction_date": "2026-03-31", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:13:11.453107"}} +{"text": "TRICOIRE JEAN-PASCAL (Other) of QCOM acquired (via RSU vesting) 262 shares worth $0.00.", "metadata": {"ticker": "QCOM", "form_type": "4", "filed_at": "2026-04-02", "accession_no": "0000804328-26-000048", "url": "https://www.sec.gov/Archives/edgar/data/804328/000080432826000048/xslF345X06/edgardoc.xml", "ingested_at": "2026-04-08T12:48:39.683945", "transaction_date": "2026-03-31", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-08T17:13:11.453126"}} +{"text": "Booking Holdings Inc. filed an amendment to its Restated Certificate of Incorporation to effect a 25-for-1 forward stock split and increase authorized common stock from 1B to 25B shares.", "metadata": {"ticker": "BKNG", "form_type": "8-K", "filed_at": "2026-04-02", "accession_no": "0000950157-26-000465", "url": "https://www.sec.gov/Archives/edgar/data/1075531/000095015726000465/form8-k.htm", "ingested_at": "2026-04-08T12:48:50.322210", "transaction_date": "2026-04-02", "tone_score": 0, "action_direction": "NONE", "topics": ["corporate action", "stock split"], "processed_at": "2026-04-08T17:13:14.127822"}} +{"text": "Booking Holdings Inc. appoints Caroline Sullivan as Senior Vice President, Chief Accounting Officer, and Controller.", "metadata": {"ticker": "BKNG", "form_type": "8-K", "filed_at": "2026-04-02", "accession_no": "0001075531-26-000014", "url": "https://www.sec.gov/Archives/edgar/data/1075531/000107553126000014/bkng-20260402.htm", "ingested_at": "2026-04-08T12:48:50.613430", "transaction_date": "2026-04-02", "tone_score": 0, "action_direction": "NONE", "topics": ["Executive Appointments", "Compensation", "Employment Agreements"], "processed_at": "2026-04-08T17:13:16.442511"}} +{"text": "Appointment of Director Kurt Sievers and retirement of Director Lynn Radakovich. Mr. Sievers will be compensated in accordance with the Company's non-employee director compensation program.", "metadata": {"ticker": "BKNG", "form_type": "8-K", "filed_at": "2026-04-01", "accession_no": "0001075531-26-000012", "url": "https://www.sec.gov/Archives/edgar/data/1075531/000107553126000012/bkng-20260401.htm", "ingested_at": "2026-04-08T12:48:50.961407", "transaction_date": "2026-04-01", "tone_score": 0, "action_direction": "NONE", "topics": ["Director Appointment", "Director Retirement"], "processed_at": "2026-04-08T17:13:19.071263"}} diff --git a/Data/3_Gold_Semantic/SEC_Insider_Trades/2026-04-09/qdrant_ready.jsonl b/Data/3_Gold_Semantic/SEC_Insider_Trades/2026-04-09/qdrant_ready.jsonl new file mode 100644 index 0000000..846abaf --- /dev/null +++ b/Data/3_Gold_Semantic/SEC_Insider_Trades/2026-04-09/qdrant_ready.jsonl @@ -0,0 +1,4 @@ +{"text": "Papermaster Mark D (Chief Technology Officer & Evp) of AMD sold 3,293 shares worth $740,925.00 under a pre-planned 10b5-1 trading plan.", "metadata": {"ticker": "AMD", "form_type": "4", "filed_at": "2026-04-08", "accession_no": "0000002488-26-000064", "url": "https://www.sec.gov/Archives/edgar/data/2488/000000248826000064/xslF345X06/wk-form4_1775679123.xml", "ingested_at": "2026-04-09T14:35:22.976531", "transaction_date": "2026-04-06", "tone_score": -1, "action_direction": "SELL", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-09T14:45:22.544421"}} +{"text": "BREWER BRADY (Ceo, International) of SBUX sold 1,641 shares worth $147,690.00 under a pre-planned 10b5-1 trading plan.", "metadata": {"ticker": "SBUX", "form_type": "4", "filed_at": "2026-04-08", "accession_no": "0000829224-26-000066", "url": "https://www.sec.gov/Archives/edgar/data/829224/000082922426000066/xslF345X06/form4.xml", "ingested_at": "2026-04-09T14:35:32.974848", "transaction_date": "2026-04-06", "tone_score": -1, "action_direction": "SELL", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-09T14:45:22.544884"}} +{"text": "Intel repurchased Apollo-managed funds' 49% equity interest in their joint venture related to Intel's Fab 34 in Ireland for $14.2 billion, financed by cash on hand and a bridge loan.", "metadata": {"ticker": "INTC", "form_type": "8-K", "filed_at": "2026-04-08", "accession_no": "0000050863-26-000072", "url": "https://www.sec.gov/Archives/edgar/data/50863/000005086326000072/intc-20260408.htm", "ingested_at": "2026-04-09T14:35:30.225494", "transaction_date": "2026-04-08", "tone_score": 0, "action_direction": "NONE", "topics": ["MergersAndAcquisitions", "FinancialTransactions"], "processed_at": "2026-04-09T14:45:34.974364"}} +{"text": "Amazon.com, Inc. (Registrant) filed a Current Report on Form 8-K with the Securities and Exchange Commission, disclosing Regulation FD Disclosure and Financial Statements and Exhibits.", "metadata": {"ticker": "AMZN", "form_type": "8-K", "filed_at": "2026-04-09", "accession_no": "0001104659-26-041034", "url": "https://www.sec.gov/Archives/edgar/data/1018724/000110465926041034/tm263815d2_8k.htm", "ingested_at": "2026-04-09T14:35:16.491691", "transaction_date": "2026-04-09", "tone_score": 0, "action_direction": "NONE", "topics": ["REGULATION FD DISCLOSURE", "FINANCIAL STATEMENTS AND EXHIBITS"], "processed_at": "2026-04-09T14:45:37.997412"}} diff --git a/Data/3_Gold_Semantic/SEC_Insider_Trades/2026-04-10/qdrant_ready.jsonl b/Data/3_Gold_Semantic/SEC_Insider_Trades/2026-04-10/qdrant_ready.jsonl new file mode 100644 index 0000000..480615d --- /dev/null +++ b/Data/3_Gold_Semantic/SEC_Insider_Trades/2026-04-10/qdrant_ready.jsonl @@ -0,0 +1,6 @@ +{"text": "Sondel Michael (Cao (Principal Acct. Officer)) of ADI acquired (via RSU vesting) 1,341 shares worth $0.00.", "metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-09", "accession_no": "0000006281-26-000043", "url": "https://www.sec.gov/Archives/edgar/data/6281/000000628126000043/xslF345X06/wk-form4_1775768645.xml", "ingested_at": "2026-04-10T16:09:14.401049", "transaction_date": "2026-04-07", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-10T16:11:29.861888"}} +{"text": "ROCHE VINCENT (Chair & Ceo) of ADI acquired (via RSU vesting) 19,712 shares worth $0.00.", "metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-09", "accession_no": "0000006281-26-000042", "url": "https://www.sec.gov/Archives/edgar/data/6281/000000628126000042/xslF345X06/wk-form4_1775768622.xml", "ingested_at": "2026-04-10T16:09:14.605836", "transaction_date": "2026-04-07", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-10T16:11:29.861934"}} +{"text": "Puccio Richard C Jr (Evp And Cfo) of ADI acquired (via RSU vesting) 6,513 shares worth $0.00.", "metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-09", "accession_no": "0000006281-26-000041", "url": "https://www.sec.gov/Archives/edgar/data/6281/000000628126000041/xslF345X06/wk-form4_1775768603.xml", "ingested_at": "2026-04-10T16:09:14.817000", "transaction_date": "2026-04-07", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-10T16:11:29.861954"}} +{"text": "Nakamura Katsufumi (Svp, Chief Customer Officer) of ADI acquired (via RSU vesting) 4,085 shares worth $0.00.", "metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-09", "accession_no": "0000006281-26-000040", "url": "https://www.sec.gov/Archives/edgar/data/6281/000000628126000040/xslF345X06/wk-form4_1775768583.xml", "ingested_at": "2026-04-10T16:09:15.042283", "transaction_date": "2026-04-07", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-10T16:11:29.861968"}} +{"text": "Jain Vivek (Evp, Global Operations) of ADI acquired (via RSU vesting) 6,734 shares worth $0.00.", "metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-09", "accession_no": "0000006281-26-000039", "url": "https://www.sec.gov/Archives/edgar/data/6281/000000628126000039/xslF345X06/wk-form4_1775768561.xml", "ingested_at": "2026-04-10T16:09:15.241550", "transaction_date": "2026-04-07", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-10T16:11:29.861982"}} +{"text": "Cotter Martin (Svp, Vertical Business Units) of ADI acquired (via RSU vesting) 5,807 shares worth $0.00.", "metadata": {"ticker": "ADI", "form_type": "4", "filed_at": "2026-04-09", "accession_no": "0000006281-26-000038", "url": "https://www.sec.gov/Archives/edgar/data/6281/000000628126000038/xslF345X06/wk-form4_1775768544.xml", "ingested_at": "2026-04-10T16:09:15.424624", "transaction_date": "2026-04-07", "tone_score": 0, "action_direction": "ACQUIRE/VEST", "topics": ["Insider Trading", "Form 4"], "processed_at": "2026-04-10T16:11:29.861994"}} diff --git a/Data/Agent_Context/latest_macro_context.md b/Data/Agent_Context/latest_macro_context.md new file mode 100644 index 0000000..83d35d6 --- /dev/null +++ b/Data/Agent_Context/latest_macro_context.md @@ -0,0 +1,16 @@ +## 📊 Macro & Market Daily Snapshot +> **Generated on:** 2026-04-16 +> **Note to LLM:** Macro indicators lag behind market data. Use YoY/MoM changes to gauge economic momentum. + +### 📈 Market Data (Daily) +- **[Equity Index] S&P 500 (^GSPC)**: 7022.95 Points | Change: **+0.80%** *(Observed: 2026-04-15)* +- **[Equity Index] NASDAQ (^IXIC)**: 24016.02 Points | Change: **+1.59%** *(Observed: 2026-04-15)* +- **[Volatility Index] VIX Volatility (^VIX)**: 18.25 Points | Change: **+0.44%** *(Observed: 2026-04-16)* +- **[Currency] US Dollar Index (DX-Y.NYB)**: 98.22 Points | Change: **+0.16%** *(Observed: 2026-04-16)* +- **[Commodity ETF] Gold ETF (GLD)**: 440.46 USD | Change: **-1.04%** *(Observed: 2026-04-15)* +- **[Commodity ETF] Silver ETF (SLV)**: 71.84 USD | Change: **-0.28%** *(Observed: 2026-04-15)* + +### 🏛️ Macro Economic Indicators (Lagging) +- **[Interest Rate] Effective Federal Funds Rate (FEDFUNDS)**: 3.64 % | MoM: **+0.00%** | YoY: **-15.94%** *(Observed: 2026-03-01)* +- **[Inflation] CPI (Inflation) (CPIAUCSL)**: 330.29 Index | MoM: **+0.87%** | YoY: **+3.32%** *(Observed: 2026-03-01)* +- **[Labor Market] Unemployment Rate (UNRATE)**: 4.30 % | MoM: **-2.27%** | YoY: **+2.38%** *(Observed: 2026-03-01)* \ No newline at end of file diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index b5182ed..0000000 --- a/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -# Use official Python base image -FROM python:3.11-slim - -# Set working directory -WORKDIR /app - -# Install system dependencies for building native extensions -RUN apt-get update && apt-get install -y --no-install-recommends gcc build-essential && rm -rf /var/lib/apt/lists/* - -# Copy dependency file -COPY requirements.txt . - -# Install Python dependencies -# --no-cache-dir reduces image size -RUN pip install --no-cache-dir -r requirements.txt - -# Copy project files -COPY . . - -# Default command -# Run main application -CMD ["python", "src/main.py"] diff --git a/README.md b/README.md index 2742dc9..0cc499b 100644 --- a/README.md +++ b/README.md @@ -1,145 +1,190 @@ -# Options Bot 🤖 - -An automated financial research pipeline that synthesizes data from multiple sources (YouTube, News, Reddit, FRED, SEC filings, and market data) to generate daily paper-trading options ideas. The system uses a Qdrant vector database for knowledge management and a locally-hosted LLM (via Ollama) within a multi-agent framework to produce structured analysis reports. - -## 🎯 Project Objective - -This project serves as an educational exercise to: - -1. Master the engineering of multi-agent LLM systems. -2. Develop a practical understanding of how to integrate heterogeneous information sources for decision-making under uncertainty. - -The goal is to build a daily research bot that synthesizes global market and social information streams to generate 5–10 paper-trading options recommendations, complete with detailed rationales and source citations. - ------ - -## ✨ Key Features - - * **Multi-Source Data Pipeline**: Aggregates data from YouTube, Reddit, News APIs, FRED, SEC filings, and general market sources. - * **Vectorized Knowledge Base**: Utilizes a Qdrant vector database for efficient, scalable semantic retrieval of all ingested information. - * **Local LLM Orchestration**: Runs on local, open-source models (e.g., `mistral:7b`, `options-expert`) via Ollama for privacy and cost-effectiveness. - * **Multi-Agent Decision Framework**: Employs an Analyst-Checker-Critic agent loop to synthesize signals, validate facts, and challenge assumptions. - * **Automated Daily Reporting**: Generates structured JSON and Markdown reports with actionable options ideas, rationales, and confidence levels. - ------ - -## 🏗️ System Architecture - -The system operates in a sequential pipeline: - -1. **Data Collection**: Various scraper modules fetch data from their respective sources. -2. **Data Processing & Storage**: The collected text is cleaned, processed, and stored as vector embeddings in the Qdrant database with associated metadata. -3. **LLM-Powered Analysis**: A multi-agent system (`agent_system.py`) queries the vector database to retrieve relevant context and orchestrates a series of LLM calls to analyze the data, generate insights, and formulate trade ideas. -4. **Report Generation**: The final output is structured into a `FinalReport` Pydantic model and saved as both JSON and Markdown files. - -For a detailed visual overview of the data flow and component interactions, please see `ARCHITECTURE.md`. +# Multi-Modal Multi-Agent Financial RAG System + +## 1. Strategic Objectives (Goal) +The primary objective of this project is to democratize institutional-grade options trading by bridging the gap between quantitative market data and qualitative semantic insights. By leveraging a **Medallion Architecture**, the system automates the identification of cross-asset volatility arbitrage opportunities (e.g., GLD/SLV vs. correlated equities). + +**Core outcomes:** +- Reduce trading hallucinations via multi-agent cross-examination (Analyst -> Checker -> Critic -> Finalizer). +- Fuse fragmented data domains (FRED / GPR / SEC / News / options chains) into a single query surface. +- Produce auditable, reproducible recommendation artifacts for paper-trading workflows. + +--- + +## 2. High-Level System Architecture +The system operates on a **Dual-Track Data Engine** designed to handle the heterogeneity of financial markets: +* **Quantitative Track (Structured):** Processes high-frequency numeric data +(Parquet) via SQL-like tools or Pandas Agents to ensure 100% accuracy in +pricing and Greeks. +* **Qualitative Track (Unstructured):** Processes news and SEC filings +through a Hybrid RAG pipeline (Dense + Sparse + Metadata filtering) in Qdrant. +* **State Machine Orchestration:** Uses **LangGraph** to govern the +transition between data retrieval, analysis, and risk auditing. + +```mermaid +flowchart TD + A[Data Ingestion: FRED / SEC / News / yfinance] --> B[Medallion Processing: Bronze -> Silver -> Gold] + B --> C{Query Router} + C -->|Qualitative path| D[Qdrant Hybrid Search: Dense + Sparse + Metadata] + C -->|Quantitative path| E[Parquet Analytics: SQL + Pandas] + D --> F[Analyst Agent: Thesis and Trade Construction] + E --> F + F --> G[Checker Agent: Contract and Liquidity Validation] + G --> H[Critic Agent: Risk and Counter-Argument Review] + H --> I[Finalizer Agent: Structured Strategy Report] +``` ------ +--- +## 3. Operational Workflow & Multi-Agent Logic +### Workflow Orchestration (Execution Lifecycle) + +```mermaid +flowchart TD + A[Source ingestion jobs] --> B[Medallion processing
Bronze -> Silver -> Gold] + B --> C[CLI Orchestration Layer] + C --> D{User command} + + D -->|ingest| E[Run due stages with run-state idempotency] + D -->|warmup| F[Warm LLM pool models in Ollama] + D -->|query| G[LangGraph query execution] + + E --> H[Gold artifacts ready] + H --> I[Qdrant ingestion pipeline] + I --> J[Hybrid index and payload schema reconciliation] + + G --> K{Retriever router} + K -->|quant path| L[Silver SQL/Pandas retrieval] + K -->|semantic path| M[Qdrant dense+sparse retrieval] + L --> N[Analyst synthesis] + M --> N + N --> O[Checker factual validation] + O --> P[Critic risk challenge] + P --> Q[Finalizer report compiler] + Q --> R[Structured recommendation output] +``` -## 🚀 Getting Started +--- +## 4. Medallion Data Governance & Schema +Data is partitioned into three logical layers to ensure lineage and high +information density: +| Layer | Data Profile | Storage | Governance Objective | +| :--- | :--- | :--- | :--- | +| `1_Bronze_Raw` | Raw, minimally transformed captures | HTML / XML / JSONL | Traceability, replay, and source-level audits | +| `2_Silver_Processed` | Deterministic structured tables | Parquet | Accurate numeric analytics (prices, IV, macro) | +| `3_Gold_Semantic` | Retrieval-ready semantic records | JSONL / Markdown | Hybrid search relevance and citation grounding | +| `Agent_Context` | Session-level macro memory | Markdown snapshots | Shared context injection across all agent roles | -### Prerequisites +--- - * Docker and Docker Compose - * A **YouTube Data API v3 key** is required. - * API keys for **FRED**, **NewsAPI**, and the **SEC** are optional but recommended for full functionality. +## 5. Quality Assurance & Evaluation Framework (Evaluation) +The evaluation standard is designed to mirror production controls used in institutional research tooling. -### Environment Variables +### 1) Retrieval and grounding quality +- **Faithfulness (RAGAS):** verifies the report is supported by retrieved evidence. +- **Context Precision (RAGAS):** checks whether retrieved chunks are topically and temporally relevant. +- **Time-barrier compliance:** validates retrieval respects `unified_timestamp/publish_timestamp` filters. -Configure the following environment variables in the `docker-compose.prod.yml` file or a separate `.env` file: +### 2) Deterministic market validation +- **Contract existence checks:** Checker validates recommended option contracts against live `yfinance` chain data. +- **Liquidity guardrails:** enforce minimum open interest / quote sanity checks before contract inclusion. +- **Numeric drift controls:** configurable tolerances (for example, `CHECKER_NUMERIC_TOLERANCE`) to detect unstable conclusions. - * `QDRANT_HOST`: The hostname for the Qdrant container (e.g., `qdrant_vdb_prod`). - * `OLLAMA_HOST`: The URL for the Ollama container (e.g., `http://ollama_llm_prod:11434`). - * `OLLAMA_MODEL`: The default model to use (e.g., `options-expert` or `mistral:7b-instruct-q4_0`). - * `YOUTUBE_API_KEY`: Your YouTube Data API key. - * **Optional**: `FRED_API_KEY`, `NEWS_API_KEY`, `REDDIT_CLIENT_ID`, `REDDIT_CLIENT_SECRET`, `REDDIT_USER_AGENT`. +### 3) Regression and model governance +- **Golden dataset replay:** historical complex QA set for non-regression across prompt/model updates. +- **Role-level warmup validation:** ensure both expert and router model tiers are online before live querying. +- **Auditability:** centralized logs and runtime state snapshots support post-mortem investigations. -### Installation & Running the System +--- -From the root of the repository, build and launch the production services in detached mode: +## 6. Operational CLI Playbook +All examples below are production-safe with the current CLI entrypoint (`python -m Scripts`). +### A. Warmup command ```bash -docker compose -f docker-compose.prod.yml up -d --build +python -m Scripts warmup +python -m Scripts warmup --roles analyst router ``` -You can check the status of the running containers: - +### B. Data collection (orchestration pipeline) ```bash -docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" +python -m Scripts ingest +python -m Scripts ingest --only news_daily options_daily +python -m Scripts ingest --force +python -m Scripts status --json ``` ------ - -## ⚙️ Usage - -Once the containers are running, you can interact with the application using `docker exec`. - -### Run the Main Pipeline - -To execute the full data collection and analysis pipeline in a non-interactive mode: - +### C. Qdrant ingestion ```bash -docker exec -it financial_agent_app_prod python src/main.py --no-interactive +python Scripts/vector_store/ingestion.py +python Scripts/vector_store/ingestion.py --no-full-refresh +python Scripts/vector_store/ingestion.py --indexes-only ``` -### Start an Interactive Q\&A Session - -To start a session where you can ask questions based on the ingested data: - +### D. Query command ```bash -docker exec -it financial_agent_app_prod python src/main.py +python -m Scripts query "Generate a hedged options idea for AAPL this week." +python -m Scripts query --warmup "Compare GLD and SLV options risk-reward under current macro regime." ``` -### Generate the Daily Production Report - -To run the script that specifically generates the daily options ideas report: +### E. GPU node with single-terminal constraint (no extra terminal allowed) +Use a **single sequential runbook** in one shell session: ```bash -docker exec -it financial_agent_app_prod python src/tools/generate_production_report.py +python -m Scripts warmup --roles analyst router && python -m Scripts ingest && python Scripts/vector_store/ingestion.py --no-full-refresh && python -m Scripts query "What is the best risk-defined setup for QQQ this week?" ``` -This command will output `options_ideas.json` and `options_ideas.md` to a new directory at `reports/YYYY-MM-DD/`. - -### Create the Fine-tuned `options-expert` Model - -To create and validate the custom `options-expert` model within Ollama: - -```bash -docker exec -it financial_agent_app_prod python src/tools/create_options_expert.py +If you need a background scheduler without opening another terminal (PowerShell): +```powershell +$daemon = Start-Job -ScriptBlock { python -m Scripts daemon --poll-seconds 30 --warmup } +Receive-Job -Id $daemon.Id -Keep ``` ------ +--- -## 📝 Project Deliverables & Documentation +## 7. Compute Topology: CPU vs GPU Model Utilization +### CPU-heavy components +- Data ingestion scripts (FRED/SEC/News/yfinance ETL). +- Parquet processing and SQL/Pandas numeric analysis. +- Most filesystem, scheduling, and orchestration logic. -This repository fulfills the following project requirements: +### GPU-preferred components +- Ollama expert model (`options-expert-v1:latest`) for analyst/checker/critic/finalizer and query transform. +- Router model (`llama3:latest`) can run on CPU, but lower-latency routing benefits from GPU if available. - * **Full Codebase & Containerization**: The complete, containerized application is available in this private GitHub repository. - * **Model Selection Memo**: The rationale for choosing the default LLM, including comparisons and trade-offs, is documented in `model_selection_memo.md`. - * **Example Run**: An example of the system's inputs, outputs, and logs is also included in `PRODUCTION_OPS_NOTES.md`. - * **Additional Signal Sources**: A note documenting other high-signal data sources that could be integrated is available in `PRODUCTION_OPS_NOTES.md`. - * **Compliance Note**: A section covering API usage terms, scraping restrictions, and disclosure rules is detailed in `compliance_note.md`. +### Configuration controls +- `RETRIEVER_DEVICE=cpu|cuda` controls retriever-side model device preference. +- `EMBEDDING_DEVICE=cpu|cuda` controls embedding model placement. +- `OLLAMA_KEEP_ALIVE=30m` avoids repeated model eviction/cold-start. ------ +--- -## 🔧 Troubleshooting +## 8. Environment Blueprint +Use the sample at `/.env.sample` as the canonical template. Copy it to `.env` and fill secrets before running the pipeline. - * **Missing Transcripts**: If transcript fetching fails frequently, some channels may lack captions or API rate limits may have been hit. Consider widening the scan size and adding more channels to `tools/Youtube_channel_ID`. - * **`youtube_transcript_api` issues**: Ensure the library is correctly installed in the container by checking the `requirements.txt` and Docker build logs. - * **Qdrant/Ollama Health**: Check container logs for errors (`docker logs -f `). Ensure ports 6333 (Qdrant) and 11434 (Ollama) are accessible between containers and that Docker volumes are correctly mounted. - -### Common Docker Commands +--- +### 9. Implementation Prerequisites +All dependencies are consolidated into a single deployment command. The +infrastructure is fully containerized for portability. ```bash -# Stop and remove all production containers -docker compose -f docker-compose.prod.yml down - -# Force a rebuild of the application image without using cache -docker compose -f docker-compose.prod.yml build --no-cache - -# Restart the main application container -docker restart financial_agent_app_prod - -# Tail the logs of the main application container -docker logs -f financial_agent_app_prod +pip install requests pandas numpy pyarrow yfinance fredapi python-dotenv beautifulsoup4 markdownify langchain-ollama langchain-huggingface langgraph qdrant-client pydantic rich fastembed newspaper3k duckduckgo-search ``` +**Environment Requirements:** +* **Local Inference:** Ollama (running `llama3` or `mistral`). +* **Vector Store:** Qdrant Cloud or Dockerized Qdrant. +* **Credentials:** `.env` file containing `FRED_API_KEY` and `SEC_USER_AGENT`. +--- + +## 10. Supporting Technical Documentation +- Architecture deep dive: [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) +- Orchestration details: [`docs/Orchestration.md`](docs/Orchestration.md) +- Agent architecture: [`docs/agent/Agent_Architecture.md`](docs/agent/Agent_Architecture.md) +- Observability model: [`docs/Observability.md`](docs/Observability.md) +- Retrieval strategy: [`docs/Query_retrieval_docs/Retrieval_Architecture_and_Strategy.md`](docs/Query_retrieval_docs/Retrieval_Architecture_and_Strategy.md) +- Qdrant ingestion design: [`docs/Vector_store_docs/Vector_Ingestion.md`](docs/Vector_store_docs/Vector_Ingestion.md) +- Qdrant connection setup: [`docs/Vector_store_docs/Qdrant_connection.md`](docs/Vector_store_docs/Qdrant_connection.md) +- Data platform master reference: [`docs/Data_source_docs/Data_source_summary.md`](docs/Data_source_docs/Data_source_summary.md) +- Macro and market data dossier: [`docs/Data_source_docs/macro_market_data.md`](docs/Data_source_docs/macro_market_data.md) +- News ingestion dossier: [`docs/Data_source_docs/market_news_data.md`](docs/Data_source_docs/market_news_data.md) +- SEC filing dossier: [`docs/Data_source_docs/SEC_data.md`](docs/Data_source_docs/SEC_data.md) +- GPR dossier: [`docs/Data_source_docs/GPR_Index.md`](docs/Data_source_docs/GPR_Index.md) +- Time schema and cadence contract: [`docs/Data_source_docs/Time_Schema_Audit.md`](docs/Data_source_docs/Time_Schema_Audit.md) \ No newline at end of file diff --git a/Scripts/__init__.py b/Scripts/__init__.py new file mode 100644 index 0000000..220e736 --- /dev/null +++ b/Scripts/__init__.py @@ -0,0 +1,6 @@ +"""Top-level `Scripts` package. + +Explicit package marker so the project stops relying on PEP 420 implicit +namespace packages. This makes tooling (mypy, pyinstaller, wheel builds) +and test collection behave deterministically. +""" diff --git a/Scripts/__main__.py b/Scripts/__main__.py new file mode 100644 index 0000000..3323f10 --- /dev/null +++ b/Scripts/__main__.py @@ -0,0 +1,5 @@ +"""Enable ``python -m Scripts ...`` as a synonym for ``Scripts.orchestration.cli``.""" +from Scripts.orchestration.cli import main + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Scripts/agents/__init__.py b/Scripts/agents/__init__.py new file mode 100644 index 0000000..a9d716f --- /dev/null +++ b/Scripts/agents/__init__.py @@ -0,0 +1,8 @@ +"""Agents package — LangGraph nodes (Router, Analyst, Checker, Critic, Finalizer). + +Intentionally left import-empty: each agent class brings heavy LLM / LangChain +dependencies and should be imported by its leaf module path, e.g. +`from Scripts.agents.router import build_graph`. This keeps CLI / smoke tests +from paying the cost of instantiating LangChain clients just to import an +unrelated helper. +""" diff --git a/Scripts/agents/analyst.py b/Scripts/agents/analyst.py new file mode 100644 index 0000000..f87665d --- /dev/null +++ b/Scripts/agents/analyst.py @@ -0,0 +1,332 @@ +""" +Scripts/agents/analyst.py + +Analyst Agent — institutional-grade draft author for the LangGraph pipeline. + +Design pillars (aligned with the architect brief): +1. **Macro-Chain reasoning**: macro_context is injected into the system prompt + using the Macro → Meso → Micro framework so the LLM reasons about + transmission channels (e.g. GPR spike -> safe-haven flow -> GLD call demand) + rather than isolated facts. +2. **IV Regime awareness** (Silver upgrade from "recommendation" to "arbitrage + discovery"): before drafting, a deterministic helper classifies the current + implied-vol regime from silver_context. The LLM is told the regime so its + strategy recommendation is compatible (sell premium in high-IV, buy + protection in low-IV). +3. **Strict data lineage**: every numeric / factual claim must carry either + `[Silver: ]` or `[Gold: ]`. Downstream the + CheckerAgent enforces this. +4. **Revision-aware**: on every re-entry the agent sees the full append-only + feedback log from state["critic_feedback"] (both Checker + Critic senders) + and MUST address every unresolved Fatal error. +5. **Temporal decay hint**: the LLM is explicitly told to weight newer + gold_context entries (fresh record_date) more heavily than stale ones. +6. **Graceful degradation**: LLM failures surface as a stub draft that + explicitly says "INSUFFICIENT DATA" rather than a hallucinated report. +""" + +from __future__ import annotations + +import os +import logging +from pathlib import Path +from typing import Any, Dict, List, Literal, Optional + +from langchain_ollama import ChatOllama + +from Scripts.agents.prompts import get_analyst_prompt, render_revision_block + +logger = logging.getLogger(__name__) + + +class AnalystResult: + """Typed envelope for the analyst node's multi-field return. + + Using a tiny structured return instead of a raw string lets the router + plumb `iv_regime_pinned` into AgentState without awkwardly breaking + backwards-compat with the Markdown-only contract (a plain string is + still accessible via `.draft`). + """ + + __slots__ = ("draft", "iv_regime") + + def __init__(self, draft: str, iv_regime: Dict[str, Any]): + self.draft = draft + self.iv_regime = iv_regime + + +# ========================================== +# IV Regime Classifier (deterministic, no LLM) +# ========================================== +# Threshold defaults are conservative; can be tuned via env overrides without touching code. +_IV_HIGH_DEFAULT = float(os.getenv("IV_REGIME_HIGH_THRESHOLD", "0.35")) +_IV_LOW_DEFAULT = float(os.getenv("IV_REGIME_LOW_THRESHOLD", "0.18")) + + +def _infer_iv_regime( + silver_context: Dict[str, Any], + high: float = _IV_HIGH_DEFAULT, + low: float = _IV_LOW_DEFAULT, +) -> Dict[str, Any]: + """Classify the current IV regime from silver_context.values. + + Inspects the `latest_atm_iv` key written by + `Scripts/retrieval/sql_tools._handle_options_analysis`. Also surfaces + Put/Call Ratio when present because PCR drives the regime narrative. + + Returns a stable dict the LLM prompt can consume verbatim: + { + "iv_regime": "HIGH" | "LOW" | "NORMAL" | "UNKNOWN", + "atm_iv": float | None, + "pcr_volume": float | None, + "pcr_status": str | None, + "thresholds": {"high": ..., "low": ...} + } + + Note on "IV Rank": we use absolute IV thresholds here because the Silver + layer does not yet expose a historical IV distribution per symbol. The + TODO in `sql_tools.py` is to add an `iv_rank` column; once that exists + this function should switch to percentile-based ranking (see README). + """ + values = (silver_context or {}).get("values", {}) if isinstance(silver_context, dict) else {} + atm_iv = values.get("latest_atm_iv") + pcr_vol = values.get("pcr_volume") + pcr_status = values.get("pcr_status") + + if not isinstance(atm_iv, (int, float)): + regime: Literal["HIGH", "LOW", "NORMAL", "UNKNOWN"] = "UNKNOWN" + elif atm_iv >= high: + regime = "HIGH" + elif atm_iv <= low: + regime = "LOW" + else: + regime = "NORMAL" + + return { + "iv_regime": regime, + "atm_iv": atm_iv, + "pcr_volume": pcr_vol, + "pcr_status": pcr_status, + "thresholds": {"high": high, "low": low}, + } + + +# ========================================== +# Context formatters (LLM-friendly, stable layout) +# ========================================== + +def _format_silver(silver_context: Dict[str, Any]) -> str: + """Flatten the Silver Layer payload into a deterministic table. + + The layout intentionally places every quantitative value on its own + pipe-separated line so the Checker's regex-based number extraction is + robust to whitespace. + """ + if not silver_context: + return "(no silver context)" + values = silver_context.get("values") or {} + lineage = silver_context.get("lineage_anchors") or [] + if not values: + return "(silver returned no values — INSUFFICIENT DATA)" + + lines = ["| metric | value |", "|---|---|"] + for k, v in values.items(): + lines.append(f"| {k} | {v} |") + + if lineage: + lines.append("") + lines.append( + "LINEAGE ANCHORS — copy the EXACT anchor string into [Silver: ] " + "after every numeric claim that uses the corresponding metric value:" + ) + # Build a value→anchor hint so the LLM doesn't have to guess which + # anchor covers which number. We group by anchor prefix so related + # metrics (MACRO_VIX_* covers both VIX_value and VIX_change_pct) are + # shown together rather than as a flat list. + anchor_covered: Dict[str, List[str]] = {} + for lid in lineage: + # Derive the metric-key prefix: MACRO_VIX_2026-04-23 → VIX + parts = lid.split("_") + if lid.startswith("MACRO_") and len(parts) >= 3: + code = parts[1] + prefix_keys = [k2 for k2 in values if k2.startswith(code)] + elif lid.startswith("GPR_"): + prefix_keys = [k2 for k2 in values if k2.startswith("gpr")] + else: + # For options / px / iv anchors, show all keys whose prefix + # appears in the anchor name (best-effort heuristic). + anchor_stem = lid.split("_")[0] if "_" in lid else lid + prefix_keys = [k2 for k2 in values if anchor_stem.lower() in k2.lower()] + anchor_covered[lid] = prefix_keys or ["(see table above)"] + + for lid, covered_keys in anchor_covered.items(): + val_hints = ", ".join( + f"{k2}={values[k2]}" for k2 in covered_keys[:3] if k2 in values + ) + if len(covered_keys) > 3: + val_hints += f", +{len(covered_keys) - 3} more" + lines.append(f" [Silver: {lid}] covers → {val_hints}") + return "\n".join(lines) + + +def _format_gold(gold_context: List[Any]) -> str: + """Serialise RetrievedChunk objects (or plain dicts, as a fallback) into + a numbered, citation-ready list. + + Each line exposes `bronze_ref` as the citation key so the LLM can emit + `[Gold: ]` verbatim. + """ + if not gold_context: + return "(no gold context)" + + lines = [] + for i, chunk in enumerate(gold_context, 1): + # RetrievedChunk is a Pydantic model; fall back to dict for robustness. + content = getattr(chunk, "content", None) or (chunk.get("content", "") if isinstance(chunk, dict) else "") + bronze = getattr(chunk, "bronze_ref", None) or (chunk.get("bronze_ref", "UNKNOWN") if isinstance(chunk, dict) else "UNKNOWN") + src = getattr(chunk, "source_type", None) or (chunk.get("source_type", "") if isinstance(chunk, dict) else "") + meta = getattr(chunk, "metadata", None) or (chunk.get("metadata", {}) if isinstance(chunk, dict) else {}) + record_date = meta.get("record_date", "unknown") if isinstance(meta, dict) else "unknown" + ticker = meta.get("ticker", "") if isinstance(meta, dict) else "" + + # Truncate long content to keep the prompt lean — 600 chars preserves + # roughly one paragraph of SEC or news text, the reranker already + # surfaced the most relevant portion. + snippet = (content or "").replace("\n", " ").strip() + if len(snippet) > 600: + snippet = snippet[:600] + "…" + + lines.append( + f"[{i}] source={src} | ticker={ticker} | record_date={record_date} | " + f"bronze_ref={bronze}\n {snippet}" + ) + return "\n".join(lines) + + +def _load_macro_context(state_value: Optional[str]) -> str: + """Prefer the macro context already in state, else fall back to the + on-disk daily snapshot. A hard-coded fallback keeps the pipeline alive + even when the data pipeline has not yet produced a macro snapshot.""" + if state_value and state_value.strip(): + return state_value + + try: + project_root = Path(__file__).resolve().parents[2] + fp = project_root / "Data" / "Agent_Context" / "latest_macro_context.md" + if fp.exists(): + return fp.read_text(encoding="utf-8") + except Exception as e: + logger.warning(f"AnalystAgent: macro context fallback failed: {e}") + + return "Market conditions are currently stable. (fallback — no snapshot available)" + + +# ========================================== +# AnalystAgent class (router-compatible) +# ========================================== + +class AnalystAgent: + """LangGraph-compatible analyst node implementation. + + Public contract: + agent = AnalystAgent() + result = await agent.generate_report(state) # AnalystResult + draft_markdown = result.draft + iv_regime_dict = result.iv_regime + + The router in Scripts/agents/router.py wraps this and writes + `result.draft` into ``state["draft_report"]`` and (on the first pass + only) ``result.iv_regime`` into ``state["iv_regime_pinned"]``. + """ + + def __init__(self): + self.model_name = os.getenv("OLLAMA_ANALYST_MODEL", "options-expert-v1:latest") + temperature = float(os.getenv("ANALYST_TEMPERATURE", "0.1")) + self.llm = ChatOllama(model=self.model_name, temperature=temperature) + # Prompt is now sourced from the single-source-of-truth prompts module. + self.prompt = get_analyst_prompt() + + async def generate_report(self, state: Dict[str, Any]) -> AnalystResult: + """Run one analyst pass and return the draft Markdown + pinned IV regime. + + Returns + ------- + AnalystResult + ``.draft`` is the Markdown (existing contract), ``.iv_regime`` + is the dict the router writes into ``state["iv_regime_pinned"]`` + so subsequent revisions reuse the same regime instead of + recomputing it from a Silver table that may have mutated under + the Checker's rescue refresh. + + Note: `revision_count` increment is owned by the router's analyst_node, + not by this method — keeps the SoC clean and lets the route functions + rely on a single source of truth for "how many drafts have been tried". + """ + user_query = state.get("original_query", "") + macro_ctx = _load_macro_context(state.get("macro_context")) + silver_ctx = state.get("silver_context", {}) or {} + gold_ctx = state.get("gold_context", []) or [] + feedback_log = state.get("critic_feedback", []) or [] + revision_n = state.get("revision_count", 0) + + # Deterministic pre-compute: IV regime. + # IV Regime Pinning (2026-04-22, docs/test/2026-04-22/ + # router_e2e_deep_analysis.md §6.5): + # The regime MUST be stable across revisions otherwise the + # strategy recommendation flips direction mid-pipeline (Test 4 + # flipped NORMAL → LOW → NORMAL over three revisions because the + # Checker's rescue refreshed `latest_atm_iv` each time). We pin + # the regime on the very first pass and reuse it verbatim — the + # router writes it back onto AgentState.iv_regime_pinned. + pinned = state.get("iv_regime_pinned") + if isinstance(pinned, dict) and pinned.get("iv_regime"): + iv_regime = pinned + logger.info( + f"AnalystAgent: reusing pinned IV regime={iv_regime['iv_regime']} " + f"| atm_iv={iv_regime.get('atm_iv')} (revision={revision_n})" + ) + else: + iv_regime = _infer_iv_regime(silver_ctx) + logger.info( + f"AnalystAgent: pinning IV regime={iv_regime['iv_regime']} " + f"| atm_iv={iv_regime['atm_iv']} (first pass; will be reused on revisions)" + ) + + iv_regime_block = ( + f"iv_regime={iv_regime['iv_regime']} | atm_iv={iv_regime['atm_iv']} " + f"| pcr_volume={iv_regime['pcr_volume']} | pcr_status={iv_regime['pcr_status']} " + f"| thresholds={iv_regime['thresholds']}" + ) + + # Revision-aware prompting — empty on the first pass. + revision_block = render_revision_block(feedback_log) + + try: + chain = self.prompt | self.llm + logger.info( + f"AnalystAgent: invoking LLM | revision={revision_n} | " + f"iv_regime={iv_regime['iv_regime']} | gold_n={len(gold_ctx)} | " + f"silver_values_n={len(silver_ctx.get('values', {}))}" + ) + response = await chain.ainvoke({ + "original_query": user_query, + "macro_context": macro_ctx, + "iv_regime_block": iv_regime_block, + "silver_block": _format_silver(silver_ctx), + "gold_block": _format_gold(gold_ctx), + "revision_block": revision_block, + }) + draft = getattr(response, "content", str(response)).strip() + if not draft: + raise RuntimeError("LLM returned empty draft") + return AnalystResult(draft=draft, iv_regime=iv_regime) + + except Exception as e: + logger.exception(f"AnalystAgent: LLM call failed: {e}") + fallback_draft = ( + "## Analyst Draft — DEGRADED MODE\n" + "INSUFFICIENT DATA — the Analyst LLM call failed. No recommendation " + "will be produced until the model is available again.\n\n" + f"Diagnostic: {type(e).__name__}" + ) + return AnalystResult(draft=fallback_draft, iv_regime=iv_regime) diff --git a/Scripts/agents/checker.py b/Scripts/agents/checker.py new file mode 100644 index 0000000..c4056fb --- /dev/null +++ b/Scripts/agents/checker.py @@ -0,0 +1,307 @@ +""" +Scripts/agents/checker.py + +Checker Agent (Blue Team) — deterministic + LLM fact & lineage audit of the +Analyst draft, with an opt-in Silver-tool escape hatch for missing anchors. + +Design philosophy: +- The Checker is NOT a strategist. It is a silent, uncompromising data-integrity auditor. +- Robustness Upgrades: + * Tolerates LLM anchor truncation (substring matching). + * Ignores calendar years and structural constants. + * Aggressively truncates 'Strategy/Recommendation' sections before numeric audit. +""" + +from __future__ import annotations + +import os +import re +import logging +from typing import Any, Dict, List, Optional, Set + +from pydantic import BaseModel, Field +from langchain_ollama import ChatOllama + +from Scripts.agents.state import AgentFeedback +from Scripts.agents.prompts import get_checker_prompt + +logger = logging.getLogger(__name__) + +# 放宽至 3% 的容差,给 LLM 四舍五入留足空间 +_NUMERIC_REL_TOLERANCE = float(os.getenv("CHECKER_NUMERIC_TOLERANCE", "0.03")) +_MAX_REVISIONS = int(os.getenv("AGENT_MAX_REVISIONS", "3")) +_TOOL_RECOVERY_ENABLED = os.getenv("CHECKER_TOOL_RECOVERY", "1") == "1" +_COVERAGE_CHECK_ENABLED = os.getenv("CHECKER_COVERAGE_CHECK_ENABLED", "1") == "1" + +_COVERAGE_KEYS: Dict[str, str] = { + "latest_atm_iv": "ATM implied volatility", + "pcr_volume": "put/call ratio (volume)", + "gpr_index_level": "GPR geopolitical risk index", +} + +# ========================================== +# Structured LLM output +# ========================================== +class CheckerViolation(BaseModel): + severity: str = Field(description="'Fatal' for any number mismatch; 'Minor' for missing citations only") + description: str = Field(description="What was hallucinated vs what the real data says") + cited_silver_value: Optional[str] = Field(default=None, description="Ground-truth value from silver_context") + draft_value: Optional[str] = Field(default=None, description="Value claimed by the draft") + +class CheckerResult(BaseModel): + is_passed: bool = Field(description="True iff every claim is grounded AND cited") + violations: List[CheckerViolation] = Field(default_factory=list) + +# ========================================== +# Regex pass (deterministic layer 1) +# ========================================== +_NUMBER_RE = re.compile(r"(?Silver|Gold)\s*:\s*(?P[^\]]+)\]", re.IGNORECASE) + +_STRATEGY_VOCAB_RE = re.compile( + r"\b(dte|delta|strike|strikes?|days?\s+to\s+expir\w*|expir\w+|" + r"spread|otm|atm|itm|leg|wing|condor|straddle|strangle|collar|" + r"debit|credit|wide|breakeven|break-?even|payout|" + r"max\s+loss|max\s+gain|risk[- ]reward|theta|vega|gamma|rho)\b", + re.IGNORECASE, +) +_STRATEGY_WINDOW = 60 + +_COMMON_NUMERIC_WHITELIST: Set[float] = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 10.0, 25.0, 30.0, 45.0, 50.0, 100.0, 500.0} + +_SENTINEL_ANCHORS: frozenset = frozenset({ + "insufficient data", "no direct data available", "no data", "no data available", + "not applicable", "n/a", "na", "none", "unknown", "tbd", "pending", +}) + +def _is_sentinel_anchor(anchor: str) -> bool: + if not anchor: return False + return " ".join(anchor.lower().split()) in _SENTINEL_ANCHORS + +def _is_strategy_parameter(m: "re.Match[str]", text: str) -> bool: + start = max(0, m.start() - _STRATEGY_WINDOW) + end = min(len(text), m.end() + _STRATEGY_WINDOW) + return bool(_STRATEGY_VOCAB_RE.search(text[start:end])) + +def _numeric_equiv(draft_val: float, truth_val: float, rel_tol: float = _NUMERIC_REL_TOLERANCE) -> bool: + if truth_val == 0: return abs(draft_val - truth_val) < 1e-9 + if abs(draft_val - truth_val) / abs(truth_val) <= rel_tol: return True + if abs(draft_val - truth_val * 100) / abs(truth_val * 100 or 1) <= rel_tol: return True + if abs(draft_val * 100 - truth_val) / abs(truth_val) <= rel_tol: return True + return False + +def _numeric_equiv_abs(draft_val: float, truth_val: float, rel_tol: float = _NUMERIC_REL_TOLERANCE) -> bool: + return _numeric_equiv(draft_val, truth_val, rel_tol) or _numeric_equiv(abs(draft_val), abs(truth_val), rel_tol) + +def _extract_silver_numbers(silver_context: Dict[str, Any]) -> List[float]: + out: List[float] = [] + values = (silver_context or {}).get("values") or {} + for v in values.values(): + if isinstance(v, (int, float)): + out.append(float(v)) + elif isinstance(v, str): + try: out.append(float(v.replace(",", "").rstrip("%").strip())) + except ValueError: continue + return out + +def _build_source_pools(frozen: Dict[str, Any]) -> Dict[str, List[float]]: + _MACRO_PREFIXES = ("MACRO_", "VIX", "GSPC", "IXIC", "DXY", "GLD_SPOT", "SLV_SPOT", "FEDFUNDS", "CPIAUCSL", "UNRATE", "TNX", "BAML") + values = (frozen or {}).get("values") or {} + macro_nums, gpr_nums, other_nums = [], [], [] + + for k, v in values.items(): + if isinstance(v, (int, float)): fv = float(v) + elif isinstance(v, str): + try: fv = float(v.replace(",", "").rstrip("%").strip()) + except ValueError: continue + else: continue + + if any(k.startswith(p) for p in _MACRO_PREFIXES): macro_nums.append(fv) + elif k.startswith("gpr"): gpr_nums.append(fv) + else: other_nums.append(fv) + return {"macro": macro_nums, "gpr": gpr_nums, "options": other_nums} + +def _extract_fact_section(draft: str) -> str: + """🌟 架构师增强:极度强化的策略区截断,防止误杀参数""" + if not draft: return "" + stop_re = re.compile( + r"(?im)^(?:#+)?\s*(?:\d+\.?\s*)?(?:Trade Idea|Options Strategy|Recommendation|Positioning|Execution|Trade Execution)\b" + ) + m = stop_re.search(draft) + return draft[: m.start()] if m else draft + +def _check_key_metric_coverage(draft: str, silver_context: Dict[str, Any]) -> List[AgentFeedback]: + if not _COVERAGE_CHECK_ENABLED: return [] + feedbacks: List[AgentFeedback] = [] + values = (silver_context or {}).get("values") or {} + + for key, label in _COVERAGE_KEYS.items(): + sv = values.get(key) + if sv is None: continue + try: sv_float = float(sv) + except (ValueError, TypeError): continue + + draft_nums = [ + float(m.group(1).replace(",", "")) + for m in _NUMBER_RE.finditer(draft) + if m.group(1).replace(",", "").replace(".", "").lstrip("-").isdigit() or "." in m.group(1) + ] + if not any(_numeric_equiv(dn, sv_float) for dn in draft_nums): + feedbacks.append(AgentFeedback( + sender="Checker", error_type="Minor", + comment=f"[rule:COVERAGE_MISS | metric={key}] Metric '{label}' ({sv_float}) missing from draft." + )) + return feedbacks + +def _deterministic_audit(draft: str, silver_context: Dict[str, Any], gold_context: List[Any], frozen_context: Optional[Dict[str, Any]] = None) -> List[AgentFeedback]: + feedbacks: List[AgentFeedback] = [] + truth_ctx = frozen_context if frozen_context is not None else silver_context + silver_truth_numbers = _extract_silver_numbers(truth_ctx) + source_pools = _build_source_pools(truth_ctx) + + _silver_values_keys: Set[str] = set((truth_ctx or {}).get("values", {}).keys()) + known_silver_anchors = set(str(a) for a in (truth_ctx or {}).get("lineage_anchors", []) or []) | _silver_values_keys + + known_gold_refs: Set[str] = set() + for chunk in gold_context or []: + br = getattr(chunk, "bronze_ref", None) or (chunk.get("bronze_ref") if isinstance(chunk, dict) else None) + if br: known_gold_refs.add(str(br)) + + # 🌟 架构师增强:容忍 LLM 对 Citation Anchor 的截断和缩写 + for m in _CITATION_RE.finditer(draft): + kind, anchor = m.group("kind").capitalize(), m.group("anchor").strip() + if _is_sentinel_anchor(anchor): continue + + if kind == "Silver": + # Fuzzy match: "MACRO_VIX" is acceptable for "MACRO_VIX_2026-04-23" + matched = any(anchor.lower() in k.lower() or k.lower() in anchor.lower() for k in known_silver_anchors) + if not matched: + feedbacks.append(AgentFeedback( + sender="Checker", error_type="Fatal", + comment=f"[rule:UNKNOWN_SILVER_ANCHOR | anchor={anchor}] Anchor '{anchor}' not found.", + missing_lineage_id=[anchor], + )) + elif kind == "Gold": + matched = any(anchor.lower() in k.lower() or k.lower() in anchor.lower() for k in known_gold_refs) + if not matched: + feedbacks.append(AgentFeedback( + sender="Checker", error_type="Fatal", + comment=f"[rule:UNKNOWN_GOLD_REF | anchor={anchor}] Ref '{anchor}' not found.", + missing_lineage_id=[anchor], + )) + + # Number audit + fact_section = _extract_fact_section(draft) + draft_without_citations = _CITATION_RE.sub("", fact_section) + for m in _NUMBER_RE.finditer(draft_without_citations): + raw, is_pct = m.group(1), m.group(2) + try: val = float(raw.replace(",", "")) + except ValueError: continue + + # 🌟 架构师增强:免疫年份 (2020-2030) 和 常见自然数 + if abs(val) in _COMMON_NUMERIC_WHITELIST: continue + if val >= 2020 and val <= 2030 and "." not in raw: continue + + is_claim = bool(is_pct) or "." in raw or abs(val) >= 10 + if not is_claim: continue + if _is_strategy_parameter(m, draft_without_citations): continue + + if any(_numeric_equiv_abs(val, t) for t in silver_truth_numbers): continue + + all_sub = source_pools["macro"] + source_pools["gpr"] + source_pools["options"] + if any(_numeric_equiv_abs(val, t) for t in all_sub): continue + + feedbacks.append(AgentFeedback( + sender="Checker", error_type="Fatal", + comment=f"[rule:NUMERIC_MISMATCH | draft={raw}{is_pct}] Number not in Silver data." + )) + + return feedbacks + + +# ========================================== +# CheckerAgent class +# ========================================== +class CheckerAgent: + def __init__(self, silver_tool: Optional[Any] = None): + self.silver_tool = silver_tool + self.enable_rescue = _TOOL_RECOVERY_ENABLED and silver_tool is not None + self.model_name = os.getenv("OLLAMA_CHECKER_MODEL", "options-expert-v1:latest") + self.llm = ChatOllama(model=self.model_name, temperature=0.0, format="json").with_structured_output(CheckerResult) + self.prompt = get_checker_prompt() + + async def audit(self, state: Dict[str, Any]) -> Dict[str, Any]: + revision_n = state.get("revision_count", 0) + if revision_n >= _MAX_REVISIONS: + logger.warning("CheckerAgent: max revisions reached — skipping audit.") + return {"critic_feedback": [], "checker_verdict": "pass"} + + draft, silver_ctx, gold_ctx = state.get("draft_report", ""), state.get("silver_context", {}), state.get("gold_context", []) + frozen_ctx = state.get("silver_context_frozen") + macro_text = state.get("macro_context", "") + + feedbacks = _deterministic_audit(draft, silver_ctx, gold_ctx, frozen_ctx) + + truth_ctx_for_coverage = frozen_ctx if frozen_ctx is not None else silver_ctx + feedbacks.extend(_check_key_metric_coverage(draft, truth_ctx_for_coverage)) + + refreshed_silver = None + if self.enable_rescue and any(fb.error_type.lower() == "fatal" and fb.missing_lineage_id for fb in feedbacks): + refreshed_silver, feedbacks = await self._rescue_missing_anchors(feedbacks, state) + if refreshed_silver: silver_ctx = refreshed_silver + + try: + from Scripts.agents.analyst import _format_silver, _format_gold + result: CheckerResult = await (self.prompt | self.llm).ainvoke({ + "silver_block": _format_silver(silver_ctx), + "gold_block": _format_gold(gold_ctx), + "draft": draft, + "macro_context": macro_text[:2000] if macro_text else "(not available)", + }) + if not result.is_passed: + for v in result.violations: + sev = v.severity if v.severity in ("Fatal", "Minor") else "Fatal" + feedbacks.append(AgentFeedback(sender="Checker", error_type=sev, comment=f"[rule:LLM_CONSISTENCY] {v.description}", revision_index=revision_n)) + except Exception as e: + logger.warning(f"CheckerAgent: LLM audit failed: {e}") + + for fb in feedbacks: fb.revision_index = fb.revision_index or revision_n + verdict = "pass" if not feedbacks else ("fatal" if any(f.error_type.lower() == "fatal" for f in feedbacks) else "minor") + + payload = {"critic_feedback": feedbacks, "checker_verdict": verdict} + if refreshed_silver: payload["silver_context"] = refreshed_silver + return payload + + async def _rescue_missing_anchors(self, feedbacks: List[AgentFeedback], state: Dict[str, Any]) -> tuple[Optional[Dict[str, Any]], List[AgentFeedback]]: + metadata = state.get("metadata") + if not metadata: return None, feedbacks + + live_predicates = None + if serialised_preds := (state.get("time_range") or {}).get("source_predicates"): + try: + from Scripts.retrieval.time_adapter import predicates_from_serialised + live_predicates = predicates_from_serialised(serialised_preds) + except: pass + + try: refreshed = await self.silver_tool.query_parquet_by_metadata(metadata, time_predicates=live_predicates) + except Exception: return None, feedbacks + + old_silver = state.get("silver_context", {}) or {} + merged_values = {**(old_silver.get("values", {})), **(refreshed.get("values", {}))} + merged_anchors = sorted( + set(str(a) for a in old_silver.get("lineage_anchors", [])) + | set(str(a) for a in refreshed.get("lineage_anchors", [])) + ) + merged_silver = { + **{k: v for k, v in old_silver.items() if k not in ("values", "lineage_anchors")}, + **{k: v for k, v in refreshed.items() if k not in ("values", "lineage_anchors")}, + "values": merged_values, + "lineage_anchors": merged_anchors, + } + + updated = [ + AgentFeedback(sender="Checker", error_type="Minor", comment=f"(Rescued) {fb.missing_lineage_id}", missing_lineage_id=fb.missing_lineage_id, revision_index=fb.revision_index) + if fb.error_type.lower() == "fatal" and fb.missing_lineage_id and any(m in merged_anchors for m in fb.missing_lineage_id) + else fb for fb in feedbacks + ] + return merged_silver, updated \ No newline at end of file diff --git a/Scripts/agents/critic.py b/Scripts/agents/critic.py new file mode 100644 index 0000000..6829c3e --- /dev/null +++ b/Scripts/agents/critic.py @@ -0,0 +1,321 @@ +""" +Scripts/agents/critic.py + +Critic Agent (Red Team) — adversarial logic / regime / insider-signal review. + +In the new topology, the router calls `checker_node` BEFORE `critic_node`, so +this agent no longer needs to invoke the Checker internally. Critic's job is +now narrowly scoped: challenge the STRATEGY LOGIC of an already fact-checked +draft. + +Review axes (in strict priority order): + 1. IV Regime Fit — long premium in HIGH IV / short in LOW IV = Fatal. + 2. Macro Contradiction — directional bias contradicting [MACRO ENVIRONMENT]. + 3. Insider Weakness — single-exec signal being treated as conviction. + 4. Risk/Reward Balance — expensive protection where a spread would suffice. + +Deterministic backstops (no-LLM): + - If draft recommends bullish calls but the Insider Confidence Index is + BEARISH_SIGNAL (3+ execs selling) → Fatal (always raised). + - If draft recommends bearish puts but the Insider Confidence Index is + BULLISH_SIGNAL → Fatal (always raised). + +State I/O: + reads : state["draft_report"], state["silver_context"], state["gold_context"], + state["macro_context"], state["original_query"], state["revision_count"] + writes: { + "critic_feedback": List[AgentFeedback] (append-only; sender="Critic"), + "critic_verdict": "pass" | "fatal" | "minor", + } +""" + +from __future__ import annotations + +import os +import logging +from typing import Any, Dict, List, Literal + +from pydantic import BaseModel, Field +from langchain_ollama import ChatOllama + +from Scripts.agents.state import AgentFeedback +from Scripts.agents.analyst import _infer_iv_regime, _format_silver, _format_gold +from Scripts.agents.prompts import get_critic_prompt + +logger = logging.getLogger(__name__) + +_MAX_REVISIONS = int(os.getenv("AGENT_MAX_REVISIONS", "3")) +_INSIDER_SIGNAL_MIN_COUNT = int(os.getenv("INSIDER_SIGNAL_MIN_COUNT", "3")) + + +# ========================================== +# Structured LLM output +# ========================================== + +class LogicIssue(BaseModel): + severity: Literal["Fatal", "Minor"] = Field( + description=( + "Fatal: strategy MUST be rewritten (direction contradicts regime/macro/insider signal). " + "Minor: strategy is acceptable but could be polished — do NOT set is_passed=False for Minor only." + ) + ) + category: Literal[ + "iv_regime_fit", + "macro_contradiction", + "insider_signal_weakness", + "risk_reward_imbalance", + "other", + ] = Field(description="Which logic axis fails") + comment: str = Field(description="Concrete pushback with a suggested correction (≤ 40 words)") + + +class CriticResult(BaseModel): + is_passed: bool = Field( + description=( + "True iff there are NO Fatal issues. " + "Minor-only findings MUST still set is_passed=True — they go to minor_suggestions. " + "Only set is_passed=False when at least one Fatal issue exists." + ) + ) + issues: List[LogicIssue] = Field( + default_factory=list, + description=( + "Fatal-severity issues only. " + "If is_passed=True this list MUST be empty. " + "Minor-severity findings go into minor_suggestions instead." + ) + ) + minor_suggestions: List[str] = Field( + default_factory=list, + description=( + "Polish notes for the Finalizer — improvements that do NOT block approval. " + "Each entry ≤ 30 words. Examples: tighten spread width, add hedge note, adjust DTE." + ) + ) + + +# ========================================== +# Insider Confidence Index (deterministic, no LLM) +# ========================================== + +def _compute_insider_confidence(gold_context: List[Any]) -> Dict[str, Any]: + """Aggregate SEC-sourced Form-4 activity into a directional verdict. + + Single-exec transactions (tax, vesting) are noise. Signal requires + _INSIDER_SIGNAL_MIN_COUNT aligned executives. + """ + bullish = 0 + bearish = 0 + tone_scores: List[float] = [] + + for chunk in gold_context or []: + meta = getattr(chunk, "metadata", None) or (chunk.get("metadata", {}) if isinstance(chunk, dict) else {}) + src = getattr(chunk, "source_type", None) or (chunk.get("source_type", "") if isinstance(chunk, dict) else "") + if str(src).lower() != "sec": + continue + + action = str(meta.get("action_direction", "")).upper() if isinstance(meta, dict) else "" + if action == "BUY": + bullish += 1 + elif action == "SELL": + bearish += 1 + + tone = meta.get("tone_score") if isinstance(meta, dict) else None + if isinstance(tone, (int, float)): + tone_scores.append(float(tone)) + + avg_tone = sum(tone_scores) / len(tone_scores) if tone_scores else None + + if bullish >= _INSIDER_SIGNAL_MIN_COUNT and bullish > bearish: + verdict = "BULLISH_SIGNAL" + elif bearish >= _INSIDER_SIGNAL_MIN_COUNT and bearish > bullish: + verdict = "BEARISH_SIGNAL" + else: + verdict = "NOISE" + + return { + "bullish_exec_count": bullish, + "bearish_exec_count": bearish, + "avg_tone_score": avg_tone, + "verdict": verdict, + "threshold": _INSIDER_SIGNAL_MIN_COUNT, + } + + +# ========================================== +# CriticAgent class +# ========================================== + +class CriticAgent: + """Red-team logic critic. Scoped strictly to strategy — facts are the Checker's job.""" + + def __init__(self): + self.model_name = os.getenv("OLLAMA_CRITIC_MODEL", "options-expert-v1:latest") + temperature = float(os.getenv("CRITIC_TEMPERATURE", "0.0")) + self.logic_llm = ChatOllama( + model=self.model_name, + temperature=temperature, + format="json", + ).with_structured_output(CriticResult) + + self.prompt = get_critic_prompt() + + async def audit(self, state: Dict[str, Any]) -> Dict[str, Any]: + """Return the Critic node payload for LangGraph. + + Shape: + { + "critic_feedback": List[AgentFeedback], + "critic_verdict": "pass" | "fatal" | "minor", + } + """ + revision_n = state.get("revision_count", 0) + if revision_n >= _MAX_REVISIONS: + logger.warning("CriticAgent: max revisions reached — skipping audit.") + return {"critic_feedback": [], "critic_verdict": "pass"} + + draft = state.get("draft_report", "") or "" + silver_ctx = state.get("silver_context", {}) or {} + gold_ctx = state.get("gold_context", []) or [] + macro_ctx = state.get("macro_context", "") or "" + user_query = state.get("original_query", "") or "" + + # Deterministic pre-computes give the LLM an unambiguous ground truth. + iv_regime_info = _infer_iv_regime(silver_ctx) + insider_info = _compute_insider_confidence(gold_ctx) + + feedbacks: List[AgentFeedback] = [] + + # -------- Deterministic backstop 1: insider/structure contradiction -------- + lowered_draft = draft.lower() + if insider_info["verdict"] == "BEARISH_SIGNAL" and any( + kw in lowered_draft for kw in ("long call", "buy call", "bull call") + ): + feedbacks.append(AgentFeedback( + sender="Critic", + error_type="Fatal", + comment=( + f"[insider_signal_weakness] Recommended bullish call structure contradicts a " + f"BEARISH insider signal ({insider_info['bearish_exec_count']} execs selling, " + f"threshold={insider_info['threshold']}). " + "Either justify why the signal does not apply, or restructure." + ), + revision_index=revision_n, + )) + elif insider_info["verdict"] == "BULLISH_SIGNAL" and any( + kw in lowered_draft for kw in ("long put", "buy put", "bear put") + ): + feedbacks.append(AgentFeedback( + sender="Critic", + error_type="Fatal", + comment=( + f"[insider_signal_weakness] Recommended bearish put structure contradicts a " + f"BULLISH insider signal ({insider_info['bullish_exec_count']} execs buying, " + f"threshold={insider_info['threshold']})." + ), + revision_index=revision_n, + )) + + # -------- Deterministic backstop 2: IV regime contradiction -------- + # If regime is HIGH and the draft is clearly long premium, or regime + # is LOW and the draft is clearly short premium, raise a hard rule. + regime = iv_regime_info.get("iv_regime") + if regime == "HIGH" and any( + kw in lowered_draft for kw in ("long straddle", "long strangle", "buy protective", "buy insurance") + ): + feedbacks.append(AgentFeedback( + sender="Critic", + error_type="Fatal", + comment=( + f"[iv_regime_fit] HIGH IV regime (atm_iv={iv_regime_info['atm_iv']}) — long premium " + "structure is fighting the regime. Prefer credit spreads / iron condors." + ), + revision_index=revision_n, + )) + elif regime == "LOW" and any( + kw in lowered_draft for kw in ("iron condor", "credit spread", "sell premium", "short strangle") + ): + feedbacks.append(AgentFeedback( + sender="Critic", + error_type="Fatal", + comment=( + f"[iv_regime_fit] LOW IV regime (atm_iv={iv_regime_info['atm_iv']}) — selling premium " + "is under-paid for the risk. Prefer long optionality / debit spreads." + ), + revision_index=revision_n, + )) + + # -------- LLM logic critique (best-effort) -------- + # Minor suggestions are collected separately and forwarded to the Finalizer + # as polish notes — they do NOT block the draft or trigger a revision. + # Only Fatal issues set is_passed=False and go into critic_feedback. + minor_suggestions: List[str] = [] + + try: + chain = self.prompt | self.logic_llm + logger.info( + f"CriticAgent: invoking logic LLM | iv_regime={iv_regime_info['iv_regime']} " + f"| insider_verdict={insider_info['verdict']}" + ) + result: CriticResult = await chain.ainvoke({ + "original_query": user_query, + "macro_context": macro_ctx, + "iv_regime": iv_regime_info, + "insider_confidence": insider_info, + "silver_block": _format_silver(silver_ctx), + "gold_block": _format_gold(gold_ctx), + "draft": draft, + }) + + # Minor suggestions: forward to Finalizer, do NOT block. + if result.minor_suggestions: + minor_suggestions.extend(result.minor_suggestions) + logger.info( + f"CriticAgent: {len(result.minor_suggestions)} minor suggestions " + "forwarded to Finalizer (non-blocking)." + ) + + # Fatal issues only: add to critic_feedback → may trigger revision. + if not result.is_passed: + for issue in result.issues: + if issue.severity == "Fatal": + feedbacks.append(AgentFeedback( + sender="Critic", + error_type="Fatal", + comment=f"[{issue.category}] {issue.comment}", + revision_index=revision_n, + )) + else: + # LLM incorrectly placed a Minor in issues — demote to suggestion. + minor_suggestions.append(f"[{issue.category}] {issue.comment}") + logger.debug( + f"CriticAgent: Minor issue demoted from issues→suggestions: " + f"{issue.comment[:60]}" + ) + + except Exception as e: + logger.warning( + f"CriticAgent: logic LLM failed ({type(e).__name__}); " + f"deterministic findings retained. Error: {e}" + ) + + verdict = self._compute_verdict(feedbacks) + logger.info( + f"CriticAgent: verdict={verdict} | fatal={len(feedbacks)} | " + f"minor_suggestions={len(minor_suggestions)}" + ) + + return { + "critic_feedback": feedbacks, + "critic_verdict": verdict, + # Non-blocking polish notes forwarded to Finalizer via state. + "critic_minor_suggestions": minor_suggestions, + } + + @staticmethod + def _compute_verdict(feedbacks: List[AgentFeedback]) -> str: + if not feedbacks: + return "pass" + if any(fb.error_type.lower() == "fatal" for fb in feedbacks): + return "fatal" + return "minor" diff --git a/Scripts/agents/finalizer.py b/Scripts/agents/finalizer.py new file mode 100644 index 0000000..adbb8ae --- /dev/null +++ b/Scripts/agents/finalizer.py @@ -0,0 +1,515 @@ +""" +Scripts/agents/finalizer.py + +Finalizer Agent — converts the fact-checked + logic-approved Markdown draft +into the deterministic Pydantic `FinalReport` that the UI / downstream tools +consume. Preserves the original schema contract (FinalReport, TradeIdea, +SourceCitation) so any existing Streamlit/JSON consumer keeps working. + +Design pillars: +1. **Structured output, not prose** — uses ChatOllama.with_structured_output(FinalReport) + so the LLM cannot return a free-form string. If the structured parse fails, + we fall back to a safe skeleton report instead of throwing. +2. **Traceability (Audit Trail)** — populates every TradeIdea.supporting_evidence + with real lineage IDs from state["silver_context"]["lineage_anchors"] and + state["gold_context"][*].bronze_ref. This satisfies the financial-compliance + requirement called out in the original docstring. +3. **Confidence score reflects data, not vibes** — if Gold or Silver layers + returned nothing / errored, the confidence score is capped. If the + revision counter hit the hard limit, we annotate the report as "degraded". +4. **LangGraph-friendly** — `FinalizerAgent.format_and_clean(state)` returns + the dict that the router writes into `state["final_strategy"]`. +""" + +from __future__ import annotations + +import os +import logging +from datetime import datetime +from typing import Any, Dict, List, Literal, Optional + +from pydantic import BaseModel, Field +from langchain_ollama import ChatOllama + +from Scripts.agents.prompts import get_finalizer_prompt + +logger = logging.getLogger(__name__) + +# Hard revision cap — must match checker.py / critic.py / router.py. +_MAX_REVISIONS = int(os.getenv("AGENT_MAX_REVISIONS", "3")) + + +# ========================================== +# Pydantic contracts (PRESERVED — downstream UI depends on these) +# ========================================== + +class SourceCitation(BaseModel): + """RAG Traceability: Forces the LLM to cite its sources to reduce hallucination.""" + source_type: Literal["Macro Data", "SEC Filing", "Global News", "GPR Index", "Options Market Data"] = Field( + description="The category of the data source used." + ) + detail: str = Field( + description="Brief description of the source (e.g., 'SEC Form 4 for GOOG filed on 2026-04-03')" + ) + + +class TradeIdea(BaseModel): + """Structured representation of a single actionable options trade.""" + + ticker: str = Field(description="The underlying asset ticker, e.g., SPY, AAPL, GLD, SLV") + + asset_class: Literal["Equity", "Index ETF", "Commodity ETF", "Currency"] = Field( + description="Broad classification of the underlying asset." + ) + + market_outlook: Literal["Bullish", "Bearish", "Neutral", "Highly Volatile"] = Field( + description="The directional bias for this underlying asset." + ) + + option_strategy: Literal[ + "Long Call", "Long Put", "Straddle/Strangle", + "Call Spread", "Put Spread", "Iron Condor" + ] = Field( + description="The specific options strategy recommended." + ) + + strike_details: str = Field( + description="Recommended strike price(s). Use string to accommodate spreads (e.g., 'Buy 150C / Sell 155C' or '150')." + ) + + expiration_date: str = Field( + description="Recommended expiration date, formatted as YYYY-MM-DD or specific timeframe (e.g., '30-45 DTE')." + ) + + rationale: str = Field( + description="Detailed, logical explanation combining macro trends, news, or insider activity." + ) + + catalysts: List[str] = Field( + description="Upcoming events driving this trade (e.g., 'CPI release next week', 'Earnings call')." + ) + + risk_profile: Literal["Low", "Medium", "High", "Speculative"] = Field( + description="Assessed risk level of this specific trade structure." + ) + + supporting_evidence: List[SourceCitation] = Field( + default_factory=list, + description="Crucial citations from the RAG context that justify this trade idea." + ) + + +class FinalReport(BaseModel): + """The overarching schema for the LLM's final response.""" + + report_date: str = Field( + default_factory=lambda: datetime.now().strftime("%Y-%m-%d"), + description="Date of the report generation." + ) + + macro_summary: str = Field( + description="High-level synthesis of current macro environment (VIX, GPR, Broad Markets)." + ) + + trade_ideas: List[TradeIdea] = Field( + description="List of top actionable options trades based on the retrieved context." + ) + + key_risks_and_hedges: List[str] = Field( + description="Systemic risks that could invalidate these trade ideas and suggested hedges." + ) + + confidence_score: float = Field( + ge=0.0, le=1.0, + description="Overall confidence in the report's conclusions based on data alignment." + ) + + conversation_reply: str = Field( + default="", + description=( + "A 50-100 word plain-English trading recommendation in direct dialogue style. " + "No markdown, no section headers, no bullet points. " + "Write as if speaking to the trader: start with the key macro/news context in " + "one sentence, state the recommended structure and ticker in one sentence, " + "then add the main risk or caveat in one sentence. " + "Example tone: 'Given elevated geopolitical risk and NORMAL IV on NVDA, " + "a call spread with 30-45 DTE captures momentum while limiting premium outlay. " + "Watch the insider selling overhang — size conservatively.' " + "Incorporate any polish notes from the Critic if provided." + ) + ) + + def to_markdown(self) -> str: + """Converts the structured Pydantic object into a clean, readable Markdown report for UI display.""" + md_lines = [ + f"# 📊 Institutional Options Strategy Report", + f"**Generated on:** {self.report_date}", + f"**Overall Confidence Score:** {self.confidence_score * 100:.1f}%", + ] + # Quick Take — the 50-100 word conversation reply shown first for chat interfaces. + if self.conversation_reply and self.conversation_reply.strip(): + md_lines += [ + f"\n> **💬 Quick Take:** {self.conversation_reply.strip()}", + ] + md_lines += [ + f"\n## 🌍 Macro Context Summary", + f"{self.macro_summary}", + f"\n## 💡 Top Trade Ideas" + ] + + for idx, trade in enumerate(self.trade_ideas, 1): + md_lines.extend([ + f"\n### Idea {idx}: {trade.option_strategy} on {trade.ticker} ({trade.market_outlook})", + f"- **Asset Class:** {trade.asset_class}", + f"- **Target Strike(s):** {trade.strike_details}", + f"- **Expiration:** {trade.expiration_date}", + f"- **Risk Profile:** {trade.risk_profile}", + f"- **Catalysts:** {', '.join(trade.catalysts)}", + f"\n**Investment Rationale:**", + f"{trade.rationale}", + ]) + + if trade.supporting_evidence: + md_lines.append("\n**Supporting Evidence (RAG Context):**") + for evidence in trade.supporting_evidence: + md_lines.append(f" - *{evidence.source_type}:* {evidence.detail}") + + md_lines.append("\n---") # Separator between trades + + md_lines.append(f"\n## ⚠️ Systemic Risks & Hedging Considerations") + for risk in self.key_risks_and_hedges: + md_lines.append(f"- {risk}") + + return "\n".join(md_lines) + + +# ========================================== +# Helpers +# ========================================== + +def _collect_evidence_pool(state: Dict[str, Any]) -> List[SourceCitation]: + """Build a deterministic evidence pool from the retrieval state. + + The LLM is asked to draw TradeIdea citations from this pool. If the LLM + misses any, the pool is also used as a final fallback so the compliance + audit trail is never empty when data exists. + """ + pool: List[SourceCitation] = [] + + silver_ctx = state.get("silver_context", {}) or {} + for anchor in silver_ctx.get("lineage_anchors", []) or []: + anchor_s = str(anchor) + # Route Silver anchors by prefix into the closest UI category. The + # anchor prefix convention comes from sql_tools.py lineage writes + # (e.g. "PCR_AGG_SPY_2026-04-19", "MACRO_VIX_...", "GPR_202604"). + if anchor_s.startswith("GPR_"): + st: Literal["Macro Data", "SEC Filing", "Global News", "GPR Index", "Options Market Data"] = "GPR Index" + elif anchor_s.startswith("MACRO_"): + st = "Macro Data" + else: + st = "Options Market Data" + pool.append(SourceCitation(source_type=st, detail=f"Silver lineage anchor: {anchor_s}")) + + for chunk in state.get("gold_context", []) or []: + src = getattr(chunk, "source_type", None) or (chunk.get("source_type", "") if isinstance(chunk, dict) else "") + meta = getattr(chunk, "metadata", None) or (chunk.get("metadata", {}) if isinstance(chunk, dict) else {}) + br = getattr(chunk, "bronze_ref", None) or (chunk.get("bronze_ref", "UNKNOWN") if isinstance(chunk, dict) else "UNKNOWN") + record_date = meta.get("record_date", "unknown") if isinstance(meta, dict) else "unknown" + + src_l = str(src).lower() + if src_l == "sec": + ui_src: Literal["Macro Data", "SEC Filing", "Global News", "GPR Index", "Options Market Data"] = "SEC Filing" + elif src_l == "gpr": + ui_src = "GPR Index" + else: + ui_src = "Global News" + + pool.append(SourceCitation( + source_type=ui_src, + detail=f"{ui_src} @ {record_date} | ref={br}", + )) + + return pool + + +def _enforce_deterministic_report_date( + report: "FinalReport", + state: Dict[str, Any], +) -> None: + """Overwrite `report.report_date` with the pipeline-known anchor date. + + The LLM was previously hallucinating this field as a literal string + ("current date"), as the first gold-chunk's record_date, or as + "INSUFFICIENT DATA" — none of which are useful to a compliance reader. + The pipeline's authoritative anchor lives at + ``state["time_range"]["anchor_date"]`` (set by MasterRetriever from + ``config/runtime/collect_data_state.json:options_daily``). When that + is present we simply clobber the LLM's guess. When absent (e.g. the + retriever hard-failed) we leave the LLM value alone so a downstream + auditor can still see something plausible. + """ + tr = state.get("time_range") or {} + anchor = tr.get("anchor_date") + if isinstance(anchor, str) and len(anchor) == 10 and anchor[4] == "-" and anchor[7] == "-": + # basic ISO-8601 shape check — avoids writing a bogus anchor + report.report_date = anchor + + +def _reconcile_citation_source_types( + report: "FinalReport", + evidence_pool: List["SourceCitation"], +) -> None: + """Clobber LLM-invented `source_type` values against the deterministic pool. + + Scenario (§5.2 of the 2026-04-22 deep analysis): the evidence pool is + built correctly from Gold chunks (source_type=sec → "SEC Filing"), but + the LLM re-wrote them all to "Global News" when producing + `trade_ideas[].supporting_evidence`. The pool already contains the + correct mapping; we match by `detail` substring and force the canonical + `source_type` when the LLM matches a real pool item. + """ + if not evidence_pool or not report.trade_ideas: + return + + # Index the pool on two keys: exact detail and a lowercased prefix so + # minor whitespace/punctuation drift from the LLM still matches. + pool_exact: Dict[str, SourceCitation] = {p.detail: p for p in evidence_pool} + pool_prefix: List[tuple] = [ + (p.detail.lower()[:60], p) for p in evidence_pool if p.detail + ] + + for idea in report.trade_ideas: + for citation in idea.supporting_evidence: + if not citation.detail: + continue + exact = pool_exact.get(citation.detail) + if exact is not None: + if exact.source_type != citation.source_type: + citation.source_type = exact.source_type + continue + # Fuzzy prefix match — handles LLM line breaks / truncations. + key = citation.detail.lower()[:60] + for pkey, p in pool_prefix: + if key == pkey: + if p.source_type != citation.source_type: + citation.source_type = p.source_type + break + + +def _degraded_report( + reason: str, + draft: str, + evidence_pool: List[SourceCitation], + cap_confidence: float = 0.20, +) -> FinalReport: + """Safe fallback when the Finalizer LLM fails or the pipeline is degraded. + + We never throw from this node — that would strand the entire graph. + Instead we return a FinalReport that explicitly declares degradation, + carries whatever evidence we have, and sets a low confidence score. + """ + return FinalReport( + macro_summary=( + "DEGRADED MODE — finalizer could not produce a structured report. " + f"Reason: {reason}. Raw analyst draft preserved below (first 400 chars):\n\n" + f"{(draft or '')[:400]}" + ), + trade_ideas=[], + key_risks_and_hedges=[ + "Automated pipeline degradation — do not act on partial outputs.", + "Re-run the pipeline once upstream data + LLM availability is restored.", + ], + confidence_score=cap_confidence, + ) + + +# ========================================== +# FinalizerAgent class +# ========================================== + +class FinalizerAgent: + """LangGraph-compatible finalizer. Produces the terminal `final_strategy` dict. + + Optional llama3:latest enrichment pass (FINALIZER_LLAMA3_ENRICHMENT=1): + After the structured FinalReport is produced, a second lightweight LLM + call uses llama3:latest to generate an enriched_macro_narrative — a + plain-English synthesis of macro_context for the executive summary + section. This pass is best-effort and never blocks the primary output. + Enabled via env var to avoid extra GPU load in CI / cold-start scenarios. + """ + + _LLAMA3_ENRICHMENT_ENABLED = os.getenv("FINALIZER_LLAMA3_ENRICHMENT", "0") == "1" + _LLAMA3_MODEL = os.getenv("OLLAMA_FINALIZER_ENRICHMENT_MODEL", "llama3:latest") + + def __init__(self): + self.model_name = os.getenv("OLLAMA_FINALIZER_MODEL", "options-expert-v1:latest") + temperature = float(os.getenv("FINALIZER_TEMPERATURE", "0.0")) + self.llm = ChatOllama( + model=self.model_name, + temperature=temperature, + format="json", + ).with_structured_output(FinalReport) + + # Prompt comes from the single source of truth; variables expected by the + # template are: original_query, draft, evidence_block, macro_context. + self.prompt = get_finalizer_prompt() + + # Optional llama3 enrichment LLM (lazy init — only loaded when enabled). + self._llama3_llm: Optional[Any] = None + if self._LLAMA3_ENRICHMENT_ENABLED: + try: + from langchain_ollama import ChatOllama as _OllamaChat + self._llama3_llm = _OllamaChat( + model=self._LLAMA3_MODEL, + temperature=0.3, + ) + logger.info(f"FinalizerAgent: llama3 enrichment enabled (model={self._LLAMA3_MODEL})") + except Exception as e: + logger.warning(f"FinalizerAgent: llama3 enrichment init failed ({e}) — enrichment disabled.") + + async def format_and_clean(self, state: Dict[str, Any]) -> Dict[str, Any]: + """Convert the Analyst draft into a FinalReport dict. + + Returns a dict (not the Pydantic model) so it survives serialisation + at the LangGraph state boundary. Shape:: + + { + "status": "complete" | "degraded", + "final_report": , + "markdown": , + "evidence_links": [ ... SourceCitation.model_dump ... ], + "confidence_score": float, + } + """ + draft = state.get("draft_report", "") or "" + user_query = state.get("original_query", "") or "" + revision_n = state.get("revision_count", 0) + is_fallback = bool(state.get("is_fallback", False)) + evidence_pool = _collect_evidence_pool(state) + + # Critic Minor Suggestions — non-blocking polish notes forwarded from CriticAgent. + # Rendered as a concise block so the Finalizer can incorporate them into + # conversation_reply and rationale without triggering a rewrite. + minor_suggestions: List[str] = state.get("critic_minor_suggestions") or [] + minor_block = ( + "\n".join(f"- {s}" for s in minor_suggestions) + if minor_suggestions + else "(none)" + ) + + # Render evidence pool as a readable, LLM-consumable block. + evidence_block = "\n".join( + f"- [{e.source_type}] {e.detail}" for e in evidence_pool + ) or "(no evidence available — INSUFFICIENT DATA)" + + macro_ctx = state.get("macro_context") or "" + + degraded = False + degraded_reason: Optional[str] = None + + # If the pipeline already timed out at the revision cap OR the retrieval + # layer degraded, we surface it rather than pretending everything is fine. + if revision_n >= _MAX_REVISIONS: + degraded = True + degraded_reason = f"revision_cap_hit (n={revision_n})" + elif is_fallback: + degraded = True + degraded_reason = "retrieval_fallback_active" + + report: FinalReport + try: + chain = self.prompt | self.llm + logger.info( + f"FinalizerAgent: invoking LLM | revision={revision_n} | " + f"evidence_n={len(evidence_pool)} | degraded={degraded}" + ) + report = await chain.ainvoke({ + "original_query": user_query, + "draft": draft, + "evidence_block": evidence_block, + # Macro context is passed as trusted background — it was + # pre-validated by the data pipeline and is exempt from + # Checker re-verification (see checker_strictness_v2_architecture.md §2.1). + "macro_context": macro_ctx[:3000] if macro_ctx else "(not available)", + # Critic Minor Suggestions — polish notes to incorporate (non-blocking). + "minor_suggestions_block": minor_block, + }) + + # Post-hoc traceability guarantee: if the LLM produced trade ideas + # but attached zero citations, backfill from the evidence pool + # (conservative cap of 3 citations per idea). + if report.trade_ideas and evidence_pool: + for idea in report.trade_ideas: + if not idea.supporting_evidence: + idea.supporting_evidence = evidence_pool[:3] + + # Deterministic overrides — eliminate LLM drift on fields the + # pipeline already knows exactly (docs/test/2026-04-22/ + # router_e2e_deep_analysis.md §5.1, §5.2). + _enforce_deterministic_report_date(report, state) + _reconcile_citation_source_types(report, evidence_pool) + + # Enforce confidence ceilings by regime. + if degraded: + report.confidence_score = min(report.confidence_score, 0.30) + elif revision_n > 0: + report.confidence_score = min(report.confidence_score, 0.60) + + except Exception as e: + logger.exception(f"FinalizerAgent: LLM call failed: {e}") + degraded = True + degraded_reason = f"finalizer_llm_failure:{type(e).__name__}" + report = _degraded_report( + reason=degraded_reason, + draft=draft, + evidence_pool=evidence_pool, + ) + # Keep the report_date deterministic even on the degraded path. + _enforce_deterministic_report_date(report, state) + + # Optional llama3:latest enrichment pass — macro narrative synthesis. + # Produces a plain-English executive background narrative that sits + # alongside the structured FinalReport without modifying its schema. + enriched_macro_narrative: Optional[str] = None + if self._llama3_llm is not None and macro_ctx: + try: + enrichment_prompt = ( + "You are a concise financial analyst. " + "Write a 2-3 sentence plain English executive summary of the current " + "macro environment based ONLY on the provided Macro Context. " + "Do not add new information or hedging language beyond what is in the context.\n\n" + f"[MACRO CONTEXT]\n{macro_ctx[:2000]}\n\n" + f"[ANALYST MACRO SUMMARY FOR REFERENCE]\n{report.macro_summary}\n\n" + "Executive Macro Narrative:" + ) + enrichment_response = await self._llama3_llm.ainvoke(enrichment_prompt) + enriched_macro_narrative = getattr(enrichment_response, "content", str(enrichment_response)).strip() + logger.info( + f"FinalizerAgent: llama3 enrichment completed " + f"(len={len(enriched_macro_narrative)})" + ) + except Exception as e: + logger.warning(f"FinalizerAgent: llama3 enrichment failed ({type(e).__name__}: {e}) — skipped.") + + output: Dict[str, Any] = { + "status": "degraded" if degraded else "complete", + "degraded_reason": degraded_reason, + "final_report": report.model_dump(), + "markdown": report.to_markdown(), + "evidence_links": [e.model_dump() for e in evidence_pool], + "confidence_score": report.confidence_score, + } + if enriched_macro_narrative: + output["enriched_macro_narrative"] = enriched_macro_narrative + return output + + +# ========================================== +# LangGraph node wrapper — drop-in for router.py +# ========================================== + +async def finalizer_node(state: Dict[str, Any]) -> Dict[str, Any]: + """LangGraph node: writes the structured final_strategy into state.""" + agent = FinalizerAgent() + final_strategy = await agent.format_and_clean(state) + return {"final_strategy": final_strategy} diff --git a/Scripts/agents/prompts.py b/Scripts/agents/prompts.py new file mode 100644 index 0000000..3cbe0fe --- /dev/null +++ b/Scripts/agents/prompts.py @@ -0,0 +1,421 @@ +""" +Public API: + get_analyst_prompt() -> ChatPromptTemplate + get_checker_prompt() -> ChatPromptTemplate + get_critic_prompt() -> ChatPromptTemplate get_finalizer_prompt() -> ChatPromptTemplate + format_feedback_block(feedback_list: List[AgentFeedback]) -> str + render_revision_block(feedback_list: List[AgentFeedback]) -> str +""" + +from __future__ import annotations + +from typing import TYPE_CHECKING, Dict, List + +from langchain_core.prompts import ChatPromptTemplate + +if TYPE_CHECKING: # avoid runtime cycle + from Scripts.agents.state import AgentFeedback + + +# ========================================== +# 0. Role cards (foundations for each agent's system prompt) +# ========================================== + +ROLE_PROMPTS: Dict[str, str] = { + "options_strategist": ( + "You are a Senior Options Strategist at a quantitative hedge fund. " + "Your mandate is to produce a causally grounded options strategy report — " + "not a generic market commentary — by linking macro regime, asset-level " + "transmission channels, and a concrete options structure." + ), + "data_auditor": ( + "You are a ruthless Data Integrity Auditor (Blue Team) at a quantitative " + "hedge fund. You do not evaluate strategy; you verify that every number " + "and every citation in the Analyst's draft matches the provided Silver/Gold " + "context within tight numeric tolerance." + ), + "risk_officer": ( + "You are the Chief Risk Officer (Red Team). Numeric accuracy has already " + "been verified by the Blue Team. Your job is to challenge the STRATEGY " + "LOGIC: IV-regime fit, macro contradiction, insider-signal strength, " + "risk/reward balance." + ), + "finalizer": ( + "You are the Report Finalizer for a quantitative options desk. Your only " + "job is to convert an already fact-checked, logic-approved Markdown draft " + "into the deterministic FinalReport Pydantic schema. You do not change " + "the thesis or re-evaluate strategy." + ), +} + + +# ========================================== +# 1. Global guardrails (reused across agents) +# ========================================== + +DATA_LINEAGE_DIRECTIVE = """=== DATA LINEAGE & ANTI-HALLUCINATION (CRITICAL) === +1. NEVER invent a number. Every numeric / factual statement must be backed by a + context item shown in SILVER CONTEXT or GOLD CONTEXT. +2. Citation format after EVERY quantitative claim: + - Silver numeric → [Silver: ] + - Gold qualitative → [Gold: ] +3. If a claim cannot be cited, write "INSUFFICIENT DATA" for that bullet — never + fabricate. +4. Numbers in your draft MUST match the Silver values exactly to the decimal + shown. The Checker Agent will reject drift beyond 2% relative tolerance. +""" + +MACRO_CHAIN_DIRECTIVE = """=== MACRO → MESO → MICRO FRAMEWORK (mandatory) === +Structure your reasoning in three layers: + 1. MACRO — the current regime (VIX, GPR index, yield direction, dollar strength) + pulled from [MACRO ENVIRONMENT] below. + 2. MESO — the transmission channel from macro to the asset class in the query + (e.g. "GPR spike → safe-haven flow → GLD call-side IV bid"). + 3. MICRO — the concrete options expression (strike, DTE, structure) that + exploits the MESO channel AND is compatible with the IV REGIME. +If the IV regime contradicts the user's directional intuition, say so explicitly. +""" + +TEMPORAL_DECAY_DIRECTIVE = """=== TEMPORAL DECAY === +[GOLD CONTEXT] items carry a record_date. Weight items ≤ 7 days higher than +items 8–30 days old; treat anything > 30 days as background only. NEVER let a +stale headline drive a current strategy. +""" + +INSIDER_DISCIPLINE_DIRECTIVE = """=== INSIDER SIGNAL DISCIPLINE === +A single insider transaction is NOISE (tax/vesting). Only treat insider data as +a SIGNAL when 3+ aligned executives appear in the Gold context, OR tone_score +and action_direction align across multiple recent SEC items. Otherwise treat +insider data as context, not signal. +""" + +IV_REGIME_DIRECTIVE = """=== IV REGIME DISCIPLINE (non-negotiable) === +The current IV regime is computed deterministically and injected as `iv_regime_block`. +Your strategy MUST be regime-compatible: + - HIGH IV → harvest premium (credit spreads, iron condors, covered calls). + - LOW IV → buy cheap optionality (long calls, protective puts, debit spreads). + - NORMAL → direction-first; structure second. +""" + +REVISION_INJECTION_TEMPLATE = """=== REVISION NOTICE — prior draft was REJECTED === +Below is the append-only audit trail from the Checker (Blue Team) and Critic (Red Team). +You MUST address every Fatal item in this new draft. Minor items should be +addressed when it does not compromise factual accuracy. + +{feedback_block} +""" + + +# ========================================== +# 2. Analyst prompt +# ========================================== + +def get_analyst_prompt() -> ChatPromptTemplate: + """Analyst: write a draft with mandatory citations based on Macro / Gold / Silver. + + Variables the chain must supply: + original_query, macro_context, iv_regime_block, + silver_block, gold_block, revision_block (may be "") + """ + system_template = ( + f"{ROLE_PROMPTS['options_strategist']}\n\n" + f"{MACRO_CHAIN_DIRECTIVE}\n" + f"{IV_REGIME_DIRECTIVE}\n" + f"{INSIDER_DISCIPLINE_DIRECTIVE}\n" + f"{TEMPORAL_DECAY_DIRECTIVE}\n" + f"{DATA_LINEAGE_DIRECTIVE}\n" + "=== OUTPUT FORMAT ===\n" + "Produce a Markdown report with sections in this exact order:\n" + " ## 1. Macro Regime Snapshot\n" + " ## 2. Transmission Channel (Meso)\n" + " ## 3. IV Regime & Structural Choice\n" + " ## 4. Trade Idea(s) (ticker, direction, structure, strike, DTE, rationale, risk)\n" + " ## 5. Key Catalysts & Invalidation Levels\n" + ) + + human_template = ( + "=== USER QUERY ===\n{original_query}\n\n" + "=== MACRO ENVIRONMENT (latest_macro_context.md) ===\n{macro_context}\n\n" + "=== IV REGIME (deterministic pre-compute) ===\n{iv_regime_block}\n\n" + "=== SILVER CONTEXT (quantitative, source of truth for numbers) ===\n{silver_block}\n\n" + "=== GOLD CONTEXT (qualitative — SEC / news / GPR) ===\n{gold_block}\n\n" + "{revision_block}\n" + "Produce the Markdown strategy report now, obeying Macro → Meso → Micro " + "and the lineage citation rules." + ) + + return ChatPromptTemplate.from_messages([ + ("system", system_template), + ("human", human_template), + ]) + + +# ========================================== +# 3. Checker prompt (Blue Team) +# ========================================== + +def get_checker_prompt() -> ChatPromptTemplate: + """Checker: audit the factual consistency (without evaluating strategy logic). + + Consistency focus (v2, 2026-04-23): + - Rule 1-5 unchanged: Silver numeric cross-reference, citation existence, + Gold hallucination, INSUFFICIENT DATA sentinel, no strategy evaluation. + - Rule 6 (NEW): Numbers that appear in [MACRO CONTEXT] are PRE-APPROVED. + The macro_context is produced by the pipeline's own data ingestion and + is trusted without re-verification. Do NOT flag a number as Fatal merely + because it is in the Macro Context but not in Silver Context. + - Rule 7 (NEW): Check for GOLD CONTRADICTIONS — if the draft claims + something that is directly contradicted by a Gold text snippet + (e.g. draft says 'CEO bought' but Gold says 'CEO sold'), flag as Fatal. + - Rule 8 (NEW): If a key metric (atm_iv, pcr_volume, gpr_index_level) + is present in Silver but completely absent from the draft (no number AND + no INSUFFICIENT DATA), flag as Minor. + + Variables: silver_block, gold_block, draft + Pairs with Pydantic `CheckerResult` via with_structured_output. + """ + system_template = ( + f"{ROLE_PROMPTS['data_auditor']}\n\n" + "=== AUDIT RULES (v3) ===\n" + "\n" + "CRITICAL — NUMBER EXTRACTION RULE (read before applying any other rule):\n" + " When scanning the draft for numeric claims to verify, you MUST distinguish:\n" + " A. FACTUAL / STATISTICAL CLAIMS — numbers from real observed data.\n" + " Examples: 'IV is 34.02%', 'VIX at 19.20', 'open interest 633,946'.\n" + " These MUST be verified against [SILVER CONTEXT] or [MACRO CONTEXT].\n" + " B. HYPOTHETICAL STRATEGY PARAMETERS — numbers the Analyst is proposing\n" + " as trade structure inputs. They are NOT from any data source.\n" + " Examples: '260 strike', '30 DTE', '25-delta', '30-wide condor',\n" + " 'buy the 150/160 call spread', 'sell the 0.25-delta put'.\n" + " These MUST be IGNORED — do NOT flag them as mismatches.\n" + " Rule of thumb: if the number is adjacent to words like strike, DTE, delta,\n" + " expiry, call, put, spread, leg, premium, debit, credit, wide, contract,\n" + " condor, straddle, theta, gamma — it is category B. Skip it.\n" + "\n" + "1. Cross-reference FACTUAL numeric values (category A only) against [SILVER CONTEXT].\n" + " - If the draft says 'IV is 50%' but Silver shows 0.45 or 45%, Fatal.\n" + " - Percentage formats are loose (0.45 == 45%) but values must match.\n" + "2. Every factual quantitative claim (category A) MUST carry [Silver: ]\n" + " or [Gold: ]. Missing citation = Minor (unless fabricated = Fatal).\n" + " [Silver: latest_atm_iv] is a valid citation — metric key names are anchors.\n" + "3. If the draft invokes a SEC filing or news event that does NOT appear in\n" + " [GOLD CONTEXT], that is a Fatal violation (hallucinated source).\n" + "4. 'INSUFFICIENT DATA' statements are NEVER violations — they are correct.\n" + "5. You do NOT evaluate strategy or logic. ONLY factual / quantitative accuracy.\n" + "6. MACRO CONTEXT EXEMPTION: Numbers in [MACRO CONTEXT] are pre-validated.\n" + " Do NOT flag them even if absent from [SILVER CONTEXT].\n" + "7. GOLD CONTRADICTION CHECK: If the draft directly contradicts a Gold text\n" + " snippet (e.g. draft says 'CEO bought' but Gold says 'CEO sold'), Fatal.\n" + " Prefix violation with [rule:GOLD_CONTRADICTION].\n" + "8. KEY METRIC OMISSION: If Silver has atm_iv, pcr_volume, or gpr_index_level\n" + " but the draft omits both the value and any INSUFFICIENT DATA note, Minor.\n" + "\n" + "Return a CheckerResult. If is_passed=True, violations MUST be empty." + ) + + human_template = ( + "[MACRO CONTEXT (trusted background — numbers here are pre-approved, Rule 6)]\n{macro_context}\n\n" + "[SILVER CONTEXT (quantitative ground truth)]\n{silver_block}\n\n" + "[GOLD CONTEXT (qualitative — check for contradictions per Rule 7)]\n{gold_block}\n\n" + "[ANALYST DRAFT TO AUDIT]\n{draft}\n\n" + "Return a CheckerResult." + ) + + return ChatPromptTemplate.from_messages([ + ("system", system_template), + ("human", human_template), + ]) + + +# ========================================== +# 4. Critic prompt (Red Team) +# ========================================== + +def get_critic_prompt() -> ChatPromptTemplate: + """Critic: challenge the strategy logic and risk control on the basis of factual accuracy. + + Variables: original_query, macro_context, iv_regime, insider_confidence, + silver_block, gold_block, draft + Pairs with Pydantic `CriticResult` via with_structured_output. + """ + system_template = ( + f"{ROLE_PROMPTS['risk_officer']}\n\n" + "=== FATAL vs MINOR — READ BEFORE REVIEWING ===\n" + "FATAL (set is_passed=False, put in issues[]):\n" + " - Strategy direction DIRECTLY contradicts the IV regime\n" + " (e.g. recommending long premium in HIGH-IV environment).\n" + " - Strategy direction DIRECTLY contradicts confirmed macro direction\n" + " (e.g. long GLD calls while real yields are aggressively rising).\n" + " - ≥3 aligned insider executives directly contradict the recommended position.\n" + " - The draft recommends a bullish structure on a stock with a confirmed\n" + " BEARISH insider signal (or vice versa).\n" + "\n" + "MINOR (set is_passed=True, put suggestions in minor_suggestions[] ONLY):\n" + " - Risk/reward could be improved (e.g., a spread is cheaper than a naked option).\n" + " - DTE, strike, or sizing could be tighter given the catalyst timeline.\n" + " - Rhetorical overstatement ('guaranteed upside' → 'favourable risk/reward').\n" + " - A hedge or stop-loss level is missing but the overall direction is sound.\n" + " - Rounding, phrasing polish, or adding a missing catalyst mention.\n" + "\n" + "CRITICAL RULE: If you find ONLY Minor issues, you MUST set is_passed=True.\n" + " Minor issues go into minor_suggestions[], NOT into issues[].\n" + " Do NOT force a revision for Minor issues — the Finalizer handles polish.\n" + "\n" + "=== REVIEW AXES (in strict priority order) ===\n" + "1. IV Regime Fit — current iv_regime is provided deterministically:\n" + " - HIGH IV → long premium is penalised; prefer credit spreads / condors.\n" + " - LOW IV → short premium is penalised; prefer long optionality.\n" + " - NORMAL → direction-first; structure must be justified.\n" + " Direct contradiction → Fatal. Suboptimal but not contradictory → Minor.\n" + "2. Macro Contradiction — compare directional bias to [MACRO ENVIRONMENT].\n" + " Direct contradiction → Fatal. Macro headwind acknowledged → Minor note.\n" + "3. Insider Signal — `insider_confidence` gives you the deterministic verdict.\n" + " Single-exec RSU vest = NOISE, never Fatal. ≥3 aligned execs = signal.\n" + "4. Risk/Reward Balance — naked option where spread suffices → Minor only.\n" + "\n" + "=== HARD CONSTRAINTS ===\n" + "- Never challenge a numeric value — that is the Checker's job.\n" + "- Never request more data — work only with what is provided.\n" + "- Return a CriticResult with is_passed, issues (Fatal only), minor_suggestions." + ) + + human_template = ( + "[USER QUERY]\n{original_query}\n\n" + "[MACRO ENVIRONMENT]\n{macro_context}\n\n" + "[DETERMINISTIC REGIME SIGNALS]\n" + "iv_regime={iv_regime}\n" + "insider_confidence={insider_confidence}\n\n" + "[SILVER CONTEXT (already fact-checked)]\n{silver_block}\n\n" + "[GOLD CONTEXT (already fact-checked)]\n{gold_block}\n\n" + "[ANALYST DRAFT TO REVIEW]\n{draft}\n\n" + "Return a CriticResult challenging strategy/logic, not numbers." + ) + + return ChatPromptTemplate.from_messages([ + ("system", system_template), + ("human", human_template), + ]) + + +# ========================================== +# 5. Finalizer prompt +# ========================================== + +def get_finalizer_prompt() -> ChatPromptTemplate: + """Finalizer: convert the Markdown draft that has passed fact-check and logic-approval into FinalReport. + + Variables: original_query, draft, evidence_block, macro_context, + minor_suggestions_block + Pairs with Pydantic `FinalReport` via with_structured_output. + + macro_context (v2): Pre-validated pipeline output — use for macro_summary enrichment. + minor_suggestions_block (v3): Non-blocking polish notes from the Critic. + conversation_reply (v3): 50-100 word dialogue-style field for chat UI. + """ + system_template = ( + f"{ROLE_PROMPTS['finalizer']}\n\n" + "=== HARD RULES ===\n" + "1. Every TradeIdea.supporting_evidence entry MUST reference a citation that\n" + " actually appears in the draft (looks like [Silver: ] or [Gold: ])\n" + " or in the provided evidence pool. Do NOT fabricate citations.\n" + "2. If the draft says 'INSUFFICIENT DATA' for a section, reflect that literally\n" + " in the FinalReport (empty trade_ideas, low confidence_score).\n" + "3. confidence_score should reflect data completeness:\n" + " - Full Gold + Silver + no revision timeouts → up to 0.90\n" + " - Partial data / revision loop triggered → ≤ 0.60\n" + " - Degraded / insufficient → ≤ 0.30\n" + "4. Preserve all numeric values EXACTLY as shown in the draft — they have\n" + " already been fact-checked. Do not re-round.\n" + "5. catalysts must be concrete near-term events (CPI, FOMC, earnings). If\n" + " none present in context, return an empty list — never invent.\n" + "6. MACRO BACKGROUND: Use [MACRO CONTEXT] to enrich macro_summary.\n" + " Numbers from macro_context are pre-validated; quote them without Silver citation.\n" + "7. CRITIC POLISH NOTES: [CRITIC MINOR SUGGESTIONS] are non-blocking improvements\n" + " approved by the Critic. Incorporate them into conversation_reply and rationale\n" + " where they fit naturally — do not alter trade direction.\n" + "8. CONVERSATION REPLY — STRICT FORMAT:\n" + " Write conversation_reply as 50-100 words of plain English in direct dialogue\n" + " style. NO markdown, NO headers, NO bullet points.\n" + " Structure: (a) one sentence on the key macro/news backdrop,\n" + " (b) one sentence on the recommended structure and ticker,\n" + " (c) one sentence on the main risk or caveat.\n" + " Incorporate Critic polish notes naturally if provided.\n" + " Example: 'With VIX at 19 and GPR risk elevated near all-time highs, NVDA\n" + " momentum remains intact despite insider noise. A call spread expiring in\n" + " 30-45 days captures upside while limiting premium outlay. Size conservatively\n" + " — the single-exec RSU vest in Gold context is noise, not a directional signal.'\n\n" + "Return a FinalReport object." + ) + + human_template = ( + "=== USER QUERY ===\n{original_query}\n\n" + "=== MACRO CONTEXT (pre-validated background — use for macro_summary enrichment) ===\n" + "{macro_context}\n\n" + "=== ANALYST DRAFT (already fact-checked + logic-approved) ===\n{draft}\n\n" + "=== EVIDENCE POOL (use these exact IDs for supporting_evidence) ===\n{evidence_block}\n\n" + "=== CRITIC MINOR SUGGESTIONS (non-blocking polish — incorporate where natural) ===\n" + "{minor_suggestions_block}\n\n" + "Emit a FinalReport now. Copy numbers from the draft verbatim. " + "Write conversation_reply in 50-100 plain-English words." + ) + + return ChatPromptTemplate.from_messages([ + ("system", system_template), + ("human", human_template), + ]) + + +# ========================================== +# 6. Feedback rendering helpers (shared by Analyst revision + audit logs) +# ========================================== + +def format_feedback_block(feedback_list: "List[AgentFeedback]") -> str: + """Group append-only feedback by sender, keep only the most severe first. + + Empty input returns an empty string — caller should treat that as "no + pending feedback, render no revision block". + """ + if not feedback_list: + return "" + + buckets: Dict[str, List[AgentFeedback]] = {} + for fb in feedback_list: + buckets.setdefault(fb.sender, []).append(fb) + + blocks: List[str] = [] + for sender in ("Checker", "Critic"): + items = buckets.get(sender) + if not items: + continue + # Fatal first, then Minor, then the rest. + items_sorted = sorted( + items, + key=lambda f: 0 if f.error_type.lower() == "fatal" else (1 if f.error_type.lower() == "minor" else 2), + ) + blocks.append(f"--- {sender} feedback ({len(items_sorted)}) ---") + for f in items_sorted: + rev = f"rev={f.revision_index}" if f.revision_index is not None else "rev=?" + missing = f.missing_lineage_id or [] + missing_s = f" | missing_ids={missing}" if missing else "" + blocks.append(f"[{f.error_type}][{rev}] {f.comment}{missing_s}") + # Surface any other senders we didn't expect (belt-and-suspenders). + for sender, items in buckets.items(): + if sender in ("Checker", "Critic"): + continue + blocks.append(f"--- {sender} feedback ({len(items)}) ---") + for f in items: + blocks.append(f"[{f.error_type}] {f.comment}") + + return "\n".join(blocks) + + +def render_revision_block(feedback_list: "List[AgentFeedback]") -> str: + """Wrap `format_feedback_block` in the revision-injection template. + + Returns an empty string when there is no feedback (so the Analyst prompt + does not ship a "you were rejected" block on the very first pass). + """ + block = format_feedback_block(feedback_list) + if not block: + return "" + return REVISION_INJECTION_TEMPLATE.format(feedback_block=block) diff --git a/Scripts/agents/router.py b/Scripts/agents/router.py new file mode 100644 index 0000000..ab4d3b8 --- /dev/null +++ b/Scripts/agents/router.py @@ -0,0 +1,545 @@ +""" +Topology: + retrieval_master → analyst → checker → [fatal? analyst : critic] + │ + critic → [fatal? analyst : finalizer] + │ + revision_count ≥ N → finalizer (hard circuit-breaker) + + 职责: + 1. Graph orchestration: clearly define the six-step pipeline of Transform → Dual Retrieval → Analyst → Checker → Critic → Finalizer. + Transform + Dual Retrieval are merged into `master_retrieval_node` internally, + because the MasterRetriever facade has already atomically handled the intent classification + metadata extraction + Gold/Silver concurrency. + 2. Resource reuse: global singleton MasterRetriever + global singleton SilverSQLTool, avoid reloading LLM / DuckDB / Qdrant client each time the graph is entered. + 3. Macro preamble (Macro Preamble): read latest_macro_context.md into `state["macro_context"]` at the entry node, all downstream nodes share the same macro snapshot. + 4. Conditional routing: Checker and Critic have independent conditional edges, short-circuit fields `checker_verdict` / `critic_verdict` make the routing decision O(1) and do not depend on the time window inference of the append-only list. + 5. Circuit breaker: `revision_count >= AGENT_MAX_REVISIONS` hard-force entering Finalizer, + Finalizer will mark the product as `status="degraded"`. +""" + +from __future__ import annotations + +import logging +import os +import time +from datetime import date, datetime, timedelta +from pathlib import Path +from typing import Any, Dict, List + +from langgraph.graph import StateGraph, END + +from Scripts.agents.state import AgentState +from Scripts.retrieval import MasterRetriever +from Scripts.retrieval.sql_tools import SilverSQLTool +from Scripts.agents.analyst import AnalystAgent +from Scripts.agents.checker import CheckerAgent +from Scripts.agents.critic import CriticAgent +from Scripts.agents.finalizer import FinalizerAgent + +logger = logging.getLogger(__name__) + +# --- Hard circuit-breaker (shared constant across agents) --- +_MAX_REVISIONS = int(os.getenv("AGENT_MAX_REVISIONS", "3")) + + +# ========================================== +# 0a. Per-node audit log helper +# ========================================== + +def _emit_node_audit( + node: str, + revision_n: int, + t0: float, + verdict: str | None = None, + findings_n: int = 0, + key_in: Dict[str, Any] | None = None, + key_out: Dict[str, Any] | None = None, +) -> List[Dict[str, Any]]: + """Build a single node audit event and return it as a 1-element list. + + Returned as a list so it can be directly used as the `node_audit_log` + value in the router node's return dict — LangGraph merges it via the + ``operator.add`` reducer declared in AgentState. + + Schema (docs/test/2026-04-23/checker_strictness_v2_architecture.md §2.3): + node, revision_n, t_start (ISO-8601), latency_ms, verdict, + findings_n, key_state_in, key_state_out + """ + latency_ms = round((time.monotonic() - t0) * 1000, 1) + event: Dict[str, Any] = { + "node": node, + "revision_n": revision_n, + "t_start": datetime.utcnow().isoformat(timespec="milliseconds"), + "latency_ms": latency_ms, + "verdict": verdict, + "findings_n": findings_n, + "key_state_in": key_in or {}, + "key_state_out": key_out or {}, + } + logger.info( + f"📋 [AuditLog:{node}] revision={revision_n} | latency={latency_ms}ms | " + f"verdict={verdict} | findings={findings_n}" + ) + return [event] + +# --- Global singletons: loaded once per process, not per invocation --- +_MASTER_RETRIEVER = MasterRetriever() +# Share the same SilverSQLTool instance across Retriever + Checker so the +# Checker's tool-call escape hatch hits the same DuckDB connection that +# already cached the Parquet schema at startup. +_SILVER_SQL_TOOL: SilverSQLTool = _MASTER_RETRIEVER.sql_tool + +# --- Agent singletons (ChatOllama clients are expensive to construct) --- +_ANALYST_AGENT = AnalystAgent() +_CHECKER_AGENT = CheckerAgent(silver_tool=_SILVER_SQL_TOOL) +_CRITIC_AGENT = CriticAgent() +_FINALIZER_AGENT = FinalizerAgent() + + +# ========================================== +# 0. Macro preamble helper (injected into state on first pass) +# ========================================== + +def _load_macro_snapshot() -> str: + """Read Data/Agent_Context/latest_macro_context.md once at graph entry. + + Returns a safe fallback string when the snapshot file is absent so the + pipeline never crashes on first-run or in CI. The Analyst / Critic both + consume `state["macro_context"]` downstream. + """ + try: + project_root = Path(__file__).resolve().parents[2] + fp = project_root / "Data" / "Agent_Context" / "latest_macro_context.md" + if fp.exists(): + return fp.read_text(encoding="utf-8") + except Exception as e: + logger.warning(f"router: macro snapshot load failed: {e}") + return ( + "Market conditions are currently stable. (fallback — " + "latest_macro_context.md not yet produced by the macro pipeline.)" + ) + + +# ========================================== +# 1. Node: retrieval_master (Transform + Dual Retrieval + Macro preamble) +# ========================================== + +# ------------------------------------------------------------------ +# Canonical default shapes for the two audit channels. +# ----------------------------------------------------------------------------- +# These keys match the contract declared in Scripts/agents/state.py (AgentState) +# AND the per-node assertion list in Scripts/tests/test_router_e2e.py +# (_REQUIRED_TIMERANGE_KEYS / _REQUIRED_HYDE_KEYS). Hard-coding the shape here +# guarantees the Analyst can always read state["time_range"]["start_date"] +# even when MasterRetriever degraded to the _empty_payload branch. +# ----------------------------------------------------------------------------- + +def _default_time_range() -> Dict[str, Any]: + """Fallback time-range used when the retriever couldn't compute one.""" + today = date.today() + # 180-day look-back mirrors the schema default so downstream Silver queries + # still have a sensible window even in emergency mode. + return { + "time_window_label": "past_six_months", + "window_days": 180, + "anchor_date": today.isoformat(), + "start_date": (today - timedelta(days=180)).isoformat(), + "end_date": today.isoformat(), + "is_default_window_applied": True, + } + + +def _default_hyde_anticipation() -> Dict[str, Any]: + """Fallback HyDE payload — zero-capacity but schema-compliant.""" + return { + "paragraph": "", + "rerank_query": "", + "raw_candidates": [], + "whitelisted_tickers": [], + "novel_tickers": [], + "source_channel": "reference", + } + + +def _coerce_time_range(tr: Any) -> Dict[str, Any]: + """Fill in any missing required keys with defaults so downstream nodes + can safely `state["time_range"]["start_date"]` without guards. + Accepts None, a partial dict, or a full dict; always returns a full dict. + """ + base = _default_time_range() + if isinstance(tr, dict): + for k, v in tr.items(): + if v is not None: + base[k] = v + return base + + +def _coerce_hyde_anticipation(he: Any) -> Dict[str, Any]: + base = _default_hyde_anticipation() + if isinstance(he, dict): + for k, v in he.items(): + if v is not None: + base[k] = v + return base + + +async def master_retrieval_node(state: AgentState) -> Dict[str, Any]: + """Transform → Dual Retrieval → Macro Preamble, atomically. + + Writes into state: + intent, metadata, gold_context, silver_context, macro_context, + time_range, hyde_anticipation, + revision_count=0, is_fallback, checker_verdict=None, critic_verdict=None + + Contract guarantee (NEW): time_range and hyde_anticipation are ALWAYS + non-None and always carry the full set of required keys. This closes the + 2026-04-22 production bug where retrieve() returned an _empty_payload and + the Analyst then crashed on `state["time_range"]["start_date"]`. Defaults + are coerced via `_coerce_time_range` / `_coerce_hyde_anticipation` so a + partial retriever response still produces a schema-valid state delta. + """ + t0 = time.monotonic() + logger.info("🔄 [Node:retrieval_master] Entering Master Retrieval + Macro preamble...") + + retrieval_results = await _MASTER_RETRIEVER.retrieve(state["original_query"]) + is_fallback = retrieval_results.get("status") != "success" + if is_fallback: + logger.warning("⚠️ [Node:retrieval_master] Retrieval partial_failure. Activating fallback state.") + + macro_ctx = _load_macro_snapshot() + + time_range = _coerce_time_range(retrieval_results.get("time_range")) + hyde_anticipation = _coerce_hyde_anticipation(retrieval_results.get("hyde_anticipation")) + + gold_n = len(retrieval_results.get("gold_context") or []) + silver_n = len((retrieval_results.get("silver_context") or {}).get("values") or {}) + + return { + "metadata": retrieval_results.get("metadata"), + "gold_context": retrieval_results.get("gold_context", []), + "silver_context": retrieval_results.get("silver_context", {}), + # 🌟 Audit channels produced by MasterRetriever.retrieve() — now + # guaranteed non-None and fully-shaped even in degraded modes: + # - time_range : (anchor, start, end, window_days, label, + # is_default_window_applied). Analyst emits + # this in the compliance footer of every + # final report. + # - hyde_anticipation : HyDE paragraph + novel tickers. Checker + # relaxes numeric audit when silver_context + # carries `source_channel=silver_layer_via_hyde_expansion`. + "time_range": time_range, + "hyde_anticipation": hyde_anticipation, + "macro_context": macro_ctx, + "revision_count": 0, + "is_fallback": is_fallback, + # Reset verdicts on every new graph entry (safe for re-runs via checkpointer). + "checker_verdict": None, + "critic_verdict": None, + # Reset the pinned IV regime: the first Analyst pass of this new + # graph entry must recompute from the freshly-retrieved Silver, + # not inherit a regime from the previous run under a checkpointer. + "iv_regime_pinned": None, + # Per-node audit log (v2 — append-only via operator.add). + "node_audit_log": _emit_node_audit( + node="retrieval_master", + revision_n=0, + t0=t0, + verdict="fallback" if is_fallback else "success", + findings_n=0, + key_in={"query": (state.get("original_query") or "")[:80]}, + key_out={"gold_n": gold_n, "silver_n": silver_n, "is_fallback": is_fallback}, + ), + } + + +# ========================================== +# 2. Node: analyst (single place that increments revision_count) +# ========================================== + +async def analyst_node(state: AgentState) -> Dict[str, Any]: + """Produce (or re-produce) the Markdown draft. + + IMPORTANT: Analyst is the SOLE owner of `revision_count` — each time the + Analyst runs, it has produced one more draft, so we increment here. Checker + and Critic no longer touch the counter. This makes the route functions' + `revision_count >= N` circuit-breaker a clean "how many drafts have we + tried so far" semantic. + + Also pins `iv_regime_pinned` on the first pass so subsequent revisions + never see a flipped regime (was §6.5 of the 2026-04-22 deep analysis). + """ + t0 = time.monotonic() + revision_n = state.get("revision_count", 0) + logger.info(f"✍️ [Node:analyst] Drafting (revision={revision_n + 1})...") + + result = await _ANALYST_AGENT.generate_report(state) + + # Pin the IV regime on the very first draft. On re-entry the analyst has + # already read it back from state, so the pinned value round-trips + # unchanged across revisions — guaranteed strategy-direction stability. + delta: Dict[str, Any] = { + "draft_report": result.draft, + "revision_count": revision_n + 1, + "checker_verdict": None, + "critic_verdict": None, + "node_audit_log": _emit_node_audit( + node="analyst", + revision_n=revision_n + 1, + t0=t0, + verdict=None, + findings_n=0, + key_in={ + "revision_n": revision_n, + "feedback_n": len(state.get("critic_feedback") or []), + }, + key_out={ + "draft_len": len(result.draft), + "iv_regime": (result.iv_regime or {}).get("iv_regime"), + }, + ), + } + if state.get("iv_regime_pinned") is None and isinstance(result.iv_regime, dict): + delta["iv_regime_pinned"] = result.iv_regime + return delta + + +# ========================================== +# 3. Node: checker (Blue team, fact + lineage) +# ========================================== + +async def checker_node(state: AgentState) -> Dict[str, Any]: + """Deterministic regex audit + coverage check + LLM consistency audit + Silver rescue.""" + t0 = time.monotonic() + revision_n = state.get("revision_count", 0) + logger.info(f"🧐 [Node:checker] Auditing draft (revision={revision_n}) for factual + lineage accuracy...") + result = await _CHECKER_AGENT.audit(state) + # audit() returns {"critic_feedback": [...], "checker_verdict": ..., optional silver_context} + verdict = result.get("checker_verdict", "pass") + findings_n = len(result.get("critic_feedback") or []) + + # Log structured rejection reasons for Fatal findings (aids Analyst revision). + if verdict == "fatal": + fatal_comments = [ + fb.comment for fb in (result.get("critic_feedback") or []) + if fb.error_type.lower() == "fatal" + ] + for fc in fatal_comments: + logger.warning(f"🚫 [Checker:Fatal] {fc}") + + result["node_audit_log"] = _emit_node_audit( + node="checker", + revision_n=revision_n, + t0=t0, + verdict=verdict, + findings_n=findings_n, + key_in={"revision_n": revision_n, "draft_len": len(state.get("draft_report") or "")}, + key_out={"verdict": verdict, "findings_n": findings_n}, + ) + return result + + +# ========================================== +# 4. Node: critic (Red team, logic + regime + insider) +# ========================================== + +async def critic_node(state: AgentState) -> Dict[str, Any]: + """Red-team logic critique; runs only if Checker produced no Fatal findings.""" + t0 = time.monotonic() + revision_n = state.get("revision_count", 0) + logger.info(f"🛡️ [Node:critic] Challenging strategy logic / regime fit / insider signal (revision={revision_n})...") + result = await _CRITIC_AGENT.audit(state) + verdict = result.get("critic_verdict", "pass") + findings_n = len(result.get("critic_feedback") or []) + + # Log structured rejection reasons for Fatal findings. + if verdict == "fatal": + fatal_comments = [ + fb.comment for fb in (result.get("critic_feedback") or []) + if fb.error_type.lower() == "fatal" + ] + for fc in fatal_comments: + logger.warning(f"🚫 [Critic:Fatal] {fc}") + + result["node_audit_log"] = _emit_node_audit( + node="critic", + revision_n=revision_n, + t0=t0, + verdict=verdict, + findings_n=findings_n, + key_in={"revision_n": revision_n}, + key_out={"verdict": verdict, "findings_n": findings_n}, + ) + return result + + +# ========================================== +# 5. Node: finalizer (structured output) +# ========================================== + +async def finalizer_node(state: AgentState) -> Dict[str, Any]: + """Convert Markdown draft → FinalReport Pydantic dict.""" + t0 = time.monotonic() + revision_n = state.get("revision_count", 0) + logger.info("✨ [Node:finalizer] Structuring FinalReport...") + final_strategy = await _FINALIZER_AGENT.format_and_clean(state) + status = final_strategy.get("status", "unknown") + return { + "final_strategy": final_strategy, + "node_audit_log": _emit_node_audit( + node="finalizer", + revision_n=revision_n, + t0=t0, + verdict=status, + findings_n=0, + key_in={"revision_n": revision_n}, + key_out={ + "status": status, + "confidence": final_strategy.get("confidence_score"), + }, + ), + } + + +# ========================================== +# 6. Conditional edges — the routing brain +# ========================================== + +def route_after_checker(state: AgentState) -> str: + """After Checker: fatal → analyst, else → critic. Hard cap → finalizer.""" + revision_n = state.get("revision_count", 0) + if revision_n >= _MAX_REVISIONS: + # Structured: [rule:CIRCUIT_BREAK | node=checker | revision_n=N | limit=N] + logger.warning( + f"🛑 [Route:after_checker] [rule:CIRCUIT_BREAK | node=checker | " + f"revision_n={revision_n} | limit={_MAX_REVISIONS}] " + "Forcing finalizer (degraded output)." + ) + return "finalizer" + + verdict = state.get("checker_verdict") + if verdict == "fatal": + # Emit which specific findings caused the reroute so the Analyst log + # has machine-parseable rejection context adjacent to the route decision. + fatal_items = [ + fb.comment for fb in (state.get("critic_feedback") or []) + if fb.error_type.lower() == "fatal" and fb.sender == "Checker" + ] + logger.info( + f"🔄 [Route:after_checker] [rule:CHECKER_FATAL_REROUTE | revision_n={revision_n} | " + f"fatal_count={len(fatal_items)}] Routing back to Analyst. " + f"First fatal: {fatal_items[0][:120] if fatal_items else 'n/a'}" + ) + return "analyst" + + # "pass" or "minor" or None → move forward to Critic. + # Minor findings are delivered to Analyst via the append-only feedback log + # only if the Critic also pushes back; alone they do not trigger a rewrite. + logger.info( + f"✅ [Route:after_checker] verdict={verdict or 'pass'} — forwarding to Critic." + ) + return "critic" + + +def route_after_critic(state: AgentState) -> str: + """After Critic: fatal → analyst, else → finalizer. Hard cap → finalizer.""" + revision_n = state.get("revision_count", 0) + if revision_n >= _MAX_REVISIONS: + logger.warning( + f"🛑 [Route:after_critic] [rule:CIRCUIT_BREAK | node=critic | " + f"revision_n={revision_n} | limit={_MAX_REVISIONS}] " + "Forcing finalizer (degraded output)." + ) + return "finalizer" + + verdict = state.get("critic_verdict") + if verdict == "fatal": + fatal_items = [ + fb.comment for fb in (state.get("critic_feedback") or []) + if fb.error_type.lower() == "fatal" and fb.sender == "Critic" + ] + logger.info( + f"🔄 [Route:after_critic] [rule:CRITIC_FATAL_REROUTE | revision_n={revision_n} | " + f"fatal_count={len(fatal_items)}] Routing back to Analyst. " + f"First fatal: {fatal_items[0][:120] if fatal_items else 'n/a'}" + ) + return "analyst" + + logger.info( + f"✅ [Route:after_critic] verdict={verdict or 'pass'} — forwarding to Finalizer." + ) + return "finalizer" + + +# ========================================== +# 7. Graph assembly +# ========================================== + +def build_financial_rag_graph(): + """Compile the industrial-grade workflow. + + Contract consumed by `main.py` / `Scripts.Generation_Phase`: + graph = build_financial_rag_graph() + final_state = await graph.ainvoke({"original_query": user_input}) + """ + workflow = StateGraph(AgentState) + + # 1. Nodes + workflow.add_node("retrieval_master", master_retrieval_node) + workflow.add_node("analyst", analyst_node) + workflow.add_node("checker", checker_node) + workflow.add_node("critic", critic_node) + workflow.add_node("finalizer", finalizer_node) + + # 2. Linear edges + workflow.set_entry_point("retrieval_master") + workflow.add_edge("retrieval_master", "analyst") + workflow.add_edge("analyst", "checker") + + # 3. Conditional edges: Checker -> {analyst | critic | finalizer(circuit-break)} + workflow.add_conditional_edges( + "checker", + route_after_checker, + { + "analyst": "analyst", + "critic": "critic", + "finalizer": "finalizer", + }, + ) + + # 4. Conditional edges: Critic -> {analyst | finalizer} + workflow.add_conditional_edges( + "critic", + route_after_critic, + { + "analyst": "analyst", + "finalizer": "finalizer", + }, + ) + + # 5. Terminal edge + workflow.add_edge("finalizer", END) + + logger.info( + "🛠️ Financial RAG Graph compiled. Topology: retrieval_master → analyst → " + "checker → {analyst|critic|finalizer} ; critic → {analyst|finalizer}." + ) + return workflow.compile() + + +# Public alias. Generic LangGraph tutorials and the orchestration CLI +# refer to the entry point as ``build_graph``; exposing it here removes +# an entire class of cross-module naming-drift bugs (see +# docs/test/2026-04-22/ingestion_and_query_runtime_failures.md §2.5). +build_graph = build_financial_rag_graph + +__all__ = [ + "build_financial_rag_graph", + "build_graph", + "master_retrieval_node", + "analyst_node", + "checker_node", + "critic_node", + "finalizer_node", + "route_after_checker", + "route_after_critic", +] diff --git a/Scripts/agents/state.py b/Scripts/agents/state.py new file mode 100644 index 0000000..db38229 --- /dev/null +++ b/Scripts/agents/state.py @@ -0,0 +1,140 @@ +""" +Scripts/agents/state.py +Role: "Global State Protocol" for the financial multi-agent system. +Design philosophy: +1. Traceability (Traceability): force data ID to be passed through. +2. Resilience (Resilience): prevent memory loss through accumulator. +3. Determinism (Determinism): use Pydantic to constrain all intermediate products. +""" + +import operator +from typing import TypedDict, Annotated, List, Dict, Any, Optional, Literal +from pydantic import BaseModel, Field + +# ========================================== +# 1. Data lineage and source structure (Lineage) +# ========================================== + +class EvidenceLink(BaseModel): + """Evidence link anchor""" + source_id: str = Field(..., description="original data ID from Gold or Silver layer (e.g. UUID or Row_Index)") + content_summary: str = Field(..., description="the key numerical or factual summary supported by this evidence") + reliability_score: float = Field(default=1.0, description="reliability score of the data source") + +# ========================================== +# 2. Feedback object structure (solve deadlock and forgetfulness) +# ========================================== + +class AgentFeedback(BaseModel): + """Agent interaction feedback object""" + sender: str = Field(..., description="the name of the agent that sent the feedback (Checker/Critic)") + error_type: str = Field(..., description="Fatal (must be corrected) or Minor (suggestions for optimization)") + comment: str = Field(..., description="specific rejection reason or modification suggestion") + missing_lineage_id: Optional[List[str]] = Field(None, description="the missing or incorrect evidence ID") + revision_index: Optional[int] = Field( + default=None, + description="the revision index of the feedback (used for audit replay; locate the新增 in the append-only list)") + + +# ========================================== +# 3. Structured parameter extraction (solve SQL hallucination) +# ========================================== + +class QueryMetadata(BaseModel): + """ + Structured intent extracted by Transform. + For backend Python code to directly perform parameterized SQL拼接。 + """ + tickers: List[str] = Field(default_factory=list) + metrics: List[str] = Field(default_factory=list, description="IV, Skew, Vol, Insider_Flow etc.") + date_range: Dict[str, str] = Field( + default_factory=dict, + description="YYYY-MM-DD format containing start_date and end_date" + ) + logical_constraints: List[str] = Field( + default_factory=list, + description="e.g. 'only look at options above 5% OTM'" + ) + +# ========================================== +# 4. Global AgentState (core contract) +# ========================================== + +class AgentState(TypedDict): + """ + LangGraph global state: the "living dictionary" of the system. + """ + # --- 原始输入 --- + original_query: str + macro_context: str # latest macro snapshot content injected from external source + + # --- Retrieval layer data (with lineage) --- + metadata: QueryMetadata + gold_context: List[Dict[str, Any]] # Qdrant returns, must contain {'id': ..., 'text': ...} + # silver_context example: {'values': {...}, 'lineage_anchors': [...], 'source_channel': 'primary'} + silver_context: Dict[str, Any] + + # 🔒 Immutable Silver snapshot — written ONCE by retrieval_master at exit, + # never modified by rescue or revision passes. + # Checker uses this as the deterministic numeric ground truth so that + # Rescue-driven updates to `silver_context` (which are additive and used + # by the NEXT analyst revision) cannot shift the audit baseline mid-round + # and cause the IV-regime / numeric-match oscillation documented in + # docs/test/2026-04-22/router_e2e_deep_analysis.md §6.5 (Test 4). + # Structure mirrors silver_context: {values: Dict, lineage_anchors: List[str]} + silver_context_frozen: Optional[Dict[str, Any]] + + # 🌟 Time audit: Retriever uniformly computes the retrieval interval, Analyst must declare at the end + # structure: {time_window_label, window_days, anchor_date, start_date, end_date, + # is_default_window_applied} + time_range: Optional[Dict[str, Any]] + + # 🌟 HyDE semantic hedge (HE = Hypothetical Expansion) + # structure: {paragraph, rerank_query, novel_tickers, whitelisted, source_channel} + # sql_only route as LLM prior knowledge supplement; vector_only route drives Silver reverse compensation query. + hyde_anticipation: Optional[Dict[str, Any]] + + # 🌟 Pinned IV regime — computed ONCE by the Analyst on the first draft, + # reused verbatim on every revision so the strategy recommendation does + # not flip direction mid-pipeline (see docs/test/2026-04-22/ + # router_e2e_deep_analysis.md §6.5 — Test 4 flipped NORMAL→LOW→NORMAL + # across three revisions because Silver rescues refreshed atm_iv). + # Structure: {"iv_regime": str, "atm_iv": float|None, + # "pcr_volume": float|None, "pcr_status": str|None, + # "thresholds": {"high": float, "low": float}} + iv_regime_pinned: Optional[Dict[str, Any]] + + # --- Inference interaction process --- + draft_report: str + + # 🌟 Core: Append-only feedback list (solve Risk 2) + # use operator.add to implement state accumulation, Analyst always sees the "error set" + critic_feedback: Annotated[List[AgentFeedback], operator.add] + + # 📝 Critic Minor Suggestions — non-blocking polish notes for Finalizer. + # Unlike critic_feedback (Fatal → analyst revision), these are style/structure + # improvements that do NOT warrant a full rewrite. Finalizer reads them + # and incorporates where possible into conversation_reply and rationale. + # Written by critic_node each pass (NOT append-only — replaced each time). + critic_minor_suggestions: Optional[List[str]] + + # 🌟 Short-circuit decision fields: only read these two fields to decide the next jump, + # avoid time window inference of "who reported the error in the last round" in the append-only list. + # value domain: "pass" | "fatal" | "minor" | None(not yet audited) + checker_verdict: Optional[Literal["pass", "fatal", "minor"]] + critic_verdict: Optional[Literal["pass", "fatal", "minor"]] + + # --- Flow control (solve Risk 3) --- + revision_count: int # number of drafts produced by Analyst; only Analyst node is responsible for increment + is_fallback: bool # whether the fallback logic is triggered + + # --- Final product --- + # force final_strategy to contain evidence_links to implement data lineage + final_strategy: Dict[str, Any] + + # 🔍 Per-node audit trail — append-only, never reset between revisions. + # Each node wrapper in router.py appends one Dict per call: + # {"node", "revision_n", "t_start", "latency_ms", "verdict", "findings_n", + # "key_state_in", "key_state_out"} + # Enables full replay of the pipeline history from a single state dump. + node_audit_log: Annotated[List[Dict[str, Any]], operator.add] \ No newline at end of file diff --git a/Scripts/core/__init__.py b/Scripts/core/__init__.py new file mode 100644 index 0000000..7463bcd --- /dev/null +++ b/Scripts/core/__init__.py @@ -0,0 +1,103 @@ +""" +`Scripts.core` — pure primitives layer. + +Contract (enforced by convention, not code): + * zero network I/O + * zero LLM clients + * zero scraper dependencies + * safe to import from any orchestrator / agent / scraper / test + +Because this package is imported by *everything* in the project, eager +imports of heavy sub-modules (large regex tables, pandas, etc.) would +force every caller to pay that cost. Instead we expose a PEP 562 lazy +facade: `from Scripts.core import trading_calendar` loads the module +the first time it is referenced, and caches the result in this module's +globals so subsequent accesses are free. +""" +from __future__ import annotations + +from importlib import import_module +from typing import TYPE_CHECKING, Any + +__all__ = [ + # Sub-modules (lazy) + "trading_calendar", + "financial_ontology", + "financial_config", + "universe", + "prompt_templates", + "intent_router_prompt_templates", + "few_shot_config", + "few_shot_intent", + "llm_pool", + "yfinance_bootstrap", + # Re-exported primitives — the most common agent-side helpers + "is_business_day", + "previous_business_day", + "next_business_day", + "n_business_days_back", + "clamp_to_business_day", + "business_days_between", +] + +_LAZY_SUBMODULES = frozenset( + { + "trading_calendar", + "financial_ontology", + "financial_config", + "universe", + "prompt_templates", + "intent_router_prompt_templates", + "few_shot_config", + "few_shot_intent", + "llm_pool", + "yfinance_bootstrap", + } +) + +_LAZY_SYMBOLS: dict[str, tuple[str, str]] = { + "is_business_day": ("trading_calendar", "is_business_day"), + "previous_business_day": ("trading_calendar", "previous_business_day"), + "next_business_day": ("trading_calendar", "next_business_day"), + "n_business_days_back": ("trading_calendar", "n_business_days_back"), + "clamp_to_business_day": ("trading_calendar", "clamp_to_business_day"), + "business_days_between": ("trading_calendar", "business_days_between"), +} + + +def __getattr__(name: str) -> Any: # PEP 562 + if name in _LAZY_SUBMODULES: + module = import_module(f"{__name__}.{name}") + globals()[name] = module + return module + if name in _LAZY_SYMBOLS: + mod_name, attr = _LAZY_SYMBOLS[name] + obj = getattr(import_module(f"{__name__}.{mod_name}"), attr) + globals()[name] = obj + return obj + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") + + +def __dir__() -> list[str]: # Help IDEs / REPL completion + return sorted(list(globals().keys()) + list(__all__)) + + +if TYPE_CHECKING: # Static analysers only — never executed at runtime + from . import ( # noqa: F401 + financial_config, + financial_ontology, + few_shot_config, + few_shot_intent, + intent_router_prompt_templates, + prompt_templates, + trading_calendar, + universe, + ) + from .trading_calendar import ( # noqa: F401 + business_days_between, + clamp_to_business_day, + is_business_day, + n_business_days_back, + next_business_day, + previous_business_day, + ) diff --git a/Scripts/core/few_shot_config.py b/Scripts/core/few_shot_config.py new file mode 100644 index 0000000..234ea9e --- /dev/null +++ b/Scripts/core/few_shot_config.py @@ -0,0 +1,38 @@ +FEW_SHOT_EXAMPLES = [ + { + "scenario": "Macro & News (Geopolitics)", + "user_query": "How did the recent Middle East tensions affect Gold prices and volatility sentiment in news?", + "extraction": { + "logical_reasoning": "Macro Step: Middle East tensions (Geopolitics). Meso Step: Safe-haven asset flow. Micro Step: Gold (XAU/GLD). Metrics: Price & Volatility Sentiment.", + "tickers": ["GLD", "XAU"], + "source_types": ["news", "gpr"], + "event_keyword": "geopolitical_tension", + "metrics": ["Sentiment Score", "Volatility"], + "time_window": "past_month" + } + }, + { + "scenario": "SEC Insider Trading (Form 4)", + "user_query": "Show me all CEO stock offloading for NVDA in the last half year.", + "extraction": { + "logical_reasoning": "Macro Step: N/A. Meso Step: Insider activity. Micro Step: NVDA CEO. Action: SELL. Form: 4.", + "tickers": ["NVDA"], + "source_types": ["sec"], + "action_direction": "SELL", + "form_type": "4", + "time_window": "past_six_months" + } + }, + { + "scenario": "Options Chain & Volatility", + "user_query": "Is there an IV skew shift for SPY following the recent Fed meeting?", + "extraction": { + "logical_reasoning": "Macro Step: Fed Meeting (Rates). Meso Step: Options market reaction. Micro Step: SPY. Metric: IV Skew.", + "tickers": ["SPY"], + "source_types": ["options", "news"], + "event_keyword": "fed_meeting", + "metrics": ["Implied Volatility (IV)", "IV Skew"], + "time_window": "past_month" + } + } +] \ No newline at end of file diff --git a/Scripts/core/few_shot_intent.py b/Scripts/core/few_shot_intent.py new file mode 100644 index 0000000..5e98d96 --- /dev/null +++ b/Scripts/core/few_shot_intent.py @@ -0,0 +1,23 @@ +# Scripts/core/few_shot_intent.py + +INTENT_FEW_SHOT_EXAMPLES = """ +User Query: "What is the current IV Skew for AAPL?" +Path: sql_only +Reasoning: Requesting a specific quantitative metric (IV Skew) for a specific ticker. + +User Query: "How does the Fed's recent rate hike affect gold sentiment?" +Path: vector_only +Reasoning: Analytical/Qualitative question about sentiment and macro impact. + +User Query: "Did the recent spike in GPR index cause the unusual put buying in SPY last Friday?" +Path: hybrid_both +Reasoning: Linking a macro event (GPR spike - Vector) with specific market data (Put buying - SQL). + +User Query: "List all Form 4 insider buys for NVDA in the last 7 days." +Path: sql_only +Reasoning: Factual data retrieval from structured records. + +User Query: "Explain the logic behind hedging with protective puts in a high volatility environment." +Path: vector_only +Reasoning: Educational/Conceptual explanation. +""" \ No newline at end of file diff --git a/Scripts/core/financial_config.py b/Scripts/core/financial_config.py new file mode 100644 index 0000000..b8ffae3 --- /dev/null +++ b/Scripts/core/financial_config.py @@ -0,0 +1,129 @@ +""" +financial_config.py +Role: Centralized Financial Domain Knowledge & Prompt Engineering Center. +Description: This file serves as the Single Source of Truth (SSoT) for all AI agents in the RAG pipeline. + It decouples professional terminology and expert personas from execution logic. +""" + +from typing import Dict, List, Optional + +# ========================================== +# 1. PROFESSIONAL FINANCIAL TERMINOLOGY (Taxonomy) +# ========================================== +FINANCIAL_TERMS = { + "valuation": ["DCF", "PE ratio", "PB ratio", "EV/EBITDA", "NPV", "IRR", "WACC", "F-Score"], + "risk_management": ["VaR (Value at Risk)", "Beta", "Volatility Skew", "Sharpe Ratio", "Sortino", "Max Drawdown", "Hedging"], + "market_analysis": ["Technical Analysis", "Fundamental Analysis", "Sentiment Analysis", "Liquidity", "Order Flow"], + "derivatives": ["Options", "Futures", "Swaps", "Greeks (Delta, Gamma, Theta, Vega)", "Implied Volatility (IV)", "IV Rank"], + "fixed_income": ["Yield Curve", "Duration", "Convexity", "Credit Spread", "Default Risk", "OAS"], + "macro_economics": ["Inflation (CPI/PCE)", "Interest Rates (Fed Funds)", "GDP", "Unemployment", "GPR (Geopolitical Risk)"] +} + +# ========================================== +# 2. ANALYSIS FRAMEWORKS (The Logic Chains) +# ========================================== +ANALYSIS_FRAMEWORKS = { + "investment_analysis": """ + ### FRAMEWORK: FUNDAMENTAL INVESTMENT ANALYSIS + 1. Quantitative: Financial statements, Profitability ratios, Debt levels. + 2. Qualitative: Moat analysis, Management quality, Industry tailwinds. + 3. Valuation: Comparative analysis vs DCF intrinsic value. + """, + + "options_expert_logic": """ + ### FRAMEWORK: SYSTEMATIC OPTIONS TRADING + 1. Volatility Regime: Current IV vs Historical Volatility. Check IV Rank/Percentile. + 2. Greek Exposure: Evaluate Delta for direction, Vega for vol-sensitivity, Theta for time decay. + 3. Strategy Selection: + - High IV: Credit Spreads, Iron Condors (Short Vol). + - Low IV: Long Straddles, Debit Spreads (Long Vol). + """, + + "macro_geopolitics": """ + ### FRAMEWORK: MACRO-DRIVEN ASSET ALLOCATION + 1. GPR Impact: Track Geopolitical Risk Index for safe-haven flows (Gold/Silver). + 2. Yield Correlation: 10Y Treasury Yields vs DXY vs Precious Metals. + 3. Central Bank Pivot: Rate hike/cut expectations and terminal rate projections. + """ +} + +# ========================================== +# 3. EXPERT PERSONAS (System Messages) +# ========================================== +ROLE_PROMPTS = { + "options_strategist": """ + You are a Senior Options Strategist with 25+ years of experience in market-neutral strategies. + Expertise: Mastery of the Greeks, volatility arbitrage, and tail-risk hedging. + Tone: Precise, professional, data-centric, and risk-averse. + Goal: Identify high-probability option setups with favorable risk-to-reward ratios. + """, + + "macro_analyst": """ + You are a Global Macro Researcher specializing in the interaction between GPR and Commodities. + Expertise: Cross-asset correlation, Fed policy interpretation, and precious metals. + Tone: Analytical, forward-looking, and focused on regime shifts. + """ +} + +# ========================================== +# 4. OUTPUT SPECIFICATIONS (Standardization) +# ========================================== +OUTPUT_CONSTRAINTS = { + "markdown_report": """ + Your response must be formatted as a structured Markdown report: + # [Asset/Strategy Name] Analysis + ## Executive Summary + - Confidence Level: [0-100%] + - Primary Driver: [Macro/Technical/Earnings] + ## Quantitative Evidence + [List specific data points like IV Rank or Price levels] + ## Proposed Strategy + - Setup: [e.g., Bull Put Spread] + - Rationale: [Max 2 sentences] + """, + + "json_schema": { + "ticker": "string", + "direction": "Bullish/Bearish/Neutral", + "iv_status": "High/Low/Neutral", + "confidence": "float" + } +} + +# ========================================== +# 5. DYNAMIC CONTEXT HELPER +# ========================================== +def get_financial_context(query: str) -> str: + """ + Dynamically retrieves relevant frameworks based on query keywords. + Ensures the LLM is anchored with the correct domain knowledge. + """ + query_lc = query.lower() + context = [] + + if any(k in query_lc for k in ["option", "greek", "iv", "volatility", "spread"]): + context.append(ANALYSIS_FRAMEWORKS["options_expert_logic"]) + + if any(k in query_lc for k in ["gold", "silver", "gpr", "geopolitic", "fed", "macro"]): + context.append(ANALYSIS_FRAMEWORKS["macro_geopolitics"]) + + if not context: + context.append(ANALYSIS_FRAMEWORKS["investment_analysis"]) + + return "\n\n".join(context) + +def build_modelfile_system_prompt() -> str: + """ + Specifically for 'create_options_expert.py'. + Combines the best of all worlds into a single System Prompt for the Modelfile. + """ + return f""" + {ROLE_PROMPTS['options_strategist']} + + [ANALYSIS STANDARDS]: + {ANALYSIS_FRAMEWORKS['options_expert_logic']} + {ANALYSIS_FRAMEWORKS['macro_geopolitics']} + + [OUTPUT REQUIREMENTS]: + {OUTPUT_CONSTRAINTS['markdown_report']} + """.strip() \ No newline at end of file diff --git a/Scripts/core/financial_ontology.py b/Scripts/core/financial_ontology.py new file mode 100644 index 0000000..f5142f0 --- /dev/null +++ b/Scripts/core/financial_ontology.py @@ -0,0 +1,448 @@ +""" +Scripts/core/financial_ontology.py +Financial Ontology Mapping Table. + +Single source of truth that bridges LLM business intents and the physical +data architecture. Every mapping below has been **audited against the actual +parquet schemas on disk** (verified 2026-04-22 via DuckDB DESCRIBE): + + - Options : Data/2_Silver_Processed/Options_Market_Data/*/*.parquet + (18 columns, see DATASET_PHYSICAL_SCHEMA['options']) + - Macro : Data/2_Silver_Processed/Macro_History/*/*.parquet + (11 columns, see DATASET_PHYSICAL_SCHEMA['macro']) + - GPR : Data/2_Silver_Processed/GPR_index/*.parquet + (120 columns — raw Caldara–Iacoviello release plus enrichments) + - SEC : Qdrant payload (no Silver parquet); key fields: + ticker, form_type, action_direction, tone_score, transaction_date + +Rules of engagement +------------------- +1. METRIC_TO_COLUMN_MAPPING MUST only reference columns that actually exist + in one of the physical datasets listed in DATASET_PHYSICAL_SCHEMA. This + file is the contract; drift is a bug. +2. DERIVED metrics (Put/Call Ratio, IV Skew) map to the *source* columns + needed to compute them — never to a pre-materialised column that does + not exist on disk. +3. UNAVAILABLE metrics (no physical columns yet ingested, e.g. Greeks, + 13F institutional flows, yield spreads) are kept in ALLOWED_METRICS so + the LLM can still surface user intent, but map to [] so downstream SQL + dispatchers fail LOUD instead of hallucinating. +4. Keys in METRIC_TO_COLUMN_MAPPING MUST stay in sync with the dispatcher + in Scripts/retrieval/sql_tools.py. When you add a new metric here, + register a handler there. +""" + +from typing import List, Dict, Set + +# --------------------------------------------------------------------------- +# 0. PHYSICAL SCHEMA CONTRACT (authoritative, auto-verifiable) +# --------------------------------------------------------------------------- +# This dict is what Scripts/retrieval/sql_tools.py::_validate_parquet_contract +# should consume. Every column in METRIC_TO_COLUMN_MAPPING below must appear +# in at least one dataset here. +DATASET_PHYSICAL_SCHEMA: Dict[str, Set[str]] = { + "options": { + "snapshot_date", "symbol", "underlying_price", "contract_symbol", + "option_type", "strike", "expiration", "dte", "moneyness_pct", + "last_price", "bid", "ask", "spread_pct", + "volume", "open_interest", "implied_volatility", + "in_the_money", "is_liquid", + }, + "macro": { + "retrieval_date", "observation_date", "symbol", "name", + "asset_class", "value", "unit", "frequency", + "daily_change_pct", "mom_change_pct", "yoy_change_pct", + }, + "gpr": { + # Enriched fields written by our GPR pipeline. + "month", "date", "gpr_percentile", "gpr_mom_pct", "gpr_yoy_pct", "gpr_3m_ma", + # Headline + family aggregates from the Caldara–Iacoviello release. + "gpr", "gprt", "gpra", "gprh", "gprht", "gprha", + "share_gpr", "share_gprh", "n10", "n3h", + # Variant constructions retained for robustness checks. + "gpr_noew", "gpr_and", "gpr_basic", + "gprh_noew", "gprh_and", "gprh_basic", + # Country-level headline & historical indexes (subset — full list + # via `pragma table_info` on the parquet; we whitelist the majors). + "gprc_usa", "gprc_chn", "gprc_rus", "gprc_ukr", "gprc_isr", + "gprc_sau", "gprc_ira", "gprc_kor", "gprc_jpn", "gprc_deu", + "gprc_gbr", "gprc_fra", "gprc_ind", + "gprhc_usa", "gprhc_chn", "gprhc_rus", "gprhc_ukr", "gprhc_isr", + # Topic-share distribution. + "shareh_cat_1", "shareh_cat_2", "shareh_cat_3", "shareh_cat_4", + "shareh_cat_5", "shareh_cat_6", "shareh_cat_7", "shareh_cat_8", + "var_name", "var_label", + }, + # SEC insider activity lives exclusively in Qdrant (no Silver parquet). + # Exposed here so the LLM can still emit SEC-oriented metrics and the + # Gold retriever can match against the real payload fields. + "sec_qdrant_payload": { + "ticker", "form_type", "filed_at", "accession_no", + "transaction_date", "action_direction", "tone_score", "url", + }, + # News docs in Qdrant do NOT carry a ticker field today (see Ingestion + # backlog); they carry topic/entities/impacted_assets. Listed for + # completeness and to drive future ingestion enrichment. + "news_qdrant_payload": { + "topic", "title", "publish_date", "publish_timestamp", "source", + "url", "entities", "impacted_assets", "volatility_implication", + "llm_tone_score", + }, +} + +# --------------------------------------------------------------------------- +# 1. Gold-layer source-type whitelist (Qdrant payload `source_type`) +# --------------------------------------------------------------------------- +ALLOWED_SOURCES: List[str] = ["sec", "news", "gpr"] + +SOURCE_ALIAS_TO_ALLOWED_SOURCE: Dict[str, str] = { + "sec_insider_trades": "sec", + "sec_parsed_json": "sec", + "news_qdrant": "news", + "news_scrapes": "news", + "macro_narratives": "news", + "macro_history": "news", + "gpr_index": "gpr", +} + +# --------------------------------------------------------------------------- +# 2. Business-intent categories surfaced to the LLM +# --------------------------------------------------------------------------- +ALLOWED_CATEGORIES: List[str] = [ + "precious_metals_spot", "macro_inflation_employment", + "macro_central_banks", "macro_yields_dollar", "metals_derivatives", + "equities_spot", "equities_derivatives", "corporate_actions", + "macro_geopolitics_risk", "macro_growth_activity", "macro_liquidity_credit", + "commodities_energy", "commodities_agriculture", + "fx_dollar_rates", "rates_curve_real_yields", + "risk_sentiment_volatility", "earnings_guidance", +] + +# --------------------------------------------------------------------------- +# 3. Metric whitelist exposed to the Extractor LLM +# --------------------------------------------------------------------------- +# These are the *only* labels the LLM may emit under `metrics`. New metrics +# added here MUST also appear in METRIC_TO_COLUMN_MAPPING below AND in the +# dispatcher in sql_tools.py. +ALLOWED_METRICS: List[str] = [ + # ── Options-oriented ────────────────────────────────────────── + "Implied Volatility (IV)", + "IV Skew", + "Put/Call Ratio", + "Open Interest", + "Options Volume", + "Options Liquidity", + "Moneyness / OTM", + "Time Decay / DTE", + "Options Pricing / Spread", + "Underlying Price", + "Greeks (Delta/Gamma)", # Reserved — not yet in Silver schema. + + # ── Macro / price action ────────────────────────────────────── + "Price", + "Price Change (%)", + "Daily Change (%)", + "Monthly Change (%)", + "Yearly Change (%)", + "Macro Trend", + "Yield Spread", # Reserved — requires additional ingestion. + + # ── Geopolitics (GPR) ───────────────────────────────────────── + "GPR Index", + "GPR Threats", + "GPR Acts", + "GPR Components", + "GPR Country-level", + + # ── SEC / Insider (Qdrant-only, no Silver parquet) ──────────── + "Insider Trading", + "Institutional Flows", # Reserved — 13F / block-trade data not yet ingested. +] + +# --------------------------------------------------------------------------- +# 4. Metric → physical column mapping (single source of truth) +# --------------------------------------------------------------------------- +# Conventions: +# - Empty list `[]` => metric is allowed but has NO physical columns yet; +# downstream dispatcher MUST surface this as +# UNAUTHORIZED / UNAVAILABLE rather than silently drop. +# - Composite lists => the metric is DERIVED; SQL handler must aggregate +# these source columns (e.g. PCR from option_type+volume). +# - Every non-empty list is audited against DATASET_PHYSICAL_SCHEMA above. +METRIC_TO_COLUMN_MAPPING: Dict[str, List[str]] = { + # ── OPTIONS (dataset=options) ───────────────────────────────── + "Implied Volatility (IV)": ["implied_volatility"], + + # DERIVED: IV Skew = f(IV across strikes grouped by moneyness & option_type). + # No pre-materialised iv_skew column — handler must compute call-25Δ minus + # put-25Δ (or the chosen convention) from these source fields. + "IV Skew": ["implied_volatility", "moneyness_pct", "option_type", "strike"], + + # DERIVED: PCR = SUM(put.volume) / SUM(call.volume), same for open_interest. + # Handler: Scripts/retrieval/sql_tools.py::_handle_put_call_ratio. + "Put/Call Ratio": ["option_type", "volume", "open_interest"], + + "Open Interest": ["open_interest"], + "Options Volume": ["volume"], + "Options Liquidity": ["is_liquid", "volume", "open_interest", "spread_pct"], + "Moneyness / OTM": ["moneyness_pct", "in_the_money", "strike", "underlying_price"], + "Time Decay / DTE": ["dte", "expiration"], + "Options Pricing / Spread": ["last_price", "bid", "ask", "spread_pct"], + "Underlying Price": ["underlying_price"], + + # Reserved: Greeks are NOT ingested into Silver. Listed as empty so the + # ontology is honest and the SQL dispatcher will flag UNAUTHORIZED instead + # of pointing at a phantom "delta_gamma_exposure" column. + "Greeks (Delta/Gamma)": [], + + # ── MACRO (dataset=macro) ───────────────────────────────────── + # Note: macro.value and options.underlying_price are both valid "price" + # sources depending on which dataset the symbol belongs to. The handler + # dispatches by symbol class (macro index vs. options underlying). + "Price": ["value", "underlying_price"], + "Price Change (%)": ["daily_change_pct", "mom_change_pct", "yoy_change_pct"], + "Daily Change (%)": ["daily_change_pct"], + "Monthly Change (%)": ["mom_change_pct"], + "Yearly Change (%)": ["yoy_change_pct"], + "Macro Trend": ["value", "daily_change_pct", "mom_change_pct", "yoy_change_pct"], + + # Reserved: no yield-spread column in current macro parquet; would need + # paired rate series (e.g. DGS10 vs DGS2) to compute at query time. + "Yield Spread": [], + + # ── GPR (dataset=gpr) ───────────────────────────────────────── + "GPR Index": ["gpr", "gpr_percentile", "gpr_mom_pct", "gpr_yoy_pct", "gpr_3m_ma"], + "GPR Threats": ["gprt", "gprht"], + "GPR Acts": ["gpra", "gprha"], + "GPR Components": ["gpr_basic", "gpr_and", "gpr_noew", + "gprh_basic", "gprh_and", "gprh_noew"], + "GPR Country-level": ["gprc_usa", "gprc_chn", "gprc_rus", "gprc_ukr", + "gprc_isr", "gprc_sau", "gprc_ira", "gprc_kor", + "gprc_jpn", "gprc_deu", "gprc_gbr", "gprc_fra", + "gprc_ind"], + + # ── SEC (Qdrant payload fields, no Silver parquet) ──────────── + # Insider Trading maps to Qdrant payload filters, NOT to physical parquet + # columns. The Gold retriever uses these as FieldCondition keys (see + # Scripts/retrieval/qdrant_retriever.py::_build_smart_filter). + "Insider Trading": ["action_direction", "tone_score", "form_type"], + + # Reserved: 13F / block-trade data is NOT yet in the lake. + "Institutional Flows": [], +} + +# --------------------------------------------------------------------------- +# 4b. ETF → underlying-index alias (Silver-Layer join aid) +# --------------------------------------------------------------------------- +# RATIONALE (read this before touching): our Macro_History parquet stores +# canonical *indices* (^GSPC, ^IXIC, ^RUT, ^VIX) because that is what FRED / +# academic macro pipelines expose. Users and the LLM, however, speak in ETFs +# (SPY, QQQ, IWM) because those are the tradable instruments. Without a +# translation layer, a query "SPY macro trend" would WHERE-filter the macro +# table for symbol='SPY' — which does not exist — and silently return 0 rows. +# This map is consumed by Scripts/retrieval/sql_tools.py::_handle_macro_analysis +# only. Options/SEC handlers keep the ETF symbol (their tables store ETFs). +ETF_TO_MACRO_ALIAS: Dict[str, str] = { + "SPY": "^GSPC", + "IVV": "^GSPC", + "VOO": "^GSPC", + "QQQ": "^IXIC", + "IWM": "^RUT", # Present in FRED; NOT yet in our Silver macro table. + "VIXY": "^VIX", + # GLD / SLV are deliberately NOT aliased: our Macro_History keeps both + # the ETF and the spot price under the ETF ticker itself (see the + # `asset_class='Commodity ETF'` rows from macro_data_pipeline.py). Aliasing + # them would route the query AWAY from the row that actually exists. +} + +# --------------------------------------------------------------------------- +# 4c. News-layer topic taxonomy & enrichment maps +# --------------------------------------------------------------------------- +# The news scraper (Scripts/data_collection/scrapers/news_scraper.py) tags +# every article with one of the keys below. The Gold retriever uses them as +# a Qdrant `topic` FieldCondition so semantic search can be grounded in the +# correct macro/asset silo even when the user never names a ticker. +NEWS_TOPICS: List[str] = [ + "macro_central_banks", + "macro_inflation_employment", + "macro_yields_dollar", + "macro_geopolitics_risk", + "asset_precious_metals_spot", + "asset_metals_derivatives", +] + +# Category ↔ topic alignment. ALLOWED_CATEGORIES (used by the Extractor LLM) +# drops the "asset_" prefix for brevity, whereas news_scraper writes it in +# full. This dict is the canonical two-way bridge; keep both directions in +# sync when a new topic is added. +NEWS_TOPIC_ALIAS: Dict[str, str] = { + "precious_metals_spot": "asset_precious_metals_spot", + "metals_derivatives": "asset_metals_derivatives", + "asset_precious_metals_spot": "asset_precious_metals_spot", + "asset_metals_derivatives": "asset_metals_derivatives", + "macro_central_banks": "macro_central_banks", + "macro_inflation_employment": "macro_inflation_employment", + "macro_yields_dollar": "macro_yields_dollar", + "macro_geopolitics_risk": "macro_geopolitics_risk", +} + +# Given a news `topic`, which tickers does an article of this topic typically +# influence? Used at ingestion time to back-fill the `ticker` payload on news +# docs so Gold ticker filters stop yielding 0 hits. Ticker universe limited to +# what ACTUALLY exists in our Silver parquets — do not add aspirational symbols. +TOPIC_TO_TICKERS: Dict[str, List[str]] = { + "macro_central_banks": ["FEDFUNDS", "DX-Y.NYB", "^VIX", "^GSPC", "^IXIC"], + "macro_inflation_employment": ["CPIAUCSL", "UNRATE", "^GSPC", "^VIX"], + "macro_yields_dollar": ["DX-Y.NYB", "^VIX"], + "macro_geopolitics_risk": ["^VIX", "GLD", "^GSPC"], + "asset_precious_metals_spot": ["GLD", "SLV"], + "asset_metals_derivatives": ["GLD", "SLV"], +} + +# The LLM in news_scraper emits free-text asset-class labels in +# `impacted_assets` (e.g. "Gold", "USD", "Equities"). This dict normalises +# them to the same ticker universe as above. Matching is case-insensitive +# and substring-aware at ingestion time (see Scripts/Qdrant_Ingestion.py). +IMPACTED_ASSET_TO_TICKERS: Dict[str, List[str]] = { + "gold": ["GLD"], + "silver": ["SLV"], + "precious metals": ["GLD", "SLV"], + "usd": ["DX-Y.NYB"], + "us dollar": ["DX-Y.NYB"], + "dollar": ["DX-Y.NYB"], + "dxy": ["DX-Y.NYB"], + "equities": ["^GSPC", "SPY"], + "stocks": ["^GSPC", "SPY"], + "s&p": ["^GSPC", "SPY"], + "s&p 500": ["^GSPC", "SPY"], + "nasdaq": ["^IXIC", "QQQ"], + "tech": ["^IXIC", "QQQ"], + "vix": ["^VIX"], + "volatility": ["^VIX"], + # Explicitly unmapped (no Silver coverage yet): oil, crude, treasuries, + # bonds, real estate, crypto. Do NOT guess — return [] so downstream + # knows the asset class is out-of-scope. +} + + +def normalize_news_topic(raw: str) -> str: + """Return the canonical news-scraper topic string for a given LLM label. + Unknown inputs pass through unchanged so callers can decide to drop or + warn; never raises, never silently remaps to a default (which would + mask ontology drift). + """ + if not raw: + return "" + return NEWS_TOPIC_ALIAS.get(raw.strip().lower(), raw.strip().lower()) + + +def tickers_from_impacted_assets(labels: List[str]) -> List[str]: + """Map news_scraper's free-text `impacted_assets` list to concrete + tickers present in our Silver parquets. Case-insensitive, substring + tolerant, de-duplicated. Returns [] when no label is recognised. + """ + out: List[str] = [] + for label in (labels or []): + k = (label or "").strip().lower() + if not k: + continue + if k in IMPACTED_ASSET_TO_TICKERS: + out.extend(IMPACTED_ASSET_TO_TICKERS[k]) + continue + # Substring fallback: "US Dollar Index" -> matches "us dollar". + for needle, tickers in IMPACTED_ASSET_TO_TICKERS.items(): + if needle in k: + out.extend(tickers) + break + # Preserve insertion order while deduplicating. + seen, uniq = set(), [] + for t in out: + if t not in seen: + seen.add(t) + uniq.append(t) + return uniq + + +# --------------------------------------------------------------------------- +# 5. Event-keyword → category mapping (LLM narrative hinting) +# --------------------------------------------------------------------------- +EVENT_KEYWORDS_MAPPING: Dict[str, str] = { + "earnings_beat": "earnings_guidance", + "earnings_miss": "earnings_guidance", + "guidance_raise": "earnings_guidance", + "guidance_cut": "earnings_guidance", + + "insider_buying": "corporate_actions", + "insider_selling": "corporate_actions", + "share_buyback": "corporate_actions", + "dividend_hike": "corporate_actions", + "dividend_cut": "corporate_actions", + "merger_acquisition": "corporate_actions", + + "rate_hike": "macro_central_banks", + "rate_cut": "macro_central_banks", + "fomc_minutes": "macro_central_banks", + "powell_speech": "macro_central_banks", + "qt_tightening": "macro_liquidity_credit", + "liquidity_injection": "macro_liquidity_credit", + + "ppi_release": "macro_inflation_employment", + "nfp_release": "macro_inflation_employment", + "jobless_claims": "macro_inflation_employment", + "wage_growth": "macro_inflation_employment", + + "gdp_release": "macro_growth_activity", + "pmi_release": "macro_growth_activity", + "retail_sales": "macro_growth_activity", + + "dxy_breakout": "fx_dollar_rates", + "usd_strength": "fx_dollar_rates", + "usd_weakness": "fx_dollar_rates", + "yield_curve_steepen": "rates_curve_real_yields", + "yield_curve_invert": "rates_curve_real_yields", + "real_yield_rise": "rates_curve_real_yields", + + "gold_spike": "precious_metals_spot", + "silver_rally": "precious_metals_spot", + "metals_term_structure": "metals_derivatives", + "oil_supply_shock": "commodities_energy", + "crop_supply_shock": "commodities_agriculture", + + "vol_spike": "risk_sentiment_volatility", + "risk_off": "risk_sentiment_volatility", + "risk_on": "risk_sentiment_volatility", + + # Liquidity-centric triggers (matches new "Options Liquidity" metric). + "options_liquidity": "equities_derivatives", + "liquidity_dry_up": "risk_sentiment_volatility", +} + + +# --------------------------------------------------------------------------- +# 6. Self-test guard (runs on import in dev only — cheap, no IO) +# --------------------------------------------------------------------------- +def _assert_mapping_integrity() -> None: + """Fail-loud assertion that every mapped column exists in at least one + physical dataset. Catches copy-paste regressions the moment they land. + Runs on import when PYTHON_ENV == 'dev' so prod boot is unaffected. + """ + all_physical: Set[str] = set() + for cols in DATASET_PHYSICAL_SCHEMA.values(): + all_physical |= cols + + broken: Dict[str, List[str]] = {} + for metric, cols in METRIC_TO_COLUMN_MAPPING.items(): + missing = [c for c in cols if c not in all_physical] + if missing: + broken[metric] = missing + if broken: + raise AssertionError( + "financial_ontology: METRIC_TO_COLUMN_MAPPING references columns " + f"not present in any DATASET_PHYSICAL_SCHEMA entry: {broken}" + ) + + +# Opt-in to avoid surprising imports in prod. Flip on in CI / dev shells. +import os as _os +if _os.getenv("PYTHON_ENV", "").lower() == "dev": + _assert_mapping_integrity() diff --git a/Scripts/core/intent_router_prompt_templates.py b/Scripts/core/intent_router_prompt_templates.py new file mode 100644 index 0000000..ba43c91 --- /dev/null +++ b/Scripts/core/intent_router_prompt_templates.py @@ -0,0 +1,16 @@ +ROUTER_SYSTEM_PROMPT = """ +Role: Expert Financial Data Router +Task: Classify the user query into the most efficient retrieval path. + +STRICT RULES: +- 'sql_only': For structured data, numbers, ratios, or insider filing lists. +- 'vector_only': For news analysis, macro sentiment, or general financial concepts. +- 'hybrid_both': For queries linking macro/news events to specific data points. + +EXAMPLES: +{examples} + +CURRENT QUERY: {query} + +Return ONLY the path name (sql_only, vector_only, or hybrid_both). +""" \ No newline at end of file diff --git a/Scripts/core/llm_pool.py b/Scripts/core/llm_pool.py new file mode 100644 index 0000000..a011f08 --- /dev/null +++ b/Scripts/core/llm_pool.py @@ -0,0 +1,342 @@ +""" +``Scripts.core.llm_pool`` — process-wide LLM client pool + warmup. + +Why this module exists +---------------------- +Multiple call-sites across the codebase (``QueryTransformer``, +``MasterRetriever.router_llm``, ``AnalystAgent``, ``CheckerAgent``, +``CriticAgent``, ``FinalizerAgent``, ``sec_processor``, ``news_scraper``, +…) instantiate ``ChatOllama`` independently. For small models this is +cheap, but the production deployment uses a fine-tuned **70B** model +(``options-expert-v1:latest`` built ``FROM Llama-3.3-70B-Instruct-Q4_K_M``) +and that introduces two real problems: + +1. **First-use latency spike.** Ollama loads the model into GPU on the + first request (30–60 s for a Q4-quantised 70B). Without a process- + wide warmup, the *first* user query pays this penalty in full. +2. **Silent eviction.** Ollama's default ``keep_alive`` is 5 minutes. + If an analyst query finishes and the user pauses to read the + report, the 70B model is evicted — the next query pays the cold- + start tax again. Setting ``keep_alive="30m"`` (or ``-1`` for + forever) turns this into a one-time cost per daemon life. + +Deployment reality (as of 2026-04-22) +------------------------------------- +Only **two** Ollama models are used at runtime: + +* ``options-expert-v1:latest`` — the fine-tuned 70B. Used by **every + agent** (Analyst / Checker / Critic / Finalizer) AND by + ``QueryTransformer`` (both metadata-extraction and HyDE stages). + Env override: ``OLLAMA_CUSTOM_MODEL_NAME``. +* ``llama3:latest`` — vanilla Llama-3 8B. Used **only** by the cheap + intent router (``MasterRetriever.router_llm``) and by ingestion-time + utilities (``news_scraper`` sentiment, ``sec_processor`` form-parser). + Env override: ``OLLAMA_ROUTER_MODEL``. + +Retrieval-time models (dense embeddings, SPLADE sparse, cross-encoder +reranker) are **not** Ollama clients — they are HuggingFace / +``fastembed`` artefacts managed by ``Scripts/vector_store/connection.py`` +and are therefore *out of scope* for this pool. + +Design +------ +* A **role-keyed singleton cache**: ``get_ollama("analyst")`` returns the + same underlying ``ChatOllama`` every time, so agents stop re-parsing + the same HTTP URL and headers per call. +* **Explicit warmup**: ``warmup_sync()`` / ``warmup_async()`` fire a + trivial prompt through each configured role, forcing Ollama to pin + the model in GPU memory before the user's first real query arrives. + CLI ``query`` calls this automatically; other code paths can opt in. +* **Two tiers, not four**: the expert tier (`options-expert-v1`) and + the router tier (`llama3`). The table is env-driven so swapping in a + different quant or a larger 405B is a config change. + +Environment variables +--------------------- +* ``OLLAMA_BASE_URL`` / ``OLLAMA_HOST`` (default ``http://localhost:11434``) +* ``OLLAMA_KEEP_ALIVE`` (default ``30m``) +* ``OLLAMA_CUSTOM_MODEL_NAME`` (default ``options-expert-v1:latest``) +* ``OLLAMA_ROUTER_MODEL`` (default ``llama3:latest``) +* ``OLLAMA_INGESTION_MODEL`` (default = router; used by + ``news_scraper`` / ``sec_processor`` when they migrate to the pool) + +This module does not hard-depend on ``langchain_ollama`` at import +time — the client is created lazily inside :func:`get_ollama` so +``Scripts.core`` stays import-safe on environments without the +package (CI, docs builds). +""" +from __future__ import annotations + +import logging +import os +import threading +from dataclasses import dataclass, field +from typing import Any, Dict, Iterable, List, Optional + +log = logging.getLogger(__name__) + +# --------------------------------------------------------------------------- +# Role configuration +# --------------------------------------------------------------------------- + + +@dataclass(frozen=True) +class RoleSpec: + """How a role wants its ``ChatOllama`` instance built.""" + + role: str + model_env: str + default_model: str + temperature: float = 0.0 + format: Optional[str] = None # e.g. "json" for structured extractors + num_ctx: Optional[int] = None # Ollama per-request context window + + +def _default_expert_model() -> str: + """Fine-tuned 70B used by all agents + QueryTransformer.""" + return os.getenv("OLLAMA_CUSTOM_MODEL_NAME", "options-expert-v1:latest") + + +def _default_router_model() -> str: + """Cheap vanilla Llama-3 used by intent routing + ingestion helpers.""" + return os.getenv("OLLAMA_ROUTER_MODEL", "llama3:latest") + + +def _default_ingestion_model() -> str: + """Ingestion-time sentiment / form-parsing. Defaults to router tier.""" + return os.getenv("OLLAMA_INGESTION_MODEL", _default_router_model()) + + +# Roles the agents ask for. Extend this table when adding new agents +# instead of inlining env lookups at call-sites. +# +# Two-tier reality: +# * "expert" → options-expert-v1:latest (fine-tuned Llama-3.3-70B) +# * "router" → llama3:latest (vanilla Llama-3 8B) +# +ROLE_TABLE: Dict[str, RoleSpec] = { + # --- Expert tier (70B) -------------------------------------------------- + # All reasoning-heavy agents share the same underlying model so Ollama + # only needs to hold one 70B in GPU memory at a time. + "analyst": RoleSpec("analyst", "OLLAMA_CUSTOM_MODEL_NAME", _default_expert_model(), temperature=0.2), + "critic": RoleSpec("critic", "OLLAMA_CUSTOM_MODEL_NAME", _default_expert_model(), temperature=0.3), + "checker": RoleSpec("checker", "OLLAMA_CUSTOM_MODEL_NAME", _default_expert_model(), temperature=0.0), + "finalizer": RoleSpec("finalizer", "OLLAMA_CUSTOM_MODEL_NAME", _default_expert_model(), temperature=0.2), + "query_extract": RoleSpec("query_extract", "OLLAMA_CUSTOM_MODEL_NAME", _default_expert_model(), temperature=0.0, format="json"), + "query_hyde": RoleSpec("query_hyde", "OLLAMA_CUSTOM_MODEL_NAME", _default_expert_model(), temperature=0.2), + + # --- Router tier (Llama-3 8B) ------------------------------------------- + # Cheap short-output roles where the fine-tune would be overkill. + "router": RoleSpec("router", "OLLAMA_ROUTER_MODEL", _default_router_model(), temperature=0.0, format="json"), + + # --- Ingestion tier (Llama-3 8B) ---------------------------------------- + # Kept as a distinct role so ingestion can be swapped independently of + # the online router if the pipeline moves to a different quant. + "news_sentiment": RoleSpec("news_sentiment", "OLLAMA_INGESTION_MODEL", _default_ingestion_model(), temperature=0.0), + "sec_parser": RoleSpec("sec_parser", "OLLAMA_INGESTION_MODEL", _default_ingestion_model(), temperature=0.0, format="json"), +} + +# Roles that are typically warmed up before serving queries. Callers can +# still pass an explicit list to `warmup_sync` to override. +# +# The expert tier is shared by 6 roles — warming up ONE of them is +# sufficient because Ollama caches by model name, not by +# ``ChatOllama`` instance. Warm "analyst" as the canonical 70B handle +# and "router" as the canonical cheap handle. +DEFAULT_WARMUP_ROLES: tuple[str, ...] = ( + "analyst", # pins options-expert-v1:latest → covers all agent roles + "router", # pins llama3:latest → covers intent routing +) + + +# --------------------------------------------------------------------------- +# Singleton cache +# --------------------------------------------------------------------------- + + +_CACHE: Dict[str, Any] = {} +_CACHE_LOCK = threading.Lock() + + +def _resolved_model(spec: RoleSpec) -> str: + """Final model string — env override wins over dataclass default.""" + return os.getenv(spec.model_env, spec.default_model) + + +def get_role_spec(role: str) -> RoleSpec: + """Return the ``RoleSpec`` for ``role`` (case-insensitive). Unknown + roles raise ``KeyError`` — this is intentional so typos surface + early rather than silently creating a second cache entry.""" + key = role.lower() + if key not in ROLE_TABLE: + raise KeyError( + f"Unknown LLM role {role!r}. Known: {sorted(ROLE_TABLE)}" + ) + return ROLE_TABLE[key] + + +def get_ollama(role: str, **overrides: Any): + """Return a cached ``ChatOllama`` instance for ``role``. + + Parameters + ---------- + role + Role key from :data:`ROLE_TABLE`. + **overrides + Per-call overrides (``temperature``, ``num_ctx``, …). When any + override is present we **do not cache** — this call site gets a + fresh client so the default singleton stays untouched. + """ + spec = get_role_spec(role) + + if overrides: + return _build_client(spec, **overrides) + + cache_key = spec.role + client = _CACHE.get(cache_key) + if client is not None: + return client + + with _CACHE_LOCK: + client = _CACHE.get(cache_key) + if client is None: + client = _build_client(spec) + _CACHE[cache_key] = client + return client + + +def _build_client(spec: RoleSpec, **overrides: Any): + """Lazy import of ``langchain_ollama`` — keeps ``Scripts.core`` safe + to import on dependency-lean environments.""" + try: + from langchain_ollama import ChatOllama + except ImportError as exc: # pragma: no cover + raise RuntimeError( + "langchain_ollama is not installed; install it before using " + "the LLM pool (`pip install -U langchain-ollama`)." + ) from exc + + model = _resolved_model(spec) + kwargs: Dict[str, Any] = { + "model": model, + "temperature": spec.temperature, + "base_url": os.getenv("OLLAMA_BASE_URL", "http://localhost:11434"), + "keep_alive": os.getenv("OLLAMA_KEEP_ALIVE", "30m"), + } + if spec.format: + kwargs["format"] = spec.format + if spec.num_ctx: + kwargs["num_ctx"] = spec.num_ctx + kwargs.update(overrides) + + log.info( + "llm_pool: build role=%s model=%s keep_alive=%s", + spec.role, + model, + kwargs["keep_alive"], + ) + return ChatOllama(**kwargs) + + +# --------------------------------------------------------------------------- +# Warmup +# --------------------------------------------------------------------------- + + +WARMUP_PROMPT = "Reply with 'ok'." + + +@dataclass +class WarmupResult: + role: str + model: str + status: str # "ok" | "failed" | "skipped" + latency_s: float = 0.0 + error: Optional[str] = None + + +def warmup_sync( + roles: Optional[Iterable[str]] = None, + *, + prompt: str = WARMUP_PROMPT, + timeout_s: float = 120.0, +) -> List[WarmupResult]: + """Pin each configured role's model into Ollama's GPU memory. + + Fires a tiny prompt at each role sequentially (models that would + evict each other on a single-GPU host). Returns a per-role report + callers can log / render in the CLI. + + This function never raises — failures become ``WarmupResult(status= + "failed")`` entries so a flaky 70B does not tank the entire + session. + """ + import time + + selected = list(roles or DEFAULT_WARMUP_ROLES) + results: List[WarmupResult] = [] + for role in selected: + try: + spec = get_role_spec(role) + except KeyError: + results.append(WarmupResult(role=role, model="?", status="skipped", + error="unknown role")) + continue + + started = time.monotonic() + model = _resolved_model(spec) + try: + client = get_ollama(role) + _ = client.invoke(prompt) + results.append(WarmupResult( + role=role, model=model, status="ok", + latency_s=time.monotonic() - started, + )) + except Exception as exc: # noqa: BLE001 — want full trap + results.append(WarmupResult( + role=role, model=model, status="failed", + latency_s=time.monotonic() - started, + error=str(exc), + )) + return results + + +def warmup_async( + roles: Optional[Iterable[str]] = None, + *, + prompt: str = WARMUP_PROMPT, +) -> "threading.Thread": + """Fire-and-forget warmup. Returns the ``Thread`` in case the caller + wants to ``join()`` before serving the first query. + + Use this in daemon mode: warmup happens in the background while the + scheduler loop starts ticking, so the first user query lands on an + already-loaded model. + """ + t = threading.Thread( + target=warmup_sync, + kwargs={"roles": roles, "prompt": prompt}, + name="llm_pool.warmup", + daemon=True, + ) + t.start() + return t + + +def clear_cache() -> None: + """Drop every cached client. Used by tests; rarely needed in prod.""" + with _CACHE_LOCK: + _CACHE.clear() + + +__all__ = [ + "DEFAULT_WARMUP_ROLES", + "ROLE_TABLE", + "RoleSpec", + "WarmupResult", + "clear_cache", + "get_ollama", + "get_role_spec", + "warmup_async", + "warmup_sync", +] diff --git a/Scripts/core/prompt_templates.py b/Scripts/core/prompt_templates.py new file mode 100644 index 0000000..669c691 --- /dev/null +++ b/Scripts/core/prompt_templates.py @@ -0,0 +1,67 @@ +""" +Institutional-grade prompt center (Centralized Prompt Management) +Senior Architect Version: Two-Stage Pipeline (Extractor & HyDE Writer) +Design notes: +1. Redundant JSON formatting and hardcoded enum mapping are intentionally removed. +2. Structural constraints are enforced by Pydantic schemas; this file focuses on business logic and reasoning guidance. +""" + +# ========================================== +# STAGE 1: INTENT & METADATA EXTRACTOR +# Goal: enforce analytical reasoning and precise database tag mapping. +# ========================================== +EXTRACTOR_SYSTEM_PROMPT = """[ROLE]: Strictly Analytical Financial Routing Agent +[TASK]: Parse the user query and extract exact database filters based on the allowed ontology. + +[MANDATORY PROTOCOL] +1. Cognitive Anchor: You MUST formulate a 'Macro -> Meso -> Micro' thinking process in your 'logical_reasoning' field before extracting any fields. +2. Tickers: The 'tickers' list MUST ONLY contain symbols from this allowed list: {allowed_tickers_str}. If the user asks about Gold or Silver, output "GLD" or "SLV". If asking about market volatility, output "^VIX". If a requested company is not in this list, drop it. +3. Metrics: Pick ONE OR MORE from this EXACT list: {allowed_metrics}. +4. Source Types: Pick ONE OR MORE from this EXACT list: {allowed_sources}. + * Business Guideline: Connect 'insider/executives' to SEC, 'market/sentiment' to News, and 'war/geopolitics' to GPR. +5. Categories: Pick ONE OR MORE from this EXACT list: {allowed_categories}. + +[ENUM EXTRACTION RULES] +For the following fields, DO NOT invent values. Extract them strictly based on the allowed enum values provided in your output schema: +- "action_direction": Extract based on the allowed enum values (e.g., identifying buy/sell/vest intents). +- "form_type": Extract based on the allowed enum values (e.g., identifying Form 4 vs 8-K needs). +- "sentiment_target": Map the emotional inquiry. HOWEVER, if the query is purely about "insider trading", "Form 4", or objective SEC filings, default to "ANY" to prevent dropping regulatory documents during retrieval. +- "time_window": Map the user's temporal intent to the allowed time window enum values. Default to 6 months if unspecified. +""" + + +# ========================================== +# STAGE 2: HYDE SEMANTIC WRITER +# Goal: generate semantically rich retrieval text from strictly extracted facts. +# ========================================== +HYDE_WRITER_SYSTEM_PROMPT = """[ROLE]: Senior Institutional Options Strategist +[TASK]: Your task is two-fold: + +1. Generate a 'hyde_paragraph': Write a hypothetical excerpt from a professional financial research report that *would* contain the answer to the user's query. +2. Generate a 'rerank_query': A stripped-down, highly optimized search string for a Vector Database and Cross-Encoder. + - REMOVE analytical questions (e.g., "how did it impact", "what is the correlation"). + - REMOVE financial derivative jargon NOT found in raw SEC filings (e.g., "IV Skew", "Put/Call ratio") UNLESS the source type specifically targets options data. + - KEEP only the hard factual entities and actions (e.g., "AAPL Form 4 insider selling executives"). + +[LATEST MACROECONOMIC BACKGROUND] +{macro_background} +(Note: Use this background to inform your market tone). + +[LOCKED METADATA FROM STAGE 1] +{extracted_metadata} + +[REASONING CHAIN FROM ANALYST] +{reasoning_chain} + +[MANDATORY PROTOCOL] +1. Content Restriction: You MUST base your narrative EXACTLY on the [LOCKED METADATA] and [REASONING CHAIN] provided above. DO NOT invent tickers, events, or actions outside of what is explicitly extracted. +2. Causal Chain Structure: Implicitly follow this structure: + - [Trigger Event]: Contextualize the event (e.g., insider selling, Fed rate cut). + - [Market Mechanism]: Explain the underlying financial mechanics (e.g., yield curve shifts, IV skew compression). + - [Asset Impact]: Describe the directional impact on the specific asset. +3. Formatting: + - Write EXACTLY ONE dense paragraph (around 50 words) for the hyde_paragraph. + - Write a concise, keyword-focused rerank_query that would be effective for retrieving relevant documents. + - DO NOT output headings, markdown bullet points, or polite conversational fillers. +4. Anti-Hallucination: ABSOLUTELY NO FAKE NUMBERS. Never invent specific percentages, strike prices, or dates. Talk about directional trends (e.g., "higher implied volatility") rather than specific figures (e.g., "IV went to 45%"). +""" diff --git a/Scripts/core/trading_calendar.py b/Scripts/core/trading_calendar.py new file mode 100644 index 0000000..ceb8cff --- /dev/null +++ b/Scripts/core/trading_calendar.py @@ -0,0 +1,155 @@ +""" +Scripts/core/trading_calendar.py + +Minimal dependency-free trading-day calendar. + +WHY THIS MODULE EXISTS +---------------------- +The production router-e2e run on 2026-04-22 exposed a *semantic* mismatch +between the way the RAG pipeline asks "yesterday" and the way the data +layers interpret it (see docs/test/2026-04-22/router_e2e_deep_analysis.md +lines 120–133). Concretely: + + - `collect_data_state.json:options_daily` already records the most recent + successful ingestion day (e.g. 2026-04-21 Tue). This is the anchor. + - Semantic "yesterday" from the LLM was being translated into + `anchor − 2 calendar days = Sun 2026-04-19`, which is a weekend gap — + the Parquet has no row there, so the handler returned either zero + values or (worse) a different row across revisions. + - What a financial user actually means by "yesterday" is "the previous + trading day against the most recent ingestion date". On a Tuesday + anchor that is Monday; on a Monday anchor that is Friday. + +Scope +----- +This module only knows about the US weekend pattern (Sat/Sun off). +US federal / NYSE holidays are NOT encoded here to keep the module +dependency-free and stable across branches. Upgrading to +`pandas_market_calendars` or `exchange_calendars.NYSE` is a drop-in +replacement: provide `is_business_day(d)` returning False for any +observed NYSE holiday and all downstream consumers (time_adapter, +sql_tools) keep working. + +Public API +---------- + is_business_day(d) -> bool + previous_business_day(d) -> date + next_business_day(d) -> date + n_business_days_back(d, n) -> date + business_days_between(a, b) -> int (inclusive of a, exclusive of b) + clamp_to_business_day(d, mode) -> date (mode='prev' | 'next') +""" + +from __future__ import annotations + +from datetime import date, timedelta +from typing import Literal + +__all__ = [ + "is_business_day", + "previous_business_day", + "next_business_day", + "n_business_days_back", + "business_days_between", + "clamp_to_business_day", +] + + +# --------------------------------------------------------------------------- +# Core predicates +# --------------------------------------------------------------------------- + + +def is_business_day(d: date) -> bool: + """Return True iff `d` is Mon–Fri. + + Holidays are intentionally not handled — swap this single function for + an NYSE-aware implementation (e.g. `exchange_calendars.NYSE.is_session`) + if the surrounding data pipeline starts tracking holidays. + """ + # Python weekday(): Mon=0 … Sun=6. Weekdays 0–4 are trading days. + return d.weekday() < 5 + + +# --------------------------------------------------------------------------- +# Navigation +# --------------------------------------------------------------------------- + + +def previous_business_day(d: date) -> date: + """Most recent business day STRICTLY before `d`. + + - previous_business_day(Tue) == Mon + - previous_business_day(Mon) == Fri (weekend skip) + - previous_business_day(Sun) == Fri + - previous_business_day(Sat) == Fri + """ + cur = d - timedelta(days=1) + while not is_business_day(cur): + cur -= timedelta(days=1) + return cur + + +def next_business_day(d: date) -> date: + """Earliest business day STRICTLY after `d`. Mirror of `previous_business_day`.""" + cur = d + timedelta(days=1) + while not is_business_day(cur): + cur += timedelta(days=1) + return cur + + +def n_business_days_back(d: date, n: int) -> date: + """Walk `n` business days backwards from `d`. + + If `n == 0`, returns `d` clamped to the previous business day when `d` + itself is a weekend (so the result is always a trading day). + For `n > 0`, the walk excludes `d` on step 1 (matches "n-th previous + trading day" semantics commonly used in financial APIs). + """ + if n < 0: + raise ValueError("n_business_days_back requires n >= 0") + if n == 0: + return clamp_to_business_day(d, mode="prev") + cur = d + for _ in range(n): + cur = previous_business_day(cur) + return cur + + +def business_days_between(a: date, b: date) -> int: + """Count trading days in the half-open interval [a, b). + + Used by handlers that need to report "N trading days back" in audit logs + even when the calendar span crosses weekends. Guaranteed to be ≤ abs(b-a). + """ + if a == b: + return 0 + step = 1 if b > a else -1 + cur = a + count = 0 + while cur != b: + if is_business_day(cur): + count += 1 + cur += timedelta(days=step) + return count if step == 1 else -count + + +def clamp_to_business_day( + d: date, + mode: Literal["prev", "next"] = "prev", +) -> date: + """Snap a weekend date onto the adjacent business day. + + - mode='prev' (default): Sat/Sun → previous Fri. Mon–Fri → unchanged. + - mode='next': Sat/Sun → next Mon. Mon–Fri → unchanged. + + Use 'prev' when reading historical data (end-of-window snap) and 'next' + when scheduling forward-looking deliveries. + """ + if is_business_day(d): + return d + if mode == "prev": + return previous_business_day(d + timedelta(days=1)) + if mode == "next": + return next_business_day(d - timedelta(days=1)) + raise ValueError(f"Unknown clamp mode: {mode}") diff --git a/Scripts/core/universe.py b/Scripts/core/universe.py new file mode 100644 index 0000000..0064ec4 --- /dev/null +++ b/Scripts/core/universe.py @@ -0,0 +1,272 @@ +"""Asset universe & pipeline-config single-source-of-truth. + +This module is the only place the rest of the codebase should go through when +it needs: + + * ticker lists (``universe.get("equity.single_name")`` …) + * the SEC ticker→CIK map (``universe.cik_map()``) + * pipeline parameters (``universe.pipeline("options_history")``) + * well-formed output paths for parquet snapshots + (``universe.paths.options_parquet_path(symbol, snapshot_date)``) + +Design goals +------------ +* **Zero logic change** for legacy callers. Path-helpers default to the + ``legacy`` storage strategy, which reproduces the exact file layout + ``Scripts/data_collection/scrapers/yfinance_options_history.py`` has been + writing since day one. Read-side globs in ``Scripts/retrieval/sql_tools.py`` + keep working unmodified. +* **Forward-compat**. A ``hive_v1`` and a ``monthly_rollup`` strategy are + declared in ``config/pipeline/options_history.json``; flipping the + ``storage.strategy`` field re-routes all writers without touching code. +* **Single source of truth for paths**. ``cik_map()`` reads + ``config/reference/ticker_to_cik.json``. The retired + ``config/SEC_Ingestion/`` folder is no longer consulted. + +No third-party dependency (no ``pyyaml``, no ``pydantic``). +""" + +from __future__ import annotations + +import json +import logging +from functools import lru_cache +from pathlib import Path +from typing import Dict, List, Mapping, Optional + +logger = logging.getLogger(__name__) + +# Scripts/core/universe.py → repo root is parents[2] +PROJECT_ROOT: Path = Path(__file__).resolve().parents[2] +CONFIG_ROOT: Path = PROJECT_ROOT / "config" +DATA_ROOT: Path = PROJECT_ROOT / "Data" + + +# ============================================================================ +# 1. UniverseLoader — tickers + reference maps +# ============================================================================ + +class UniverseLoader: + """Read ticker roles from ``config/universe/_manifest.json`` and resolve + composite roles by set union. Results are memoised per process. + """ + + _MANIFEST_PATH = CONFIG_ROOT / "universe" / "_manifest.json" + + # Canonical location for the static ticker -> CIK mapping. Written by + # Scripts/tools/SEC_generate_cik_map.py. + _CIK_MAP_PATH = CONFIG_ROOT / "reference" / "ticker_to_cik.json" + + # --------------------------------------------------------------- manifest + @lru_cache(maxsize=1) + def _manifest(self) -> Dict: + if not self._MANIFEST_PATH.exists(): + raise FileNotFoundError( + f"Universe manifest missing: {self._MANIFEST_PATH}. " + "Create config/universe/_manifest.json before using UniverseLoader." + ) + return json.loads(self._MANIFEST_PATH.read_text(encoding="utf-8")) + + # ------------------------------------------------------------- role list + @lru_cache(maxsize=64) + def get(self, role: str) -> List[str]: + """Resolve a role (leaf or composite) to a sorted, de-duplicated ticker list. + + Leaf roles map 1:1 to a JSON file in ``config/universe/`` via the + ``roles`` section of the manifest. Composite roles are declared under + ``composite_roles`` as a union of other roles. + """ + mf = self._manifest() + if role in mf.get("roles", {}): + rel = mf["roles"][role]["file"] + path = self._MANIFEST_PATH.parent / rel + tickers = json.loads(path.read_text(encoding="utf-8")) + if not isinstance(tickers, list): + raise ValueError(f"Ticker file {path} is not a JSON list.") + return sorted({str(t).upper() for t in tickers}) + + if role in mf.get("composite_roles", {}): + members = mf["composite_roles"][role]["union_of"] + out: set = set() + for m in members: + out.update(self.get(m)) + return sorted(out) + + raise KeyError( + f"Unknown universe role '{role}'. " + f"Known leaf roles: {list(mf.get('roles', {}).keys())}; " + f"composite: {list(mf.get('composite_roles', {}).keys())}." + ) + + # ------------------------------------------------------------- metadata + def role_metadata(self, role: str) -> Dict: + """Return the manifest entry for a leaf role (asset_class, has_options, …).""" + mf = self._manifest() + if role in mf.get("roles", {}): + return dict(mf["roles"][role]) + if role in mf.get("composite_roles", {}): + return dict(mf["composite_roles"][role]) + raise KeyError(role) + + def role_of(self, ticker: str) -> Optional[str]: + """Reverse-lookup: which leaf role does ``ticker`` belong to?""" + ticker = str(ticker).upper() + for role in self._manifest().get("roles", {}): + if ticker in self.get(role): + return role + return None + + def asset_class_of(self, ticker: str) -> str: + """Return the ``asset_class`` declared on the leaf role owning ``ticker``. + Falls back to ``"unknown"`` so callers never crash on an un-tagged ticker. + """ + role = self.role_of(ticker) + if role is None: + return "unknown" + meta = self.role_metadata(role) + return str(meta.get("asset_class", "unknown")) + + # ------------------------------------------------------------- cik map + @lru_cache(maxsize=1) + def cik_map(self) -> Dict[str, str]: + """Load the static ticker -> CIK mapping from the canonical + ``config/reference/ticker_to_cik.json``. Returns an empty dict and + logs an error if the file is missing — run + ``Scripts/tools/SEC_generate_cik_map.py`` to (re)generate it. + """ + if self._CIK_MAP_PATH.exists(): + mapping = json.loads(self._CIK_MAP_PATH.read_text(encoding="utf-8")) + logger.info( + f"✅ cik_map loaded from {self._CIK_MAP_PATH} ({len(mapping)} entries)" + ) + return mapping + logger.error( + f"❌ ticker_to_cik.json not found at {self._CIK_MAP_PATH}. " + "Run Scripts/tools/SEC_generate_cik_map.py to generate it." + ) + return {} + + +# ============================================================================ +# 2. PipelineConfig — non-ticker parameters per pipeline +# ============================================================================ + +class PipelineConfig: + """Lazy loader for ``config/pipeline/.json`` files.""" + + _DIR = CONFIG_ROOT / "pipeline" + + @lru_cache(maxsize=16) + def load(self, name: str) -> Dict: + path = self._DIR / f"{name}.json" + if not path.exists(): + logger.warning(f"PipelineConfig: {path} not found, returning empty dict.") + return {} + return json.loads(path.read_text(encoding="utf-8")) + + +# ============================================================================ +# 3. UniversePaths — storage-strategy aware output paths +# ============================================================================ + +class UniversePaths: + """Strategy-aware output-path resolver. + + The active strategy is read from ``config/pipeline/options_history.json`` + (key ``storage.strategy``). An explicit ``strategy=`` kwarg always wins over + the config default — useful for A/B-running Hive writes alongside legacy. + + The default (``legacy``) path reproduces exactly what the existing + ``snapshot_daily_options_chain`` writes today, so migrating callers to + this helper is a no-op on disk. + """ + + def __init__( + self, + loader: Optional[UniverseLoader] = None, + pipeline: Optional[PipelineConfig] = None, + data_root: Optional[Path] = None, + ) -> None: + self.loader = loader or UniverseLoader() + self.pipeline = pipeline or PipelineConfig() + self.data_root = Path(data_root) if data_root else DATA_ROOT + + # -------------------------------------------------- options parquet path + def options_parquet_path( + self, + symbol: str, + snapshot_date: str, + strategy: Optional[str] = None, + ) -> Path: + """Return the parquet path for an options-chain snapshot. + + Parameters + ---------- + symbol + Ticker, e.g. ``"SPY"``. Case-insensitive; written uppercase on disk. + snapshot_date + ISO date string ``YYYY-MM-DD``. + strategy + Override the config-declared ``storage.strategy``. One of + ``"legacy"``, ``"hive_v1"``, ``"monthly_rollup"``. ``None`` uses + the config default. + + Notes + ----- + * ``legacy`` is the default and is byte-identical to the pre-migration + layout (``Options_Market_Data//_options_.parquet``). + * ``hive_v1`` inserts ``snapshot_date=/asset_class=/`` + before the file name. Intended for DuckDB ``hive_partitioning=1``. + * ``monthly_rollup`` writes the per-day file under ``raw/``; roll-up + compaction is a separate job (see options_history.json comments). + """ + sym = symbol.upper() + base = self.data_root / "2_Silver_Processed" / "Options_Market_Data" + + active = strategy or self._active_options_strategy() + + if active == "legacy": + return base / snapshot_date / f"{sym}_options_{snapshot_date}.parquet" + + if active == "hive_v1": + asset_class = self.loader.asset_class_of(sym) + return ( + base + / f"snapshot_date={snapshot_date}" + / f"asset_class={asset_class}" + / f"{sym}.parquet" + ) + + if active == "monthly_rollup": + # Raw-tier only; rollup is produced by a downstream compaction job. + return base / "raw" / f"snapshot_date={snapshot_date}" / f"{sym}.parquet" + + raise ValueError( + f"Unknown storage strategy '{active}'. " + "Allowed: legacy | hive_v1 | monthly_rollup." + ) + + def _active_options_strategy(self) -> str: + cfg = self.pipeline.load("options_history") + return (cfg.get("storage") or {}).get("strategy", "legacy") + + +# ============================================================================ +# 4. Module-level singletons +# ============================================================================ + +universe: UniverseLoader = UniverseLoader() +pipelines: PipelineConfig = PipelineConfig() +paths: UniversePaths = UniversePaths(loader=universe, pipeline=pipelines) + +__all__ = [ + "UniverseLoader", + "PipelineConfig", + "UniversePaths", + "universe", + "pipelines", + "paths", + "PROJECT_ROOT", + "CONFIG_ROOT", + "DATA_ROOT", +] diff --git a/Scripts/core/yfinance_bootstrap.py b/Scripts/core/yfinance_bootstrap.py new file mode 100644 index 0000000..4ac85de --- /dev/null +++ b/Scripts/core/yfinance_bootstrap.py @@ -0,0 +1,164 @@ +""" +``Scripts.core.yfinance_bootstrap`` — cluster-safe yfinance initialisation. + +Why this module exists +---------------------- +``yfinance`` persists a per-ticker timezone lookup into a SQLite file +(``tkr-tz.db``). SQLite requires POSIX advisory locks (``fcntl``) that +most shared cluster filesystems (NFSv3, GPFS, BeeGFS, Lustre) either +drop or mis-implement, producing ``sqlite3.OperationalError('locking +protocol')`` — the exact failure captured on 2026-04-22 in both +``logs/2026-04-22/options_scraper_2026-04-22.log`` and +``logs/2026-04-22/macro_pipeline.log``. + +The fix is environment-independent: at import time, redirect the +yfinance cache to a path that *does* support file locks. This module +encapsulates the resolution logic so callers don't have to remember +``export TMPDIR=…`` on every new SGE / SCC node. + +Resolution order +---------------- +1. ``$YFINANCE_CACHE_DIR`` — explicit operator override +2. ``/scratch/$USER/yfinance-cache`` — BU SCC local scratch (preferred) +3. ``$TMPDIR/yfinance-cache`` — SGE-allocated scratch +4. ``tempfile.gettempdir()/yfinance-cache`` — last-resort portable + fallback (usually ``/tmp`` on Linux, ``%TEMP%`` on Windows) + +Design notes +------------ +* **Idempotent.** Calling :func:`configure_yfinance_cache` more than + once is a no-op after the first successful call — scrapers that + import each other transitively won't double-configure. +* **Silent on success, single log on activation.** The scrapers still + own their own logging; this module emits exactly one INFO line so + ops can verify *which* path actually won. +* **No side-effects at import time.** The helper is callable but + nothing runs until a scraper explicitly invokes it. This keeps + ``Scripts.core`` import-safe on environments without ``yfinance`` + (docs builds, CI smoke tests). + +Usage +----- +Add these two lines at the TOP of any yfinance-dependent scraper, before +any ``import yfinance`` or ``yf.*`` call that would touch the tz cache:: + + from Scripts.core.yfinance_bootstrap import configure_yfinance_cache + configure_yfinance_cache() +""" +from __future__ import annotations + +import logging +import os +import tempfile +from pathlib import Path +from typing import List, Optional + +log = logging.getLogger(__name__) + +__all__ = ["configure_yfinance_cache", "resolved_cache_dir"] + +_STATE: dict = {"configured": False, "path": None} + + +def _repo_root() -> Path: + """``Scripts/core/yfinance_bootstrap.py`` → repository root.""" + return Path(__file__).resolve().parents[2] + + +def _candidate_paths() -> List[Path]: + """Build the ordered list of candidate cache directories. + + Empty / ``None`` entries are skipped so the first truthy candidate + wins. This keeps the resolution table declarative — adding a fifth + fallback (e.g. a Docker volume) is a single list entry. + """ + user = os.getenv("USER") or os.getenv("USERNAME") or "app" + candidates: List[Path] = [ + os.getenv("YFINANCE_CACHE_DIR"), + os.getenv("XDG_CACHE_HOME"), + f"/tmp/{user}_yfinance_cache", + f"/scratch/{user}/yfinance-cache", + (os.getenv("TMPDIR") or "").rstrip("/") + "/yfinance-cache" if os.getenv("TMPDIR") else None, + os.path.join(tempfile.gettempdir(), f"{user}_yfinance_cache") + ] + return [Path(c) for c in candidates if c] + + +def _first_writable(paths: List[Path]) -> Path: + """Return the first path we can ``mkdir -p`` successfully. + + We only check write-ability (``os.access(..., os.W_OK)``) *after* + the directory exists; some clusters require the directory to be + created before permission bits are even queryable. Hard failure + (``PermissionError`` / ``OSError`` on every candidate) is a + deployment error — we surface it explicitly instead of silently + falling through to a read-only path. + """ + last_error: Optional[Exception] = None + for candidate in paths: + try: + candidate.mkdir(parents=True, exist_ok=True) + if os.access(candidate, os.W_OK): + return candidate + except OSError as exc: # permission, read-only FS, path too long, … + last_error = exc + continue + raise RuntimeError( + f"yfinance_bootstrap: no writable cache candidate succeeded. " + f"Tried: {[str(p) for p in paths]}. Last error: {last_error!r}" + ) + + +def configure_yfinance_cache(force: bool = False) -> Path: + """Point yfinance's SQLite tz cache at a lock-safe directory. + + Parameters + ---------- + force + Re-resolve even if a previous call already succeeded. Useful + in tests and long-running daemons that want to re-check after + a filesystem mount change. + + Returns + ------- + pathlib.Path + The directory yfinance will now write its cache into. + + Raises + ------ + RuntimeError + If *every* candidate path is unwritable. This is a deployment + error that should fail-fast at scraper startup rather than + producing silent "locking protocol" errors hours later. + """ + if _STATE["configured"] and not force: + return _STATE["path"] + + chosen = _first_writable(_candidate_paths()) + + try: + import yfinance as yf + except ImportError as exc: # pragma: no cover — hit only on docs builds + raise RuntimeError( + "yfinance_bootstrap.configure_yfinance_cache called but " + "`yfinance` is not installed. Install it or guard the call " + "with `if TYPE_CHECKING:`." + ) from exc + + yf.set_tz_cache_location(str(chosen)) + + _STATE["configured"] = True + _STATE["path"] = chosen + log.info( + "yfinance_bootstrap: tz cache → %s (candidates tried in order: %s)", + chosen, + [str(p) for p in _candidate_paths()], + ) + return chosen + + +def resolved_cache_dir() -> Optional[Path]: + """Return the cache directory picked by the most recent successful + :func:`configure_yfinance_cache` call, or ``None`` if the helper + has never run. Cheap enough to call from health-check endpoints.""" + return _STATE["path"] diff --git a/Scripts/data_collection/collect_data.py b/Scripts/data_collection/collect_data.py new file mode 100644 index 0000000..0ed18f5 --- /dev/null +++ b/Scripts/data_collection/collect_data.py @@ -0,0 +1,370 @@ +""" +Data collection scheduler entrypoint. + +Layered architecture: +1) Path layer: resolves project/data/log/script paths. +2) Job layer: defines cadence and execution policy. +3) Runner layer: executes scripts with retries and timeouts. +4) Scheduler layer: orchestrates due checks and state persistence. +""" + +from __future__ import annotations + +import json +import logging +import os +import subprocess +import sys +import time +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from pathlib import Path +from typing import Callable, Dict, List + + +def project_root() -> Path: + """ + Resolve repository root from Scripts/data_collection/collect_data.py. + """ + return Path(__file__).resolve().parents[2] + + +class Paths: + """ + Centralized path resolver for scripts, data, logs and runtime state. + """ + + def __init__(self) -> None: + self.root = project_root() + self.scripts_data_collection = self.root / "Scripts" / "data_collection" + self.scrapers = self.scripts_data_collection / "scrapers" + self.processors = self.scripts_data_collection / "processors" + self.data = self.root / "Data" + self.logs = self.root / "logs" / "scheduler" + self.runtime = self.root / "config" / "runtime" + self.state_file = self.runtime / "collect_data_state.json" + + def ensure_dirs(self) -> None: + self.logs.mkdir(parents=True, exist_ok=True) + self.runtime.mkdir(parents=True, exist_ok=True) + self.data.mkdir(parents=True, exist_ok=True) + + def data_dir(self, *parts: str) -> Path: + path = self.data.joinpath(*parts) + path.mkdir(parents=True, exist_ok=True) + return path + + def log_file(self) -> Path: + return self.logs / "collect_data.log" + + +class Cadence(str, Enum): + DAILY = "daily" + WEEKLY = "weekly" + MONTHLY = "monthly" + TRADING_DAILY = "trading_daily" + + +@dataclass(frozen=True) +class JobDefinition: + name: str + script_path: Path + cadence: Cadence + hour: int + minute: int + weekday: int | None = None # Monday=0, Sunday=6 for weekly cadence. + timeout_seconds: int = 60 * 30 + max_retries: int = 2 + + +class StateStore: + """ + Persistent state for idempotent scheduling (avoids duplicate runs). + + Thin adapter over :class:`Scripts.orchestration.run_state.RunState` so + that the legacy ``SchedulerService`` daemon and the new CLI share the + *same* ``config/runtime/collect_data_state.json``. All reads / writes + delegate to the orchestration layer — atomic writes, tolerant reads, + dataset-anchor mapping all come for free. + """ + + def __init__(self, state_file: Path) -> None: + # Importing here (rather than at module top) keeps this file usable + # as a standalone daemon even on environments where the full + # orchestration package is still being rolled out. + from Scripts.orchestration.run_state import RunState + + self.state_file = state_file + self._run_state = RunState(state_path=state_file) + + # ---- back-compat surface (used by SchedulerService) -------------- + + @property + def state(self) -> Dict[str, Dict[str, str]]: + """Mirror the pre-refactor ``.state`` dict for callers that touch + it directly (``self.state["last_run_keys"][...]``).""" + return {"last_run_keys": self._run_state.all_run_keys()} + + def save(self) -> None: + # RunState writes atomically after every mutation, so this is a + # no-op — kept so existing callers do not raise AttributeError. + return None + + def get_last_run_key(self, job_name: str) -> str | None: + return self._run_state.get_run_key(job_name) + + def set_last_run_key(self, job_name: str, run_key: str) -> None: + self._run_state.write_run_key(job_name, run_key) + + +class JobRunner: + """ + Script execution engine with retries and timeout controls. + """ + + def __init__(self, logger: logging.Logger) -> None: + self.logger = logger + + def run(self, job: JobDefinition) -> bool: + cmd = [sys.executable, str(job.script_path)] + + for attempt in range(1, job.max_retries + 2): + self.logger.info("Running job=%s attempt=%s cmd=%s", job.name, attempt, cmd) + try: + completed = subprocess.run( + cmd, + capture_output=True, + text=True, + timeout=job.timeout_seconds, + cwd=str(project_root()), + check=False, + ) + if completed.stdout: + self.logger.info("job=%s stdout:\n%s", job.name, completed.stdout.strip()) + if completed.stderr: + self.logger.warning("job=%s stderr:\n%s", job.name, completed.stderr.strip()) + + if completed.returncode == 0: + self.logger.info("job=%s completed successfully", job.name) + return True + + self.logger.error( + "job=%s failed with return code=%s", + job.name, + completed.returncode, + ) + except subprocess.TimeoutExpired: + self.logger.exception("job=%s timeout after %ss", job.name, job.timeout_seconds) + except Exception: + self.logger.exception("job=%s failed with unexpected exception", job.name) + + if attempt <= job.max_retries: + backoff = min(60, 10 * attempt) + self.logger.info("job=%s retrying after %ss", job.name, backoff) + time.sleep(backoff) + + return False + + +class SchedulePolicy: + """ + Time and cadence policy. Uses simple local-time checks. + """ + + @staticmethod + def is_trading_day(dt: datetime) -> bool: + # Robust baseline: Monday-Friday. Integrate exchange holidays if needed. + return dt.weekday() < 5 + + @staticmethod + def run_key(job: JobDefinition, now: datetime) -> str: + if job.cadence in (Cadence.DAILY, Cadence.TRADING_DAILY): + return now.strftime("%Y-%m-%d") + if job.cadence == Cadence.WEEKLY: + iso = now.isocalendar() + return f"{iso.year}-W{iso.week:02d}" + if job.cadence == Cadence.MONTHLY: + return now.strftime("%Y-%m") + raise ValueError(f"Unsupported cadence: {job.cadence}") + + @staticmethod + def is_due(job: JobDefinition, now: datetime, last_run_key: str | None) -> bool: + if now.hour < job.hour or (now.hour == job.hour and now.minute < job.minute): + return False + + if job.cadence == Cadence.TRADING_DAILY and not SchedulePolicy.is_trading_day(now): + return False + + if job.cadence == Cadence.WEEKLY: + if job.weekday is None: + return False + if now.weekday() != job.weekday: + return False + + current_key = SchedulePolicy.run_key(job, now) + return current_key != last_run_key + + +class SchedulerService: + """ + Long-running scheduler loop with persistent state. + """ + + def __init__( + self, + jobs: List[JobDefinition], + paths: Paths, + state: StateStore, + runner: JobRunner, + logger: logging.Logger, + now_provider: Callable[[], datetime] | None = None, + ) -> None: + self.jobs = jobs + self.paths = paths + self.state = state + self.runner = runner + self.logger = logger + self.now_provider = now_provider or datetime.now + + def tick(self) -> None: + now = self.now_provider() + for job in self.jobs: + last_key = self.state.get_last_run_key(job.name) + if not SchedulePolicy.is_due(job, now, last_key): + continue + + run_key = SchedulePolicy.run_key(job, now) + self.logger.info( + "job=%s due at %s (last_key=%s, run_key=%s)", + job.name, + now.isoformat(timespec="seconds"), + last_key, + run_key, + ) + + ok = self.runner.run(job) + if ok: + self.state.set_last_run_key(job.name, run_key) + else: + self.logger.error("job=%s exhausted retries, state not advanced", job.name) + + def run_forever(self, poll_seconds: int = 30) -> None: + self.logger.info("Scheduler started with poll_seconds=%s", poll_seconds) + while True: + try: + self.tick() + except Exception: + self.logger.exception("Unexpected scheduler tick failure") + time.sleep(poll_seconds) + + +def build_jobs(paths: Paths) -> List[JobDefinition]: + """ + Required schedule: + - GPR_index.py: monthly. + - macro_data_pipeline.py: every trading day. + - news_scraper.py: daily. + - yfinance_options_history.py: daily. + - sec_ingestion.py: weekly. + - sec_processor.py: weekly. + """ + return [ + JobDefinition( + name="gpr_monthly", + script_path=paths.scrapers / "GPR_index.py", + cadence=Cadence.MONTHLY, + hour=6, + minute=5, + ), + JobDefinition( + name="macro_trading_daily", + script_path=paths.scrapers / "macro_data_pipeline.py", + cadence=Cadence.TRADING_DAILY, + hour=6, + minute=30, + ), + JobDefinition( + name="news_daily", + script_path=paths.scrapers / "news_scraper.py", + cadence=Cadence.DAILY, + hour=7, + minute=0, + ), + JobDefinition( + name="options_daily", + script_path=paths.scrapers / "yfinance_options_history.py", + cadence=Cadence.DAILY, + hour=7, + minute=20, + ), + JobDefinition( + name="sec_ingestion_weekly", + script_path=paths.scrapers / "sec_ingestion.py", + cadence=Cadence.WEEKLY, + hour=8, + minute=0, + weekday=6, # Sunday + timeout_seconds=60 * 45, + ), + JobDefinition( + name="sec_processor_weekly", + script_path=paths.processors / "sec_processor.py", + cadence=Cadence.WEEKLY, + hour=9, + minute=0, + weekday=6, # Sunday + timeout_seconds=60 * 45, + ), + ] + + +def configure_logging(log_file: Path) -> logging.Logger: + logger = logging.getLogger("collect_data_scheduler") + logger.setLevel(logging.INFO) + logger.handlers.clear() + + formatter = logging.Formatter("%(asctime)s | %(levelname)s | %(message)s") + + file_handler = logging.FileHandler(log_file, encoding="utf-8") + stream_handler = logging.StreamHandler(sys.stdout) + file_handler.setFormatter(formatter) + stream_handler.setFormatter(formatter) + + logger.addHandler(file_handler) + logger.addHandler(stream_handler) + return logger + + +def validate_jobs(jobs: List[JobDefinition]) -> None: + missing = [str(job.script_path) for job in jobs if not job.script_path.exists()] + if missing: + raise FileNotFoundError(f"Missing job scripts: {missing}") + + +def main() -> None: + paths = Paths() + paths.ensure_dirs() + + logger = configure_logging(paths.log_file()) + logger.info("project_root=%s", paths.root) + logger.info("data_root=%s", paths.data) + logger.info("log_file=%s", paths.log_file()) + + jobs = build_jobs(paths) + validate_jobs(jobs) + + state = StateStore(paths.state_file) + runner = JobRunner(logger) + scheduler = SchedulerService( + jobs=jobs, + paths=paths, + state=state, + runner=runner, + logger=logger, + ) + scheduler.run_forever(poll_seconds=30) + + +if __name__ == "__main__": + main() diff --git a/Scripts/data_collection/processors/sec_processor.py b/Scripts/data_collection/processors/sec_processor.py new file mode 100644 index 0000000..4b16f81 --- /dev/null +++ b/Scripts/data_collection/processors/sec_processor.py @@ -0,0 +1,221 @@ +import os +import json +import glob +import logging +import argparse +from datetime import datetime +from concurrent.futures import ThreadPoolExecutor, as_completed +from langchain_ollama import ChatOllama +from dotenv import load_dotenv + +# ========================================== +# 0. Configuration +# ========================================== +parser = argparse.ArgumentParser() +parser.add_argument("--date", type=str, default=datetime.now().strftime("%Y-%m-%d")) +args = parser.parse_args() +TARGET_DATE = args.date + +BASE_DIR = os.path.abspath( + os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..", "..") +) +RAW_FOLDER = os.path.join(BASE_DIR, "Data", "1_Bronze_Raw", "SEC_Parsed_JSON", TARGET_DATE) +QDRANT_INPUT_FOLDER = os.path.join(BASE_DIR, "Data", "3_Gold_Semantic", "SEC_Insider_Trades", TARGET_DATE) +LOG_DIR = os.path.join(BASE_DIR, "logs", TARGET_DATE, "SEC_Ingestion") +# Runtime state (accession de-duplication ledger). Canonical path migrated from +# config/SEC_Processing/ -> config/runtime/ on 2026-04-22. +RUNTIME_DIR = os.path.join(BASE_DIR, "config", "runtime") +GLOBAL_REGISTRY_PATH = os.path.join(RUNTIME_DIR, "sec_processed_registry.json") + +for folder in [QDRANT_INPUT_FOLDER, LOG_DIR, RUNTIME_DIR]: + os.makedirs(folder, exist_ok=True) + +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s') +logger = logging.getLogger(__name__) + +# ========================================== +# 1. Global Registry (Real-time sync) +# ========================================== +def load_global_registry() -> set: + if os.path.exists(GLOBAL_REGISTRY_PATH): + with open(GLOBAL_REGISTRY_PATH, 'r') as f: + return set(json.load(f)) + return set() + +def save_single_to_registry(accession_no: str): + """append a single accession number to the global registry in a thread-safe way""" + registry = load_global_registry() + registry.add(accession_no) + with open(GLOBAL_REGISTRY_PATH, 'w') as f: + json.dump(list(registry), f) + +# ========================================== +# 2. Enhanced Expert Rules for Form 4 +# ========================================== +def process_form4_rules(ticker: str, parsed_data: dict) -> dict: + """business rules: zero dollar transactions with share changes are likely vesting events, planned 10b5-1 sales are less negative, and C-suite insider buys are more positive""" + owner = parsed_data.get("reporting_owner", "Unknown") + role = parsed_data.get("role", "Officer").lower() + transactions = parsed_data.get("transactions", []) + + if not transactions: return None + + net_value = 0 + total_shares_traded = 0 + is_10b5_1 = False + + for t in transactions: + val = t.get("total_value", 0) + shares = t.get("shares", 0) + total_shares_traded += shares + if t.get("is_10b5_1_planned"): is_10b5_1 = True + + if t.get("code") == "P": net_value += val + elif t.get("code") == "S": net_value -= val + + # score logic: +3 for buys, -3 for sells, +2 if C-suite buyer, -2 if C-suite seller, -1 for 10b5-1 planned sells, 0 for vesting/zero-dollar + tone_score = 0 + action_direction = "NONE" + + if net_value > 0: + tone_score = 3 + if "chief" in role or "ceo" in role: tone_score += 2 + action_direction = "BUY" + action_word = "bought" + elif net_value < 0: + if is_10b5_1: + tone_score = -1 + else: + tone_score = -3 + if "chief" in role or "ceo" in role: tone_score -= 2 + action_direction = "SELL" + action_word = "sold" + else: + # if net value is zero but shares changed, it's likely a vesting event which is generally neutral in tone + tone_score = 0 + action_direction = "ACQUIRE/VEST" + action_word = "acquired (via RSU vesting)" + + plan_text = " under a pre-planned 10b5-1 trading plan" if is_10b5_1 and net_value < 0 else "" + summary = f"{owner} ({role.title()}) of {ticker} {action_word} {total_shares_traded:,.0f} shares worth ${abs(net_value):,.2f}{plan_text}." + + return { + "summary": summary, + "transaction_date": transactions[0].get("date", "Unknown"), + "tone_score": tone_score, + "action_direction": action_direction + } + +# ========================================== +# 3. LLM Setup for 8-K +# ========================================== +# Ingestion-time SEC form parser. Uses the vanilla Llama-3 tag +# (`llama3:latest`) by default — see docs/LLM_Pool.md §1 for the two-tier +# model contract. Respect env overrides so ops can swap the model +# without code changes. +_INGESTION_MODEL = os.getenv( + "OLLAMA_INGESTION_MODEL", + os.getenv("OLLAMA_ROUTER_MODEL", "llama3:latest"), +) +try: + llm = ChatOllama( + model=_INGESTION_MODEL, + temperature=0, + base_url=os.getenv("OLLAMA_HOST", "http://localhost:11434"), + keep_alive=os.getenv("OLLAMA_KEEP_ALIVE", "30m"), + format="json", + ) +except Exception: + llm = None + +def process_8k_llm(ticker: str, text: str) -> dict: + if not llm: return None + prompt = f""" + Analyze SEC 8-K for {ticker}. Return STRICT JSON: + {{"summary": "2 sentence summary.", "transaction_date": "YYYY-MM-DD", "tone_score": , "topics": [""]}} + Text: {text[:4000]} + """ + try: + response = llm.invoke(prompt) + return json.loads(response.content) + except: + return None + +# ========================================== +# 4. Concurrent Processor +# ========================================== +def process_single_record(raw_data: dict, global_processed: set): + """for mutiple filings in the same day, we want to process them concurrently to speed up the LLM calls for 8-K analysis. The global registry is passed in to avoid duplicates.""" + meta = raw_data.get("metadata", {}) + accession_no = meta.get("accession_no") + + if accession_no in global_processed: + return None # Skip + + ticker = meta.get("ticker") + form_type = meta.get("form_type") + parsed_data = raw_data.get("parsed_data", {}) + + result = None + if form_type == "4" and parsed_data: + result = process_form4_rules(ticker, parsed_data) + topics = ["Insider Trading", "Form 4"] + elif form_type == "8-K": + text = parsed_data.get("full_markdown", "") or str(parsed_data.get("item_chunks", "")) + result = process_8k_llm(ticker, text) + topics = result.get("topics", ["8-K Event"]) if result else [] + + if not result: return None + + final_record = { + "text": result.get("summary", ""), + "metadata": { + **meta, + "transaction_date": result.get("transaction_date", "Unknown"), + "tone_score": result.get("tone_score", 0), + "action_direction": result.get("action_direction", "NONE"), + "topics": topics, + "processed_at": datetime.now().isoformat() + } + } + return (accession_no, final_record) + +def run_pipeline(): + raw_files = glob.glob(os.path.join(RAW_FOLDER, "*.jsonl")) + if not raw_files: return + + global_processed = load_global_registry() + output_file = os.path.join(QDRANT_INPUT_FOLDER, "qdrant_ready.jsonl") + + all_lines = [] + for file_path in raw_files: + with open(file_path, 'r', encoding='utf-8') as f: + all_lines.extend([json.loads(line) for line in f]) + + logger.info(f"Loaded {len(all_lines)} total records. Processing...") + + success_count = 0 + # max_workers can be tuned based on the expected number of filings and the latency of the LLM calls. For a small number of filings, 4-8 workers should be sufficient without overwhelming the system or the LLM. For larger batches, consider increasing but monitor resource usage. + with ThreadPoolExecutor(max_workers=4) as executor: + futures = {executor.submit(process_single_record, line, global_processed): line for line in all_lines} + + for future in as_completed(futures): + try: + res = future.result() + if res: + accession_no, final_record = res + # append to output file immediately to avoid data loss on crashes, and to allow partial results to be available even if the pipeline is interrupted + with open(output_file, 'a', encoding='utf-8') as f_out: + f_out.write(json.dumps(final_record, ensure_ascii=False) + '\n') + + # update global registry immediately to prevent duplicates in the same batch + save_single_to_registry(accession_no) + success_count += 1 + logger.info(f"✅ Processed: {final_record['metadata']['ticker']} | Form {final_record['metadata']['form_type']} | Tone: {final_record['metadata']['tone_score']}") + except Exception as e: + logger.error(f"Thread Error: {e}") + + logger.info(f"🎉 Processing complete! {success_count} new records added to Qdrant ready file.") + +if __name__ == "__main__": + run_pipeline() \ No newline at end of file diff --git a/Scripts/data_collection/scrapers/GPR_index.py b/Scripts/data_collection/scrapers/GPR_index.py new file mode 100644 index 0000000..9a9bba0 --- /dev/null +++ b/Scripts/data_collection/scrapers/GPR_index.py @@ -0,0 +1,227 @@ +import os +import time +import uuid +import requests +import pandas as pd +from datetime import datetime +import io +import warnings + +warnings.filterwarnings('ignore') + +# ========================================== +# 0. Dynamic Path & Directory Setup +# ========================================== +current_date = datetime.now().strftime("%Y-%m-%d") + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) +PROJECT_ROOT = os.path.abspath(os.path.join(SCRIPT_DIR, "..", "..", "..")) + +# Bronze: optional dated raw exports. Gold: dated corpus per run. +# Silver: single canonical folder — one Parquet replaces the full 2020+ series (no date subfolder). +csv_FOLDER = os.path.join(PROJECT_ROOT, "Data", "1_Bronze_Raw", "GPR_index", current_date) +SILVER_GPR_DIR = os.path.join(PROJECT_ROOT, "Data", "2_Silver_Processed", "GPR_index") +Json_FOLDER = os.path.join(PROJECT_ROOT, "Data", "3_Gold_Semantic", "GPR_index", current_date) + +os.makedirs(SILVER_GPR_DIR, exist_ok=True) +os.makedirs(Json_FOLDER, exist_ok=True) +os.makedirs(csv_FOLDER, exist_ok=True) + +# Log setting: Saved in logs/YYYY-MM-DD/ +LOG_FOLDER = os.path.join(PROJECT_ROOT, "logs", current_date) +os.makedirs(LOG_FOLDER, exist_ok=True) +LOG_FILE = os.path.join(LOG_FOLDER, "gpr_downloader.log") + +def log_print(message): + print(message) + with open(LOG_FILE, 'a', encoding='utf-8') as f: + f.write(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - {message}\n") + +log_print("System Startup: Robust GPR Downloader Initialized.") + +# ========================================== +# 1. Download & Parse GPR Data (With Fault Tolerance) +# ========================================== +GPR_EXCEL_URL = "https://www.matteoiacoviello.com/gpr_files/data_gpr_export.xls" + +def fetch_and_process_gpr(max_retries=3): + """Fetches data with a robust retry mechanism for network drops.""" + for attempt in range(1, max_retries + 1): + log_print(f"Attempt {attempt}/{max_retries}: Downloading GPR data...") + try: + response = requests.get(GPR_EXCEL_URL, timeout=30) + response.raise_for_status() + + # Read binary content into Pandas + df = pd.read_excel(io.BytesIO(response.content)) + + # Clean and standardize column names + df.columns = df.columns.str.strip().str.lower() + + if 'month' not in df.columns or 'gpr' not in df.columns: + log_print("WARNING: Target columns not found. Excel structure might have changed.") + return None + + # Drop empty rows + df = df.dropna(subset=['gpr']) + + # Convert '1985M01' to standard datetime format + df['date'] = pd.to_datetime(df['month'].astype(str).str.replace('M', '-'), errors='coerce') + df = df.dropna(subset=['date']).sort_values('date').reset_index(drop=True) + + log_print(f"Success: Loaded {len(df)} historical records.") + return df + + except Exception as e: + log_print(f"Network/Parsing Error on attempt {attempt}: {e}") + if attempt < max_retries: + log_print("Retrying in 10 seconds...") + time.sleep(10) + else: + log_print("CRITICAL: Failed to download GPR data after maximum retries. Aborting to protect existing data.") + return None + +# ========================================== +# 2. Enrich Metadata (Deltas & Moving Averages) +# ========================================== +def enrich_gpr_data(df): + log_print("Calculating MoM, YoY, and Historical Trends...") + + # CRITICAL: Calculate moving averages BEFORE truncating to 2020. + # This ensures January 2020 has accurate historical context from late 2019. + + # Month-over-Month + df['gpr_mom_pct'] = df['gpr'].pct_change(periods=1) * 100 + + # Year-over-Year + df['gpr_yoy_pct'] = df['gpr'].pct_change(periods=12) * 100 + + # Moving averages + df['gpr_3m_ma'] = df['gpr'].rolling(window=3).mean() + + # Historical percentile + df['gpr_percentile'] = df['gpr'].rank(pct=True) * 100 + + return df.round(2) + +# ========================================== +# 3. Natural Language Generation & Qdrant Formatting +# ========================================== +def generate_rag_markdown(row): + """Converts a row of data into a clean, RAG-friendly paragraph.""" + date_str = row['date'].strftime("%B %Y") + gpr = row['gpr'] + mom = row['gpr_mom_pct'] + yoy = row['gpr_yoy_pct'] + percentile = row['gpr_percentile'] + + # Handle NaN values elegantly (prevents 'nan' from leaking into text) + ma_3_text = f"{row['gpr_3m_ma']:.2f}" if pd.notna(row['gpr_3m_ma']) else "Insufficient historical data" + + # Dynamic narrative based on momentum + if pd.isna(mom): + trend_narrative = "Data initialization phase." + elif mom > 10: + trend_narrative = f"This represents a **significant escalation**, surging by {mom:.2f}% compared to the previous month." + elif mom < -10: + trend_narrative = f"This indicates a **cooling off** of geopolitical tensions, dropping by {abs(mom):.2f}% month-over-month." + else: + trend_narrative = f"The index changed by {mom:.2f}% month-over-month, showing relative stability." + + yoy_narrative = f"Compared to the same period last year, the index shifted by {yoy:.2f}%." if pd.notna(yoy) else "" + + md_text = f"""### Geopolitical Risk (GPR) Index Update: {date_str} + +**Date:** {date_str} +**GPR Score:** {gpr} + +**Summary:** +In {date_str}, the global Geopolitical Risk (GPR) Index stood at **{gpr}**. {trend_narrative} {yoy_narrative} + +**Historical Context:** +This reading sits at the **{percentile:.1f}th percentile** of all historically recorded geopolitical risk levels. A 3-month moving average of {ma_3_text} suggests the current medium-term trend. + +**Impact on Precious Metals:** +Historically, spikes in the GPR index correlate with safe-haven asset accumulation, driving up the implied volatility and spot prices of Gold (XAU) and Silver (XAG). +""" + return md_text + +# ========================================== +# 4. Save Logic (Idempotent File Generation) +# ========================================== +def save_data(df): + import json + + # 1. Truncate time window: post-2020 for RAG, Parquet, and downstream consumers + recent_df = df[df['date'] >= '2020-01-01'].copy() + log_print(f"Truncated dataset to post-2020. Generating embeddings for {len(recent_df)} months.") + + # Silver: one file, full post-2020 history — no dated subfolder (each run overwrites the canonical snapshot). + parquet_path = os.path.join(SILVER_GPR_DIR, "gpr_monthly_enriched.parquet") + try: + recent_df.to_parquet(parquet_path, index=False, engine="pyarrow") + log_print(f"SUCCESS: Silver Parquet saved to {parquet_path}") + except ImportError: + log_print( + "WARNING: pyarrow is required for Parquet export. Install with: pip install pyarrow" + ) + except Exception as e: + log_print(f"WARNING: Parquet write failed: {e}") + + md_path = os.path.join(Json_FOLDER, "gpr_narrative_corpus.md") + qdrant_jsonl_path = os.path.join(Json_FOLDER, "qdrant_gpr_input.jsonl") + + # Open in 'w' mode to Overwrite safely + with open(md_path, 'w', encoding='utf-8') as f_md, open(qdrant_jsonl_path, 'w', encoding='utf-8') as f_jsonl: + + for idx, row in recent_df.iterrows(): + year = row['date'].year + month = row['date'].month + date_str = row['date'].strftime("%Y-%m-%d") + + # Generate RAG Narrative + md_text = generate_rag_markdown(row) + f_md.write(md_text + "\n\n---\n\n") + + # Generate Deterministic ID for Qdrant (Guarantees Idempotent Upserts) + # e.g., GPR_2024_04 will always generate the exact same UUID + doc_id = str(uuid.uuid5(uuid.NAMESPACE_DNS, f"GPR_{year}_{month}")) + + # Prepare structured Qdrant Payload + qdrant_record = { + "id": doc_id, + "text": md_text, + "metadata": { + "topic": "macro_geopolitics_risk", + "title": f"GPR Index Update {year}-{month:02d}", + "publish_date": date_str, + "publish_timestamp": int(row['date'].timestamp()), + "gpr_score": row['gpr'], + "gpr_percentile": row['gpr_percentile'] + } + } + f_jsonl.write(json.dumps(qdrant_record, ensure_ascii=False) + '\n') + + log_print(f"SUCCESS: Saved NLP narrative to {md_path}") + log_print(f"SUCCESS: Saved Qdrant payload to {qdrant_jsonl_path}") + +if __name__ == "__main__": + log_print("Starting GPR Index pipeline...") + + # Step 1: Download safely + raw_df = fetch_and_process_gpr() + + if raw_df is not None: + # Step 2: Calculate metrics on ALL historical data + enriched_df = enrich_gpr_data(raw_df) + + # Step 3: Truncate and Overwrite files ONLY if everything above succeeded + save_data(enriched_df) + + # Optional: Save a CSV for quick human viewing + csv_path = os.path.join(csv_FOLDER, "gpr_preview.csv") + enriched_df.tail(24).to_csv(csv_path, index=False) + + log_print("Pipeline completed successfully! Files are ready for Vector DB Upsert.") + else: + log_print("Pipeline aborted due to upstream errors. Existing data remains untouched.") \ No newline at end of file diff --git a/Scripts/data_collection/scrapers/macro_data_pipeline.py b/Scripts/data_collection/scrapers/macro_data_pipeline.py new file mode 100644 index 0000000..9a703da --- /dev/null +++ b/Scripts/data_collection/scrapers/macro_data_pipeline.py @@ -0,0 +1,217 @@ +import logging +import os +import sys +from datetime import datetime + +import pandas as pd +from dotenv import load_dotenv +from fredapi import Fred + +load_dotenv() + +# ========================================== +# 0. Dynamic Path & Logging Setup +# ========================================== + +# 1. Setup Base Directories +BASE_DIR = os.path.abspath( + os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..", "..") +) +if BASE_DIR not in sys.path: + sys.path.insert(0, BASE_DIR) + +# ------------------------------------------------------------------ +# yfinance tz-cache redirect — MUST run before `import yfinance` so +# the SQLite lock file lands on a local filesystem (not NFS/GPFS). +# ------------------------------------------------------------------ +from Scripts.core.yfinance_bootstrap import configure_yfinance_cache # noqa: E402 +configure_yfinance_cache() + +import yfinance as yf # noqa: E402 (intentional post-bootstrap import) +today_str = datetime.now().strftime("%Y-%m-%d") + +# 2. Construct the Daily Log Folder: logs/YYYY-MM-DD/ +# This creates a clean hierarchy for automated runs +DAILY_LOG_DIR = os.path.join(BASE_DIR, "logs", today_str) +DATA_DIR = os.path.join(BASE_DIR, "Data","2_Silver_Processed", "Macro_History", today_str) +Narratives_DIR = os.path.join(BASE_DIR, "Data","3_Gold_Semantic", "Macro_Narratives", today_str) +Agent_DIR = os.path.join(BASE_DIR, "Data", "Agent_Context") + +# Ensure both directories exist +os.makedirs(DATA_DIR, exist_ok=True) +os.makedirs(DAILY_LOG_DIR, exist_ok=True) +os.makedirs(Narratives_DIR, exist_ok=True) +os.makedirs(Agent_DIR, exist_ok=True) + + +# 3. Define the Log File Path +# Since it's already in a dated folder, you can use a generic name or keep the date +log_file = os.path.join(DAILY_LOG_DIR, "macro_pipeline.log") + +# 4. Standard Logging Configuration +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(levelname)s - %(message)s', + handlers=[ + logging.FileHandler(log_file, encoding='utf-8'), + logging.StreamHandler() + ] +) +logger = logging.getLogger(__name__) + +logger.info(f"Logging initialized. Current log stored in: {DAILY_LOG_DIR}") + +class MacroDataPipeline: + def __init__(self, data_dir=DATA_DIR, narratives_dir=Narratives_DIR, agent_dir=Agent_DIR): + self.data_dir = data_dir + self.narratives_dir = narratives_dir + self.agent_dir = agent_dir + + fred_key = os.getenv("FRED_API_KEY") + if not fred_key: + raise ValueError("FRED_API_KEY not found in environment variables. Please set it in your .env file.") + self.fred = Fred(api_key=fred_key) + + self.market_tickers = { + "^GSPC": {"name": "S&P 500", "class": "Equity Index", "unit": "Points", "freq": "Daily"}, + "^IXIC": {"name": "NASDAQ", "class": "Equity Index", "unit": "Points", "freq": "Daily"}, + "^VIX": {"name": "VIX Volatility", "class": "Volatility Index", "unit": "Points", "freq": "Daily"}, + "DX-Y.NYB": {"name": "US Dollar Index", "class": "Currency", "unit": "Points", "freq": "Daily"}, + "GLD": {"name": "Gold ETF", "class": "Commodity ETF", "unit": "USD", "freq": "Daily"}, + "SLV": {"name": "Silver ETF", "class": "Commodity ETF", "unit": "USD", "freq": "Daily"} + } + + self.fred_series = { + "FEDFUNDS": {"name": "Effective Federal Funds Rate", "class": "Interest Rate", "unit": "%", "freq": "Monthly"}, + "CPIAUCSL": {"name": "CPI (Inflation)", "class": "Inflation", "unit": "Index", "freq": "Monthly"}, + "UNRATE": {"name": "Unemployment Rate", "class": "Labor Market", "unit": "%", "freq": "Monthly"} + } + + def fetch_yfinance_data(self) -> list: + logger.info("Fetching YFinance market data...") + tickers = list(self.market_tickers.keys()) + today_str = datetime.now().strftime("%Y-%m-%d") + records = [] + + try: + # threads=False to avoid potential issues with multi-threading in some environments, especially when run in Jupyter or certain servers + data = yf.download(tickers, period="5d", progress=False, threads=False) + close_data = data['Close'] if isinstance(data.columns, pd.MultiIndex) else data + + for ticker, meta in self.market_tickers.items(): + if ticker in close_data.columns: + series = close_data[ticker].dropna() + if len(series) >= 2: + last_date = series.index[-1].strftime("%Y-%m-%d") + last_price = float(series.iloc[-1]) + prev_price = float(series.iloc[-2]) + change_pct = ((last_price - prev_price) / prev_price) * 100 + + records.append({ + "retrieval_date": today_str, + "observation_date": last_date, + "symbol": ticker, + "name": meta["name"], + "asset_class": meta["class"], + "value": last_price, + "unit": meta["unit"], + "frequency": meta["freq"], + "daily_change_pct": change_pct, + "mom_change_pct": None, # Market data is daily, so MoM/YoY doesn't apply here, but we keep the fields for uniformity in the final DataFrame + "yoy_change_pct": None + }) + except Exception as e: + logger.error(f"YFinance fetching failed: {e}") + + return records + + def fetch_fred_data(self) -> list: + logger.info("Fetching FRED macro economic data...") + today_str = datetime.now().strftime("%Y-%m-%d") + records = [] + + for series_id, meta in self.fred_series.items(): + try: + data = self.fred.get_series(series_id) + data = data.dropna() + + if len(data) >= 13: + latest_value = float(data.iloc[-1]) + observation_date = data.index[-1].strftime("%Y-%m-%d") + + # Calculate MoM and YoY changes using the last 13 data points (to ensure we have the previous month and previous year values) + prev_month_value = float(data.iloc[-2]) + last_year_value = float(data.iloc[-13]) + + mom_change = ((latest_value - prev_month_value) / prev_month_value) * 100 if prev_month_value != 0 else 0 + yoy_change = ((latest_value - last_year_value) / last_year_value) * 100 if last_year_value != 0 else 0 + + records.append({ + "retrieval_date": today_str, + "observation_date": observation_date, + "symbol": series_id, + "name": meta["name"], + "asset_class": meta["class"], + "value": latest_value, + "unit": meta["unit"], + "frequency": meta["freq"], + "daily_change_pct": None, + "mom_change_pct": mom_change, + "yoy_change_pct": yoy_change + }) + except Exception as e: + logger.error(f"FRED fetched {series_id} failed: {e}") + + return records + + def run_daily_pipeline(self): + today_str = datetime.now().strftime("%Y-%m-%d") + all_records = self.fetch_yfinance_data() + self.fetch_fred_data() + + if not all_records: + logger.error("No data fetched, pipeline aborting.") + return + + # 1. generate Markdown for RAG context (LLM-friendly format) + report_lines = [f"## 📊 Macro & Market Daily Snapshot"] + report_lines.append(f"> **Generated on:** {today_str}") + report_lines.append("> **Note to LLM:** Macro indicators lag behind market data. Use YoY/MoM changes to gauge economic momentum.\n") + + report_lines.append("### 📈 Market Data (Daily)") + for rec in all_records: + if rec['frequency'] == 'Daily': + report_lines.append(f"- **[{rec['asset_class']}] {rec['name']} ({rec['symbol']})**: {rec['value']:.2f} {rec['unit']} | Change: **{rec['daily_change_pct']:+.2f}%** *(Observed: {rec['observation_date']})*") + + report_lines.append("\n### 🏛️ Macro Economic Indicators (Lagging)") + for rec in all_records: + if rec['frequency'] != 'Daily': + report_lines.append(f"- **[{rec['asset_class']}] {rec['name']} ({rec['symbol']})**: {rec['value']:.2f} {rec['unit']} | MoM: **{rec['mom_change_pct']:+.2f}%** | YoY: **{rec['yoy_change_pct']:+.2f}%** *(Observed: {rec['observation_date']})*") + + rag_context_md = "\n".join(report_lines) + + # 2. Save the Markdown context to a file (for RAG retrieval and future reference) + md_dir = os.path.join(self.narratives_dir) + os.makedirs(md_dir, exist_ok=True) + + context_file = os.path.join(md_dir, f"macro_context_{today_str}.md") + with open(context_file, "w", encoding="utf-8") as f: + f.write(rag_context_md) + logger.info(f"✅ RAG Markdown Context generated: {context_file}") + + # Additionally, save a copy as "latest_macro_context.md" for easy retrieval by the LLM without needing to know the date-specific filename + latest_file = os.path.join(self.agent_dir, "latest_macro_context.md") + with open(latest_file, "w", encoding="utf-8") as f: + f.write(rag_context_md) + + # 3. Save the structured data to a Parquet file for potential future analysis or more complex RAG queries that might benefit from structured data instead of just markdown + df = pd.DataFrame(all_records) + cols = ['retrieval_date', 'observation_date', 'symbol', 'name', 'asset_class', 'value', 'unit', 'frequency', 'daily_change_pct', 'mom_change_pct', 'yoy_change_pct'] + df = df[cols] + + parquet_file = os.path.join(self.data_dir, f"macro_snapshot_{today_str}.parquet") + df.to_parquet(parquet_file, index=False) + logger.info(f"✅ Metadata Parquet saved: {parquet_file}") + +if __name__ == "__main__": + pipeline = MacroDataPipeline() + pipeline.run_daily_pipeline() \ No newline at end of file diff --git a/Scripts/data_collection/scrapers/news_scraper.py b/Scripts/data_collection/scrapers/news_scraper.py new file mode 100644 index 0000000..040026f --- /dev/null +++ b/Scripts/data_collection/scrapers/news_scraper.py @@ -0,0 +1,352 @@ +import os +import requests +import json +import time +from datetime import datetime, timezone +from newspaper import Article +from duckduckgo_search import DDGS +import warnings +from langchain_ollama import ChatOllama +import uuid +import re +import hashlib + +warnings.filterwarnings('ignore') + +# ========================================== +# 0. Dynamic Path & Directory Setup +# ========================================== +# Ingestion-time sentiment / cleaning model. Canonical tag is `llama3:latest` +# (vanilla Meta Llama-3 8B). Respect `.env` overrides so ops can swap the +# model without code changes — see docs/LLM_Pool.md §1 for the two-tier +# model contract. +_INGESTION_MODEL = os.getenv( + "OLLAMA_INGESTION_MODEL", + os.getenv("OLLAMA_ROUTER_MODEL", "llama3:latest"), +) +print(f"Initializing local {_INGESTION_MODEL} as the data cleaning engine...") +llm = ChatOllama( + model=_INGESTION_MODEL, + temperature=0, + base_url=os.getenv("OLLAMA_HOST", "http://localhost:11434"), + keep_alive=os.getenv("OLLAMA_KEEP_ALIVE", "30m"), +) + +# 1. Get current system date (Format: YYYY-MM-DD) +current_date = datetime.now().strftime("%Y-%m-%d") + +# 2. Repo root: .../scrapers -> data_collection -> Scripts -> project root +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) +PROJECT_ROOT = os.path.abspath(os.path.join(SCRIPT_DIR, "..", "..", "..")) + +# 3. Inject date hierarchy for data: Project_Root/Data/news/YYYY-MM-DD/ +DATA_FOLDER = os.path.join(PROJECT_ROOT, "Data", "1_Bronze_Raw", "News_Scrapes", current_date) + +# 4. Define specific layers within the daily folder +RAW_FOLDER = os.path.join(DATA_FOLDER, "Raw") +FULL_TEXT_FOLDER = os.path.join(DATA_FOLDER, "Full_text") +QDRANT_INPUT_FOLDER = os.path.join(PROJECT_ROOT, "Data", "3_Gold_Semantic", "News_Qdrant", current_date) + +# 5. Maintain logs in a date-partitioned folder (logs/YYYY-MM-DD/) +LOG_FOLDER = os.path.join(PROJECT_ROOT, "logs", current_date) + +# 6. Safely create all directories (exist_ok=True prevents errors on rerun) +for folder in [RAW_FOLDER, FULL_TEXT_FOLDER, QDRANT_INPUT_FOLDER, LOG_FOLDER]: + os.makedirs(folder, exist_ok=True) + +# Use a unified log file for all runs on the current date +LOG_FILE = os.path.join(LOG_FOLDER, f"scraper_{current_date}.log") + +def log_print(message): + print(message) + with open(LOG_FILE, 'a', encoding='utf-8') as f: + f.write(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - {message}\n") + +log_print("System Startup: Dynamic directories configured. Logs are ready.") + +# ========================================== +# 1. Enhanced RAG Topics Definition +# ========================================== +MACRO_TOPICS = { + # Strict quotes applied to eliminate ambiguous abbreviations + "macro_central_banks": '("Federal Reserve" OR FOMC OR "Jerome Powell" OR "European Central Bank" OR "Bank of Japan" OR "interest rate" OR "monetary policy")', + + # Labor market and wage keywords strictly grouped + "macro_inflation_employment": '(inflation OR CPI OR PCE OR payrolls OR "labor market" OR "wage growth")', + + # Fixed the fatal space=AND bug in GDELT syntax + "macro_yields_dollar": '("yields" OR DXY OR "dollar index" OR "US dollar" OR "bond market" OR "Treasuries")', + + # Geopolitical and country-specific hotspots + "macro_geopolitics_risk": '(geopolitics OR sanctions OR "Middle East" OR Ukraine OR Taiwan)' +} + +ASSET_TOPICS = { + # Precious metals spot with strict AND logic + "asset_precious_metals_spot": '(gold OR silver) AND (price OR market OR trading OR bullion OR "safe haven")', + + # Derivatives terminology + "asset_metals_derivatives": '(gold OR silver) (COMEX OR options OR futures OR ETF OR VIX)' +} + +ALL_TOPICS = {**MACRO_TOPICS, **ASSET_TOPICS} + +# ========================================== +# 1.5 Utility: Timestamp Parser +# ========================================== +def parse_to_timestamp(date_str): + """Converts ISO 8601 or GDELT datetime strings to an integer Unix epoch.""" + if not date_str: + return int(time.time()) + try: + # Handle ISO format (e.g., 2026-04-08T21:47:44Z) + if 'T' in date_str: + clean_str = date_str.replace('Z', '+00:00') + return int(datetime.fromisoformat(clean_str).timestamp()) + # Handle raw GDELT format (e.g., 20260408214744) + else: + dt = datetime.strptime(date_str[:14], "%Y%m%d%H%M%S") + return int(dt.replace(tzinfo=timezone.utc).timestamp()) + except Exception: + # Fallback to current time if parsing fails + return int(time.time()) + +# ========================================== +# 2. Scraper & Text Extraction Logic +# ========================================== +def fetch_gdelt_metadata(query, max_retries=2): + url = "https://api.gdeltproject.org/api/v2/doc/doc" + params = {"query": query, "mode": "artlist", "format": "json", "timespan": "48h", "maxrecords": 10, "sort": "DateDesc"} + for attempt in range(max_retries): + try: + response = requests.get(url, params=params, timeout=15) + if response.status_code == 429: + time.sleep(10) + continue + response.raise_for_status() + return response.json().get('articles', []) + except Exception: + time.sleep(5) + return [] + +def _download_and_parse(url): + try: + article = Article(url) + article.download() + article.parse() + return article.text + except Exception: + return None + +def scrape_full_text(url, title=None): + text = _download_and_parse(url) + if text and len(text) > 150: + return text, "direct_success" + if title: + try: + with DDGS() as ddgs: + search_query = f'"{title}" site:finance.yahoo.com' + results = list(ddgs.text(search_query, max_results=1)) + if results and 'href' in results[0]: + yahoo_url = results[0]['href'] + fallback_text = _download_and_parse(yahoo_url) + if fallback_text and len(fallback_text) > 150: + return fallback_text, "fallback_success" + except Exception: + pass + return None, "failed" + +# ========================================== +# 3. LLM Extraction, Translation & Scoring +# ========================================== +def llm_extract_and_score(full_text, original_title): + truncated_text = full_text[:4000] + prompt = f""" + You are an expert quantitative macro-financial analyst evaluating news for a Gold/Silver Options trading desk. + + CRITICAL INSTRUCTIONS: + 1. If the text is in a foreign language, TRANSLATE the concepts to English. + 2. If the text is a cookie consent, 404 error, or completely unrelated to finance/macro/geopolitics, reply ONLY with: INVALID_CONTENT. + 3. All your outputs MUST be in English. + + Format your output EXACTLY like this: + ENGLISH_TITLE: [Translate the original title to English if foreign. If English, just copy it.] + TONE_SCORE: [Assign an integer from -5 to +5 based on the expected impact on Gold/Silver prices] + ENTITIES: [Provide a comma-separated list of 3-5 key entities explicitly mentioned] + IMPACTED_ASSETS: [Comma-separated list of broadly affected asset classes, e.g., Equities, Gold, Oil, USD] + VOLATILITY_IMPLICATION: [State ONLY 'Increase', 'Decrease', or 'Neutral' based on how this event impacts market fear/VIX] + SUMMARY: [Write a dense, 2-3 sentence financial summary. EXPLAIN the macro transmission mechanism concisely.] + + TONE SCORING RUBRIC (Impact on GOLD/SILVER): + +3 to +5 (Bullish): Fed cutting rates, inflation rising, USD weakening, geopolitical conflicts escalating. + -3 to -5 (Bearish): Fed hiking rates, inflation cooling, USD strengthening, conflicts resolving. + 0 (Neutral): Market commentary without clear directional macro drivers. + + Original Title: {original_title} + Article Text: + {truncated_text} + """ + try: + return llm.invoke(prompt).content.strip() + except Exception as e: + log_print(f"LLM Error: {e}") + return "INVALID_CONTENT" + +def parse_llm_response(response_text, original_title): + if "INVALID_CONTENT" in response_text or "SUMMARY:" not in response_text: + return None, 0, [], [], "Neutral", None + + try: + eng_title = original_title + title_match = re.search(r"ENGLISH_TITLE:\s*(.*?)\n", response_text, re.IGNORECASE) + if title_match: eng_title = title_match.group(1).strip() + + score_match = re.search(r"TONE_SCORE:\s*([-+]?\d+)", response_text, re.IGNORECASE) + tone_score = int(score_match.group(1)) if score_match else 0 + + entities = [] + entity_match = re.search(r"ENTITIES:\s*(.*?)\n", response_text, re.IGNORECASE) + if entity_match: + raw_entities = entity_match.group(1).split(',') + entities = [e.strip() for e in raw_entities if e.strip()] + + impacted_assets = [] + asset_match = re.search(r"IMPACTED_ASSETS:\s*(.*?)\n", response_text, re.IGNORECASE) + if asset_match and "none" not in asset_match.group(1).lower(): + raw_assets = asset_match.group(1).split(',') + impacted_assets = [a.strip() for a in raw_assets if a.strip()] + + vol_match = re.search(r"VOLATILITY_IMPLICATION:\s*(.*?)\n", response_text, re.IGNORECASE) + vol_implication = vol_match.group(1).strip() if vol_match else "Neutral" + + summary_start = response_text.find("SUMMARY:") + dense_summary = response_text[summary_start:].replace("SUMMARY:", "").strip() + + return eng_title, tone_score, entities, impacted_assets, vol_implication, dense_summary + except Exception as e: + return original_title, 0, [], [], "Neutral", response_text.replace("SUMMARY:", "").strip() + +# ========================================== +# 4. Main Pipeline Controller +# ========================================== +def process_and_save_to_jsonl(topic_name, query): + log_print(f"\n{'='*40}\nProcessing topic: {topic_name}\n{'='*40}") + articles = fetch_gdelt_metadata(query) + + if not articles: + return + + # Implementing a robust deduplication mechanism using URL slugs and cleaned titles + seen_signatures = set() + unique_articles = [] + + for item in articles: + url = item.get('url', '') + title = item.get('title', '').lower() + + # 1. Extract a URL slug (last part of the URL path) to use as a unique identifier + slug_match = re.search(r'/([^/]+-[-a-zA-Z0-9]+)/?$', url) + url_slug = slug_match.group(1) if slug_match else "" + + # 2. Clean the title (remove suffixes, non-alphanumeric characters) + clean_title = re.sub(r'[^a-z0-9]', '', title.split('|')[0].strip()) + + # 3. Generate a unique signature for the article + article_signature = url_slug if url_slug else clean_title + + if article_signature not in seen_signatures: + seen_signatures.add(article_signature) + unique_articles.append(item) + else: + log_print(f" [DEDUPLICATED] Skipping duplicate: {title[:40]}...") + + # After deduplication, we proceed with the unique set of articles + articles = unique_articles + + if not articles: + log_print(f"[{topic_name}] No data fetched for this query.") + return + + raw_output_file = os.path.join(RAW_FOLDER, f"raw_gdelt_{topic_name}.jsonl") + with open(raw_output_file, 'a', encoding='utf-8') as f_raw: + for item in articles: + f_raw.write(json.dumps(item, ensure_ascii=False) + '\n') + + full_text_output_file = os.path.join(FULL_TEXT_FOLDER, f"full_text_{topic_name}.jsonl") + qdrant_output_file = os.path.join(QDRANT_INPUT_FOLDER, f"qdrant_{topic_name}_processed.jsonl") + + stats = {"total": len(articles), "scraped": 0, "llm_passed": 0, "llm_discarded": 0} + current_time_iso = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") + + with open(full_text_output_file, 'a', encoding='utf-8') as f_full, \ + open(qdrant_output_file, 'a', encoding='utf-8') as f_qdrant: + + for item in articles: + target_url = item.get('url') + article_title = item.get('title', '') + + # Standardize date for Vector DB filtering + publish_date = item.get('urldatetime', '') + if not publish_date: + publish_date = current_time_iso + + # Convert string date to Integer Unix Epoch for fast DB range filters + publish_timestamp = parse_to_timestamp(publish_date) + + full_text, status = scrape_full_text(target_url, title=article_title) + if status == "failed": + continue + stats["scraped"] += 1 + + full_text_record = { + "url": target_url, + "title": article_title, + "publish_date": publish_date, + "full_text": full_text + } + f_full.write(json.dumps(full_text_record, ensure_ascii=False) + '\n') + + llm_response = llm_extract_and_score(full_text, article_title) + + # Unpack the newly expanded metadata fields + english_title, tone_score, entities_list, impacted_assets, vol_implication, dense_summary = parse_llm_response(llm_response, article_title) + + if not dense_summary: + log_print(f" [DISCARDED] Invalid content: {article_title[:40]}...") + stats["llm_discarded"] += 1 + continue + + stats["llm_passed"] += 1 + log_print(f" [KEPT] Tone: {tone_score:2d} | Volatility: {vol_implication[:8]} | {english_title[:40]}...") + + # Clean vector text (Removed "Entities:" prefix to prevent embedding pollution) + clean_vector_text = f"{english_title}. {dense_summary}" + + doc_id = str(uuid.uuid5(uuid.NAMESPACE_URL, target_url)) + qdrant_record = { + "id": doc_id, + "text": clean_vector_text, + "metadata": { + "topic": topic_name, + "title": english_title, + "original_title": article_title, + "publish_date": publish_date, + "publish_timestamp": publish_timestamp, + "source": item.get('domain', 'Unknown Source'), + "url": target_url, + "entities": entities_list, + "impacted_assets": impacted_assets, + "volatility_implication": vol_implication, + "llm_tone_score": tone_score + } + } + f_qdrant.write(json.dumps(qdrant_record, ensure_ascii=False) + '\n') + + log_print(f"Topic [{topic_name}] -> Fetched: {stats['total']} | Scraped: {stats['scraped']} | Saved: {stats['llm_passed']} | Discarded: {stats['llm_discarded']}") + log_print("-" * 40) + +if __name__ == "__main__": + for topic_name, query in ALL_TOPICS.items(): + process_and_save_to_jsonl(topic_name, query) + time.sleep(5) + log_print("\n[+] All data cleaning and purification complete. Files archived successfully!") \ No newline at end of file diff --git a/Scripts/data_collection/scrapers/sec_ingestion.py b/Scripts/data_collection/scrapers/sec_ingestion.py new file mode 100644 index 0000000..8e9f53b --- /dev/null +++ b/Scripts/data_collection/scrapers/sec_ingestion.py @@ -0,0 +1,344 @@ +import os +import sys +import json +import time +import requests +import logging +import glob +import re +import xml.etree.ElementTree as ET +from datetime import datetime, timedelta +from bs4 import BeautifulSoup +from dotenv import load_dotenv +from markdownify import markdownify as md +from functools import wraps + +# ========================================== +# 0. Dynamic Path & Industrial Logging +# ========================================== +# Repo root: .../scrapers -> data_collection -> Scripts -> project root +BASE_DIR = os.path.abspath( + os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..", "..") +) +# Make Scripts.core.universe importable whether this file is executed directly +# (`python sec_ingestion.py`) or as a module (`python -m ...sec_ingestion`). +if BASE_DIR not in sys.path: + sys.path.insert(0, BASE_DIR) + +today_str = datetime.now().strftime("%Y-%m-%d") + +RAW_FOLDER = os.path.join(BASE_DIR, "Data", "1_Bronze_Raw", "SEC_Parsed_JSON", today_str) +# LOG_DIR still uses the SEC_Ingestion path prefix INSIDE logs/{date}/ — that is +# a log-channel name, not a config folder. The retired config/SEC_Ingestion/ +# folder is no longer created here; universe + reference maps are now resolved +# entirely through Scripts.core.universe. +LOG_DIR = os.path.join(BASE_DIR, "logs", today_str, "SEC_Ingestion") + +for folder in [RAW_FOLDER, LOG_DIR]: + os.makedirs(folder, exist_ok=True) + +load_dotenv(dotenv_path=os.path.join(BASE_DIR, '.env')) + +progress_log_file = os.path.join(LOG_DIR, f"ingestion_progress_{today_str}.log") +logger = logging.getLogger("ProgressLogger") +logger.setLevel(logging.INFO) +formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') + +fh_prog = logging.FileHandler(progress_log_file, encoding='utf-8') +sh_prog = logging.StreamHandler() +fh_prog.setFormatter(formatter) +sh_prog.setFormatter(formatter) +logger.addHandler(fh_prog) +logger.addHandler(sh_prog) + +# SEC Official User-Agent Required! +SEC_USER_AGENT = os.getenv("SEC_USER_AGENT", "DataEngineer (bot@example.com)") +SEC_HEADERS = { + 'User-Agent': SEC_USER_AGENT, + 'Accept-Encoding': 'gzip, deflate' +} + +# ========================================== +# 1. Resilient Network & Local CIK Mapping +# ========================================== +def retry_on_exception(retries=3, delay=2): + """A decorator to retry a function on exceptions, with exponential backoff.""" + def decorator(func): + @wraps(func) + def wrapper(*args, **kwargs): + for i in range(retries): + try: + return func(*args, **kwargs) + except Exception as e: + if i < retries - 1: + wait_time = delay * (2 ** i) + logger.warning(f"Network issue/429 triggered: {e}. Retrying in {wait_time}s...") + time.sleep(wait_time) + else: + logger.error(f"Failed after {retries} retries.") + raise e + return wrapper + return decorator + +def load_local_cik_map() -> dict: + """Thin shim retained for backward compat with external callers. + + Delegates to ``Scripts.core.universe.UniverseLoader.cik_map()``, which reads + ``config/reference/ticker_to_cik.json``. + """ + try: + from Scripts.core.universe import universe as _universe + mapping = _universe.cik_map() + logger.info(f"✅ Successfully loaded {len(mapping)} CIK mappings via UniverseLoader") + return mapping + except Exception as e: + logger.error(f"❌ UniverseLoader.cik_map() failed: {e}. Run SEC_generate_cik_map.py first.") + return {} + +def load_tickers(file_name: str) -> list: + """Thin shim retained for backward compat. + + Maps the legacy file name ``SEC_tickers.json`` to + ``universe.get('sec.filers')``; anything else returns an empty list with a + warning. + """ + try: + from Scripts.core.universe import universe as _universe + except Exception as e: + logger.error(f"UniverseLoader unavailable: {e}") + return [] + if file_name.lower() in ("sec_tickers.json", "equity_single_name.json"): + tickers = _universe.get("sec.filers") + logger.info(f"Loaded {len(tickers)} tickers via UniverseLoader (sec.filers)") + return tickers + logger.warning( + f"load_tickers({file_name}): no universe-role mapping for this legacy " + "filename; returning empty list. Migrate the caller to universe.get(role)." + ) + try: + with open(file_name, 'r', encoding='utf-8') as f: + return json.load(f) + except Exception as e: + logger.error(f"Error loading {file_name}: {e}") + return [] + +# ========================================== +# 2. Parsers (Unchanged Routing Logic) +# ========================================== +@retry_on_exception() +def fetch_and_parse_8k_html(url: str) -> dict: + time.sleep(0.15) + response = requests.get(url, headers=SEC_HEADERS, timeout=15) + response.raise_for_status() + soup = BeautifulSoup(response.content, 'html.parser') + + for tag in soup(['script', 'style', 'head', 'title', 'meta']): + tag.decompose() + + html_content = str(soup) + md_text = md(html_content, strip=['a', 'img'], heading_style="ATX") + md_text = re.sub(r'\n{3,}', '\n\n', md_text) + + item_pattern = re.compile( + r'(Item\s+\d\.\d{2}.*?)(?=\nItem\s+\d\.\d{2}|\nSignatures?|\nS I G N A T U R E S|$)', + re.IGNORECASE | re.DOTALL + ) + + chunks = {} + for match in item_pattern.finditer(md_text): + chunk_text = match.group(1).strip() + item_num_match = re.search(r'Item\s+(\d\.\d{2})', chunk_text, re.IGNORECASE) + if item_num_match: + chunks[item_num_match.group(1)] = chunk_text + + if not chunks: + return {"is_chunked": False, "full_markdown": md_text} + + return {"is_chunked": True, "item_chunks": chunks} + +@retry_on_exception() +def fetch_and_parse_form4_xml(url: str) -> dict: + raw_xml_url = re.sub(r'/xsl[^/]+/', '/', url) + time.sleep(0.15) + response = requests.get(raw_xml_url, headers=SEC_HEADERS, timeout=15) + response.raise_for_status() + root = ET.fromstring(response.content) + + def get_text(element, path, default=""): + node = element.find(path) + return node.text if node is not None else default + + reporting_owner = get_text(root, ".//reportingOwnerId/rptOwnerName", "Unknown") + title = get_text(root, ".//reportingOwnerRelationship/officerTitle", "") + if not title: + is_director = get_text(root, ".//reportingOwnerRelationship/isDirector") == "true" + title = "Director" if is_director else "Other" + + is_10b5_1 = False + for footnote in root.findall(".//footnotes/footnote"): + if footnote.text and "10b5-1" in footnote.text: + is_10b5_1 = True + break + + transactions = [] + for trans in root.findall(".//nonDerivativeTransaction"): + date = get_text(trans, ".//transactionDate/value") + code = get_text(trans, ".//transactionCoding/transactionCode") + shares = float(get_text(trans, ".//transactionAmounts/transactionShares/value", "0")) + price = float(get_text(trans, ".//transactionAmounts/transactionPricePerShare/value", "0")) + acq_disp = get_text(trans, ".//transactionAmounts/transactionAcquiredDisposedCode/value") + post_shares = float(get_text(trans, ".//postTransactionAmounts/sharesOwnedFollowingTransaction/value", "0")) + + if code == "P": direction = "STRONG_BUY (Open Market)" + elif code == "S": direction = "STRONG_SELL (Open Market)" + elif code == "M": direction = "VESTING (Options/RSU)" + elif code == "F": direction = "TAX_WITHHOLDING" + else: direction = f"OTHER ({acq_disp})" + + transactions.append({ + "date": date, "code": code, "direction": direction, + "shares": shares, "price": price, "total_value": shares * price, + "post_transaction_shares": post_shares, "is_10b5_1_planned": is_10b5_1 + }) + + return {"reporting_owner": reporting_owner, "role": title, "transactions": transactions} + +# ========================================== +# 3. Pipeline Core (Direct EDGAR Search) +# ========================================== +@retry_on_exception() +def get_sec_filings_by_cik(cik: str, start_date_str: str, end_date_str: str) -> list: + """use CIK to directly query SEC EDGAR for recent 4 and 8-K filings, with date filtering""" + url = f"https://data.sec.gov/submissions/CIK{cik}.json" + time.sleep(0.15) + response = requests.get(url, headers=SEC_HEADERS, timeout=15) + response.raise_for_status() + + data = response.json() + recent = data.get("filings", {}).get("recent", {}) + if not recent: return [] + + filings = [] + # EDGAR provides filings in reverse chronological order, so we can stop once we go past the date range + for idx, form in enumerate(recent.get("form", [])): + filed_at = recent["filingDate"][idx] + + # filter by date range and form type + if form in ["4", "8-K"] and start_date_str <= filed_at <= end_date_str: + acc_no_with_dashes = recent["accessionNumber"][idx] + acc_no_clean = acc_no_with_dashes.replace('-', '') + primary_doc = recent["primaryDocument"][idx] + + # SEC apends the CIK in the URL path, but it should be without leading zeros + cik_stripped = str(int(cik)) + url_doc = f"https://www.sec.gov/Archives/edgar/data/{cik_stripped}/{acc_no_clean}/{primary_doc}" + + filings.append({ + "formType": form, + "filedAt": filed_at, + "accessionNo": acc_no_with_dashes, + "linkToFilingDetails": url_doc + }) + + return filings + +def process_sec_data(ticker: str, cik: str): + logger.info(f"Processing: {ticker} (CIK: {cik})") + + start_date = (datetime.now() - timedelta(days=7)).strftime('%Y-%m-%d') + end_date = datetime.now().strftime('%Y-%m-%d') + + try: + filings = get_sec_filings_by_cik(cik, start_date, end_date) + if not filings: + logger.info(f"[{ticker}] No 4 or 8-K filings found in the past 7 days.") + return + + output_file = os.path.join(RAW_FOLDER, f"{ticker}.jsonl") + + with open(output_file, 'a', encoding='utf-8') as f_out: + for filing in filings: + form_type = filing.get('formType', '') + url = filing.get('linkToFilingDetails', '') + + record = { + "metadata": { + "ticker": ticker, + "form_type": form_type, + "filed_at": filing.get('filedAt', ''), + "accession_no": filing.get('accessionNo', ''), + "url": url, + "ingested_at": datetime.now().isoformat() + } + } + + if form_type == "4": + parsed_xml_data = fetch_and_parse_form4_xml(url) + if not parsed_xml_data: continue + record["parsed_data"] = parsed_xml_data + record["raw_text"] = "XML_PARSED_SUCCESSFULLY" + elif form_type == "8-K": + parsed_8k_data = fetch_and_parse_8k_html(url) + if not parsed_8k_data: continue + + record["parsed_data"] = parsed_8k_data + record["raw_text"] = "8K_PARSED_INTO_MARKDOWN_CHUNKS" + + f_out.write(json.dumps(record, ensure_ascii=False) + '\n') + + except Exception as e: + logger.error(f"Pipeline Error for {ticker}: {e}") + +# ========================================== +# 4. Statistics Engine +# ========================================== +def generate_daily_summary(): + logger.info("Generating Summary Report...") + summary = {"date": today_str, "total_filings": 0, "ticker_breakdown": {}} + + for file_path in glob.glob(os.path.join(RAW_FOLDER, "*.jsonl")): + ticker = os.path.splitext(os.path.basename(file_path))[0] + counts = {"4": 0, "8-K": 0} + + with open(file_path, 'r', encoding='utf-8') as f: + for line in f: + item = json.loads(line) + ftype = item["metadata"]["form_type"] + if ftype in counts: counts[ftype] += 1 + summary["total_filings"] += 1 + + summary["ticker_breakdown"][ticker] = counts + + summary_path = os.path.join(RAW_FOLDER, "_SUMMARY.json") + with open(summary_path, 'w', encoding='utf-8') as f: + json.dump(summary, f, indent=4) + logger.info(f"Summary generated at {summary_path}") + +# ========================================== +# Execution +# ========================================== +if __name__ == "__main__": + if SEC_USER_AGENT == "DataEngineer (bot@example.com)": + logger.warning("⚠️ WARNING: You are using the default SEC_USER_AGENT. Please set a custom User-Agent in your .env file to avoid being blocked by SEC.") + + # Universe + reference maps are resolved through Scripts.core.universe — + # the single source of truth (config/universe/ + config/reference/). + from Scripts.core.universe import universe as _universe + nasdaq_targets = _universe.get("sec.filers") + logger.info(f"✅ Loaded {len(nasdaq_targets)} SEC filers via UniverseLoader (role=sec.filers)") + + if nasdaq_targets: + ticker_to_cik = _universe.cik_map() + + if not ticker_to_cik: + logger.error("❌ CIK mapping is empty. Cannot proceed with SEC data ingestion.") + exit(1) + + for sym in nasdaq_targets: + cik = ticker_to_cik.get(sym) + if not cik: + logger.warning(f"Could not find CIK for ticker {sym}. Skipping.") + continue + process_sec_data(sym, cik) + + generate_daily_summary() \ No newline at end of file diff --git a/Scripts/data_collection/scrapers/yfinance_options_history.py b/Scripts/data_collection/scrapers/yfinance_options_history.py new file mode 100644 index 0000000..7153214 --- /dev/null +++ b/Scripts/data_collection/scrapers/yfinance_options_history.py @@ -0,0 +1,276 @@ +import logging +import os +import sys +import time +from datetime import datetime +from typing import Dict, Any, List + +import numpy as np +import pandas as pd + +# ========================================== +# 0. Dynamic Path & Logging Configuration +# ========================================== +# Resolve absolute paths based on the current script location +BASE_DIR = os.path.abspath( + os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..", "..") +) +# Make Scripts.core.* importable when executed directly (python Scripts/...). +if BASE_DIR not in sys.path: + sys.path.insert(0, BASE_DIR) + +# ------------------------------------------------------------------ +# yfinance timezone-cache redirect — MUST run before `import yfinance` +# so the SQLite tz DB lands on a lock-safe filesystem (not NFS/GPFS). +# See docs/test/2026-04-22/ingestion_and_query_runtime_failures.md. +# ------------------------------------------------------------------ +from Scripts.core.yfinance_bootstrap import configure_yfinance_cache # noqa: E402 +configure_yfinance_cache() + +import yfinance as yf # noqa: E402 (intentional post-bootstrap import) + +DATA_DIR = os.path.join(BASE_DIR, "Data","2_Silver_Processed", "Options_Market_Data") +LOG_DIR = os.path.join(BASE_DIR, "logs") + +os.makedirs(DATA_DIR, exist_ok=True) +os.makedirs(LOG_DIR, exist_ok=True) + +today_str = datetime.now().strftime("%Y-%m-%d") +log_file = os.path.join(LOG_DIR, today_str,f"options_scraper_{today_str}.log") +os.makedirs(os.path.dirname(log_file), exist_ok=True) + +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(levelname)s - %(message)s', + handlers=[ + logging.FileHandler(log_file, encoding='utf-8'), + logging.StreamHandler() + ] +) +logger = logging.getLogger(__name__) + +class YFinanceClient: + """ + Yahoo Finance Options & Market Data Client + Optimized for RAG Tool Calling with derived financial metrics. + """ + + def __init__(self): + self.request_delay = 1.0 # 1 second delay between requests to prevent IP ban + + def get_stock_info(self, symbol: str) -> Dict[str, Any]: + """Fetch basic stock information and latest quote.""" + try: + ticker = yf.Ticker(symbol) + info = ticker.info + time.sleep(self.request_delay) + + return { + 'symbol': symbol, + 'current_price': info.get('currentPrice', info.get('regularMarketPrice', 0)), + 'volume': info.get('volume', 0), + 'market_cap': info.get('marketCap', 0), + } + except Exception as e: + logger.error(f"Failed to fetch stock info for {symbol}: {e}") + return {} + + def get_options_expirations(self, symbol: str) -> List[str]: + """Fetch available option expiration dates.""" + try: + ticker = yf.Ticker(symbol) + expirations = ticker.options + time.sleep(self.request_delay) + + if not expirations: + logger.warning(f"No option expiration dates found for {symbol}") + return [] + + exp_dates = [str(exp) for exp in expirations] + exp_dates.sort() + return exp_dates + except Exception as e: + logger.error(f"Failed to fetch expirations for {symbol}: {e}") + return [] + + def get_options_chain(self, symbol: str, expiration_date: str = None) -> Dict[str, Any]: + """Fetch the full options chain for a specific expiration date.""" + try: + ticker = yf.Ticker(symbol) + if not expiration_date: + expirations = ticker.options + if not expirations: + return {} + expiration_date = str(expirations[0]) + + options_chain = ticker.option_chain(expiration_date) + time.sleep(self.request_delay) + + if options_chain is None: + return {} + + def process_chain(df, opt_type): + data = [] + if not df.empty: + for _, row in df.iterrows(): + data.append({ + 'contract_symbol': str(row.get('contractSymbol', '')), + 'strike': float(row['strike']), + 'last_price': float(row['lastPrice']) if pd.notna(row['lastPrice']) else 0, + 'bid': float(row['bid']) if pd.notna(row['bid']) else 0, + 'ask': float(row['ask']) if pd.notna(row['ask']) else 0, + 'volume': int(row['volume']) if pd.notna(row['volume']) else 0, + 'open_interest': int(row['openInterest']) if pd.notna(row['openInterest']) else 0, + 'implied_volatility': float(row['impliedVolatility']) if pd.notna(row['impliedVolatility']) else 0, + 'in_the_money': bool(row.get('inTheMoney', False)) + }) + return data + + return { + 'symbol': symbol, + 'expiration_date': expiration_date, + 'calls': process_chain(options_chain.calls, 'call'), + 'puts': process_chain(options_chain.puts, 'put') + } + except Exception as e: + logger.error(f"Failed to fetch options chain for {symbol}: {e}") + return {} + + def snapshot_daily_options_chain(self, symbol: str) -> bool: + """ + Automated daily snapshot script with advanced derived metrics. + """ + today = datetime.now() + today_str = today.strftime("%Y-%m-%d") + + # [Architecture Update 1]: Resolve the output path through the + # storage-strategy-aware UniversePaths helper. The active strategy + # defaults to ``legacy`` (see config/pipeline/options_history.json), + # which produces the EXACT same path as the pre-migration code + # ({DATA_DIR}/{today_str}/{SYMBOL}_options_{today_str}.parquet). Flip + # `storage.strategy` to `hive_v1` or `monthly_rollup` to migrate — no + # code change needed here. + try: + from Scripts.core.universe import paths as _paths + file_path_obj = _paths.options_parquet_path(symbol, today_str) + file_path = str(file_path_obj) + daily_folder = os.path.dirname(file_path) + except Exception as _paths_err: + logger.warning( + f"UniversePaths unavailable ({_paths_err}); using legacy path layout." + ) + daily_folder = os.path.join(DATA_DIR, today_str) + file_path = os.path.join(daily_folder, f"{symbol}_options_{today_str}.parquet") + os.makedirs(daily_folder, exist_ok=True) + + logger.info(f"Starting options snapshot for {symbol} ({today_str})...") + + # 1. Fetch underlying price + stock_info = self.get_stock_info(symbol) + current_price = stock_info.get('current_price', 0) + if current_price == 0: + logger.error(f"Unable to fetch current price for {symbol}. Snapshot aborted.") + return False + + # 2. Fetch expirations + expirations = self.get_options_expirations(symbol) + if not expirations: + return False + + all_options_data = [] + + # 3. Loop through chains (Limit to near-term expirations) + for exp in expirations[:10]: + try: + exp_date_obj = datetime.strptime(exp, "%Y-%m-%d") + dte = (exp_date_obj - today).days + if dte < 0: dte = 0 + + chain = self.get_options_chain(symbol, exp) + + for call in chain.get('calls', []): + call.update({ + 'symbol': symbol, 'underlying_price': current_price, + 'expiration': exp, 'dte': dte, + 'option_type': 'call', 'snapshot_date': today_str + }) + all_options_data.append(call) + + for put in chain.get('puts', []): + put.update({ + 'symbol': symbol, 'underlying_price': current_price, + 'expiration': exp, 'dte': dte, + 'option_type': 'put', 'snapshot_date': today_str + }) + all_options_data.append(put) + + except Exception as e: + logger.warning(f"Error processing expiration {exp} for {symbol}: {e}") + continue + + if not all_options_data: + logger.warning(f"No valid options data retrieved for {symbol}.") + return False + + # 4. Convert to DataFrame for advanced vectorized calculations + df = pd.DataFrame(all_options_data) + + # [Architecture Update 2]: Calculate Derived Metrics for LLM Reasoning + # A. Moneyness Percentage: How far is the strike from the current price? + df['moneyness_pct'] = (abs(df['strike'] - df['underlying_price']) / df['underlying_price']) * 100 + + # B. Bid-Ask Spread Percentage: Measure of liquidity cost (safely avoid division by zero) + df['spread_pct'] = 0.0 + mask_ask_gt_zero = df['ask'] > 0 + df.loc[mask_ask_gt_zero, 'spread_pct'] = ((df.loc[mask_ask_gt_zero, 'ask'] - df.loc[mask_ask_gt_zero, 'bid']) / df.loc[mask_ask_gt_zero, 'ask']) * 100 + + # C. Liquidity Flag: True if it has decent volume, open interest, and valid bid + df['is_liquid'] = (df['volume'] >= 50) & (df['open_interest'] >= 100) & (df['bid'] > 0) + + # Reorder columns to group related metrics together + cols = ['snapshot_date', 'symbol', 'underlying_price', 'contract_symbol', 'option_type', + 'strike', 'expiration', 'dte', 'moneyness_pct', + 'last_price', 'bid', 'ask', 'spread_pct', + 'volume', 'open_interest', 'implied_volatility', 'in_the_money', 'is_liquid'] + df = df[[c for c in cols if c in df.columns]] + + # Save into the daily subfolder (path already resolved above via UniversePaths). + df.to_parquet(file_path, index=False) + + # Log how many contracts are actually highly liquid + liquid_count = df['is_liquid'].sum() + logger.info(f"✅ Archived {symbol} -> Total: {len(df)} | Liquid: {liquid_count} | Path: {file_path}") + return True + +if __name__ == "__main__": + client = YFinanceClient() + + # [Architecture Update 3]: Universe is now driven by + # config/universe/_manifest.json via Scripts.core.universe. + # * role `options.scrape` = equity.single_name ∪ etf.broad_market ∪ etf.commodity (~53 tickers) + # * role `etf.all` = etf.broad_market ∪ etf.commodity (5 tickers, legacy default) + # The active role is read from config/pipeline/options_history.json + # (`universe_role`), with `etf.all` as a safe fallback if the loader or + # the config is unavailable — this preserves the pre-migration behaviour + # byte-for-byte when run in degraded mode. + try: + from Scripts.core.universe import universe as _universe, pipelines as _pipelines + _role = (_pipelines.load("options_history") or {}).get("universe_role", "etf.all") + target_symbols = _universe.get(_role) + logger.info( + f"Initiating daily options data pipeline for {len(target_symbols)} symbols " + f"(universe_role='{_role}')." + ) + except Exception as _universe_err: + logger.warning( + f"UniverseLoader unavailable ({_universe_err}); " + "falling back to hard-coded ETF baseline [SPY, QQQ, IWM, GLD, SLV]." + ) + target_symbols = ["SPY", "QQQ", "IWM", "GLD", "SLV"] + logger.info(f"Initiating daily options data pipeline for {len(target_symbols)} symbols (fallback mode).") + + for symbol in target_symbols: + client.snapshot_daily_options_chain(symbol) + time.sleep(2) + + logger.info("Pipeline execution completed successfully.") \ No newline at end of file diff --git a/Scripts/main.py b/Scripts/main.py new file mode 100644 index 0000000..2d600ae --- /dev/null +++ b/Scripts/main.py @@ -0,0 +1,13 @@ +"""Thin CLI shell — delegates to ``Scripts.orchestration.cli``. + +Kept for backward compatibility with existing shortcuts like +``python Scripts/main.py ingest --dry-run``. New invocations should +prefer ``python -m Scripts ingest --dry-run`` which is exactly +equivalent but stays robust under packaging / PyInstaller. +""" +from __future__ import annotations + +from Scripts.orchestration.cli import main + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Scripts/observability/__init__.py b/Scripts/observability/__init__.py new file mode 100644 index 0000000..f09b423 --- /dev/null +++ b/Scripts/observability/__init__.py @@ -0,0 +1,20 @@ +"""Observability primitives — structured logging + unified audit paths. + +Kept dependency-free so that every script / agent can import it at boot +without paying the cost of heavy libraries. +""" +from Scripts.observability.audit import ( + audit_path, + configure_root_logger, + current_run_id, + get_audit_logger, + start_run, +) + +__all__ = [ + "audit_path", + "configure_root_logger", + "current_run_id", + "get_audit_logger", + "start_run", +] diff --git a/Scripts/observability/audit.py b/Scripts/observability/audit.py new file mode 100644 index 0000000..1570e7a --- /dev/null +++ b/Scripts/observability/audit.py @@ -0,0 +1,264 @@ +""" +Unified logging + audit-path helpers. + +Motivation +---------- +Before this module the project wrote logs into a zoo of top-level +folders (``logs/retrieval/``, ``logs/query_transform/``, ``logs/router_e2e/``, +``logs/Parquet_Query/``, ``logs/scheduler/``, …). Investigating a single +production incident meant stitching together four timestamp-matched +files by hand. + +This module converges everything on two well-known layouts: + +1. **Run-scoped logs** (for *one* orchestrator invocation / CLI session) + + :: + + logs/runs/{YYYY-MM-DD}/{run_id}/ + orchestrator.log # root logger, human-readable + retrieval.jsonl # per-module audit trail + query_transform.jsonl + router_e2e.jsonl + sql_range.jsonl + + Every orchestrator invocation gets its own ``run_id`` folder, making + "what happened between 15:09 and 15:12 on 2026-04-22?" trivial to + answer with ``ls -R``. + +2. **Daemon / long-lived logs** (for the scheduler that does not have a + single-shot boundary) + + :: + + logs/scheduler/collect_data.log # existing, back-compat + logs/daemon/{YYYY-MM-DD}.log # rolled daily + +Migration path +-------------- +* ``audit_path(module, anchor)`` returns the new unified path; existing + modules can switch one call-site at a time. +* ``get_audit_logger(name, module)`` wraps ``logging.getLogger`` and + attaches a ``FileHandler`` pointed at the unified path. Call it once + per module and reuse the returned logger. +* Legacy paths still work — nothing under ``logs/`` is deleted. + +Design constraints +------------------ +* **Stdlib only** — imported during CLI / daemon bootstrap before any + heavy dependencies. +* **Windows-safe** — file handles are opened with ``encoding="utf-8"`` + and ``delay=True`` so that transient permission issues do not crash + the scheduler mid-tick. +* **Idempotent** — calling ``configure_root_logger()`` twice replaces + handlers instead of stacking them (important for Jupyter / pytest). +""" +from __future__ import annotations + +import contextvars +import logging +import os +import sys +import uuid +from datetime import date, datetime +from pathlib import Path +from typing import Optional + + +# --------------------------------------------------------------------------- +# Path layout +# --------------------------------------------------------------------------- + + +def _project_root() -> Path: + # Scripts/observability/audit.py -> parents[2] + return Path(__file__).resolve().parents[2] + + +def _logs_root() -> Path: + return _project_root() / "logs" + + +# --------------------------------------------------------------------------- +# run_id — one per orchestrator / CLI invocation +# --------------------------------------------------------------------------- + + +_RUN_ID: contextvars.ContextVar[Optional[str]] = contextvars.ContextVar( + "audit_run_id", default=None +) + + +def start_run(tag: str = "session") -> str: + """Mint and register a ``run_id`` for this process. + + Returns + ------- + str + ``"{YYYYMMDD}_{HHMMSS}_{tag}_{short-uuid}"``. Short enough to be + a filesystem-safe folder name, long enough to be unique under + millisecond-scale re-runs. + """ + rid = f"{datetime.now():%Y%m%d_%H%M%S}_{tag}_{uuid.uuid4().hex[:6]}" + _RUN_ID.set(rid) + return rid + + +def current_run_id() -> str: + """Return the active ``run_id``. Starts a fresh one if nothing has + been registered yet — this keeps ad-hoc scripts (notebooks, tests) + from needing to remember to call ``start_run`` first. + """ + rid = _RUN_ID.get() + if rid: + return rid + return start_run(tag="adhoc") + + +# --------------------------------------------------------------------------- +# Paths +# --------------------------------------------------------------------------- + + +def audit_path( + module: str, + anchor: Optional[date] = None, + *, + filename: Optional[str] = None, + scoped_by_run: bool = True, +) -> Path: + """Return the canonical path for a module's audit file. + + Parameters + ---------- + module + Logical module name — ``"retrieval" / "query_transform" / + "router_e2e" / "sql_range"``. Used as both the leaf filename + (``.jsonl``) and a short tag. + anchor + The *data* date this audit entry pertains to. Defaults to today. + Using an explicit anchor is recommended for agent-side audits so + backfills land in the correct folder. + filename + Override the default ``.jsonl`` leaf filename. Mostly + useful for sub-files like ``retriever_audit_trail.jsonl`` that + existing consumers already expect. + scoped_by_run + When ``True`` (default), place the file under the current + ``run_id`` so that everything produced by one CLI invocation + lives together. When ``False``, use the flat + ``logs/{module}/{date}/`` layout that predates + ``run_id`` and is still read by legacy offline tools. + + The parent folder is created as a side-effect. + """ + anchor = anchor or date.today() + date_str = anchor.isoformat() + leaf = filename or f"{module}.jsonl" + + if scoped_by_run: + folder = _logs_root() / "runs" / date_str / current_run_id() / module + else: + folder = _logs_root() / module / date_str + + folder.mkdir(parents=True, exist_ok=True) + return folder / leaf + + +# --------------------------------------------------------------------------- +# Logger configuration +# --------------------------------------------------------------------------- + + +_ROOT_CONFIGURED = False + + +def configure_root_logger( + *, + level: str = "INFO", + also_to_file: bool = True, +) -> logging.Logger: + """Install a sane stdout + file handler on the root logger. + + Safe to call multiple times — subsequent calls replace existing + handlers so pytest / Jupyter do not double-print. + """ + global _ROOT_CONFIGURED + + root = logging.getLogger() + root.setLevel(getattr(logging, level.upper(), logging.INFO)) + for h in list(root.handlers): + root.removeHandler(h) + + fmt = logging.Formatter( + fmt="%(asctime)s | %(levelname)s | %(name)s | %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", + ) + + stream = logging.StreamHandler(sys.stdout) + stream.setFormatter(fmt) + root.addHandler(stream) + + if also_to_file: + run_folder = _logs_root() / "runs" / date.today().isoformat() / current_run_id() + run_folder.mkdir(parents=True, exist_ok=True) + file_handler = logging.FileHandler( + run_folder / "orchestrator.log", + encoding="utf-8", + delay=True, # open on first emit — survives read-only CI + ) + file_handler.setFormatter(fmt) + root.addHandler(file_handler) + + _ROOT_CONFIGURED = True + return root + + +def get_audit_logger( + name: str, + module: str, + *, + anchor: Optional[date] = None, + level: str = "INFO", +) -> logging.Logger: + """Return a logger whose output goes to the unified audit path. + + The returned logger has a single ``FileHandler`` attached at + ``audit_path(module, anchor, filename=f"{name}.log")``. Console + output continues to flow through the root logger (if configured). + + Typical usage — one call near the top of a module:: + + log = get_audit_logger("QdrantRetriever", module="retrieval") + log.info("search filter=%s", filt) + """ + anchor = anchor or date.today() + logger = logging.getLogger(name) + logger.setLevel(getattr(logging, level.upper(), logging.INFO)) + + target = audit_path(module, anchor, filename=f"{name}.log") + + # Avoid stacking handlers on repeat calls (pytest, Jupyter). + for h in list(logger.handlers): + if getattr(h, "_audit_path", None) == str(target): + return logger + + handler = logging.FileHandler(target, encoding="utf-8", delay=True) + handler._audit_path = str(target) # type: ignore[attr-defined] + handler.setFormatter( + logging.Formatter( + fmt="%(asctime)s | %(levelname)s | %(name)s | %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", + ) + ) + logger.addHandler(handler) + return logger + + +__all__ = [ + "audit_path", + "configure_root_logger", + "current_run_id", + "get_audit_logger", + "start_run", +] diff --git a/Scripts/orchestration/__init__.py b/Scripts/orchestration/__init__.py new file mode 100644 index 0000000..96059bb --- /dev/null +++ b/Scripts/orchestration/__init__.py @@ -0,0 +1,44 @@ +"""Orchestration layer — pipeline DAG, runtime state, CLI entrypoint. + +Intentionally re-exports only the *light* surface so this module is safe +to import from anywhere (agents, tests, Jupyter) without dragging in the +agent graph / LangChain. Heavy things (CLI entry, LLM-backed query) live +in ``Scripts.orchestration.cli`` and must be imported explicitly. +""" +from Scripts.orchestration.run_state import ( + Cadence, + DATASET_ANCHOR_KEYS, + RunState, + default_state_path, + get_run_state, + reset_run_state_singleton, + run_key, + run_key_to_date, +) +from Scripts.orchestration.stages import ( + CallableStage, + ScriptStage, + Stage, + StageResult, +) +from Scripts.orchestration.pipeline import ( + Pipeline, + build_default_pipeline, +) + +__all__ = [ + "Cadence", + "DATASET_ANCHOR_KEYS", + "RunState", + "default_state_path", + "get_run_state", + "reset_run_state_singleton", + "run_key", + "run_key_to_date", + "Stage", + "StageResult", + "ScriptStage", + "CallableStage", + "Pipeline", + "build_default_pipeline", +] diff --git a/Scripts/orchestration/cli.py b/Scripts/orchestration/cli.py new file mode 100644 index 0000000..d711b5e --- /dev/null +++ b/Scripts/orchestration/cli.py @@ -0,0 +1,305 @@ +""" +CLI entrypoint for the bot — one command, four subcommands. + + python -m Scripts ingest [--only ...] [--force] [--dry-run] + python -m Scripts daemon [--poll-seconds 30] + python -m Scripts status + python -m Scripts query "your question here" + +``ingest`` / ``daemon`` / ``status`` touch only the orchestration layer +and have no LLM dependencies — safe to run on a CI box without Ollama. +``query`` lazily imports the agent graph so the CLI stays fast for +non-query commands. +""" +from __future__ import annotations + +import argparse +import json +import logging +import sys +from datetime import datetime +from typing import List, Optional + +from Scripts.observability.audit import configure_root_logger, start_run +from Scripts.orchestration.pipeline import Pipeline, build_default_pipeline +from Scripts.orchestration.run_state import RunState, get_run_state + +log = logging.getLogger("orchestrator.cli") + + +# --------------------------------------------------------------------------- +# Subcommand handlers +# --------------------------------------------------------------------------- + + +def _cmd_ingest(args: argparse.Namespace) -> int: + pipeline = build_default_pipeline() + results = pipeline.run_once( + only=args.only, + force=args.force, + dry_run=args.dry_run, + ) + + ok = all(r.ok for r in results) + _print_run_summary(results) + return 0 if ok else 1 + + +def _cmd_daemon(args: argparse.Namespace) -> int: + if args.warmup: + _run_warmup(args.warmup_roles, synchronous=False) + pipeline = build_default_pipeline() + pipeline.run_forever(poll_seconds=args.poll_seconds) + return 0 # unreachable under normal operation + + +def _cmd_status(args: argparse.Namespace) -> int: + rs = get_run_state() + snap = rs.snapshot() + if args.json: + print(json.dumps(snap, indent=2, ensure_ascii=False)) + else: + _print_status_summary(snap) + return 0 + + +def _cmd_query(args: argparse.Namespace) -> int: + import asyncio + + question = " ".join(args.question).strip() + if not question: + print("query: empty question", file=sys.stderr) + return 2 + + # Warm the model pool before spinning up the agent graph so the + # first user query does not pay the 70B cold-start penalty. + if args.warmup: + _run_warmup(args.warmup_roles, synchronous=True) + + # Lazy import — heavy LangChain / Ollama clients are only materialised + # when the user actually asks a question. The router module exports + # ``build_financial_rag_graph``; ``build_graph`` is kept as a + # forward-compatible alias for parity with generic LangGraph tutorials. + try: + from Scripts.agents.router import build_financial_rag_graph + except ImportError as exc: + print( + f"query: agent graph is not importable — {exc}\n" + "If you only want to run the data pipeline, use `ingest` / `daemon` " + "/ `status` which do not require the agent layer.", + file=sys.stderr, + ) + return 2 + + graph = build_financial_rag_graph() + log.info("query: %s", question) + + # The graph contains async nodes (master_retrieval_node, analyst_node, + # …) so we must drive it through `ainvoke`. Using the sync `invoke` + # will raise on the first `await`. + result = asyncio.run(graph.ainvoke({"original_query": question})) + + # The finalizer writes its Pydantic dict to ``final_strategy`` (see + # ``finalizer_node`` in Scripts/agents/router.py); ``final_report`` + # was a draft-era key and no longer exists. + final_strategy = result.get("final_strategy") or result.get("draft_report") + if final_strategy is None: + print("", file=sys.stderr) + return 1 + + if isinstance(final_strategy, (dict, list)): + print(json.dumps(final_strategy, indent=2, ensure_ascii=False)) + else: + print(final_strategy) + return 0 + + +def _cmd_warmup(args: argparse.Namespace) -> int: + try: + from Scripts.core import llm_pool + except ImportError as exc: + print(f"warmup: llm_pool unavailable — {exc}", file=sys.stderr) + return 2 + + results = llm_pool.warmup_sync(roles=args.roles or None) + width = max((len(r.role) for r in results), default=8) + print(f"{'role':<{width}} status latency model") + print("-" * (width + 40)) + for r in results: + print(f"{r.role:<{width}} {r.status:<8} {r.latency_s:>6.2f}s {r.model}") + if r.error: + print(f" ! {r.error}") + return 0 if all(r.status == "ok" for r in results) else 1 + + +def _run_warmup(roles, *, synchronous: bool) -> None: + """Shared warmup entry — imports llm_pool lazily so CLI subcommands + that do not need an LLM never pay the import cost.""" + try: + from Scripts.core import llm_pool + except ImportError as exc: + log.warning("warmup skipped — llm_pool import failed: %s", exc) + return + + if synchronous: + results = llm_pool.warmup_sync(roles=roles or None) + for r in results: + log.info( + "warmup role=%s model=%s status=%s latency=%.2fs %s", + r.role, r.model, r.status, r.latency_s, + f"error={r.error}" if r.error else "", + ) + else: + llm_pool.warmup_async(roles=roles or None) + log.info("warmup dispatched asynchronously in background") + + +# --------------------------------------------------------------------------- +# Summary printers +# --------------------------------------------------------------------------- + + +def _print_run_summary(results) -> None: + width = max((len(r.name) for r in results), default=8) + header = f"{'stage':<{width}} status run_key latency" + print(header) + print("-" * len(header)) + for r in results: + rk = r.run_key or "-" + print(f"{r.name:<{width}} {r.status:<8} {rk:<17} {r.latency_s:>6.2f}s") + if r.error: + print(f" ! {r.error}") + + +def _print_status_summary(snap: dict) -> None: + print(f"state_path: {snap['state_path']}") + print(f"updated_at: {snap.get('updated_at') or '(never)'}") + print() + print("last_run_keys:") + for k, v in sorted(snap["last_run_keys"].items()): + print(f" {k:<28} {v}") + print() + print("anchors (agent-side time anchors):") + for ds, d in snap["anchors"].items(): + print(f" {ds:<10} {d}") + + +# --------------------------------------------------------------------------- +# Argument parsing +# --------------------------------------------------------------------------- + + +def build_parser() -> argparse.ArgumentParser: + p = argparse.ArgumentParser( + prog="options-bot", + description=( + "Data ingestion + RAG inference orchestrator for the " + "Automated Options Recommendation Bot." + ), + ) + p.add_argument( + "--log-level", + default="INFO", + choices=["DEBUG", "INFO", "WARNING", "ERROR"], + help="Root logger level (default: INFO).", + ) + sub = p.add_subparsers(dest="cmd", required=True) + + # ingest + p_ing = sub.add_parser( + "ingest", + help="Run data pipeline stages that are due (idempotent).", + ) + p_ing.add_argument( + "--only", + nargs="+", + metavar="STAGE", + help="Run only these stages (upstream deps are auto-included).", + ) + p_ing.add_argument( + "--force", + action="store_true", + help="Ignore is_up_to_date — re-run even if today's key already matches.", + ) + p_ing.add_argument( + "--dry-run", + action="store_true", + help="Print what would run without executing anything.", + ) + p_ing.set_defaults(handler=_cmd_ingest) + + # daemon + p_dae = sub.add_parser( + "daemon", + help="Long-running scheduler loop (same as legacy collect_data.py).", + ) + p_dae.add_argument("--poll-seconds", type=int, default=30) + p_dae.add_argument( + "--warmup", + action="store_true", + help="Warm the LLM pool in a background thread on startup.", + ) + p_dae.add_argument( + "--warmup-roles", + nargs="+", + metavar="ROLE", + help="Override the default warmup role list (e.g. 'analyst finalizer').", + ) + p_dae.set_defaults(handler=_cmd_daemon) + + # status + p_stat = sub.add_parser( + "status", + help="Show last_run_keys and agent time anchors from runtime state.", + ) + p_stat.add_argument("--json", action="store_true", help="Emit JSON.") + p_stat.set_defaults(handler=_cmd_status) + + # query + p_q = sub.add_parser( + "query", + help="Ask the multi-agent graph a question (interactive one-shot).", + ) + p_q.add_argument("question", nargs="+", help="Natural-language question.") + p_q.add_argument( + "--warmup", + action="store_true", + help="Pre-load the heavy LLM into GPU before sending the question.", + ) + p_q.add_argument( + "--warmup-roles", + nargs="+", + metavar="ROLE", + help="Override the default warmup role list.", + ) + p_q.set_defaults(handler=_cmd_query) + + # warmup (standalone — useful for CI / cron prehook) + p_w = sub.add_parser( + "warmup", + help="Pin configured LLM models into Ollama memory and exit.", + ) + p_w.add_argument( + "--roles", + nargs="+", + metavar="ROLE", + help="Specific roles to warm up (default: query_extract + analyst).", + ) + p_w.set_defaults(handler=_cmd_warmup) + + return p + + +def main(argv: Optional[List[str]] = None) -> int: + argv = argv if argv is not None else sys.argv[1:] + args = build_parser().parse_args(argv) + + configure_root_logger(level=args.log_level) + start_run(tag=args.cmd) + + log.info("cli: cmd=%s args=%s", args.cmd, vars(args)) + return int(args.handler(args) or 0) + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Scripts/orchestration/pipeline.py b/Scripts/orchestration/pipeline.py new file mode 100644 index 0000000..323718f --- /dev/null +++ b/Scripts/orchestration/pipeline.py @@ -0,0 +1,307 @@ +""" +Pipeline — compose Stages into a DAG, run them once or forever. + +Two entry points: + +* :meth:`Pipeline.run_once` — ad-hoc execution ("run today's ingest now", + or "only the ``options_daily`` stage"). Called by the CLI ``ingest`` + subcommand and by tests. +* :meth:`Pipeline.run_forever` — long-lived scheduler loop. Replaces + ``Scripts/data_collection/collect_data.py::SchedulerService.run_forever`` + while keeping the same cadence / state semantics. + +Dependency handling +------------------- +Stages declare ``depends_on``; the runner topologically sorts the graph +and skips downstream stages whose upstreams failed (unless ``force=True``). +Cycles raise ``ValueError`` at *pipeline build time* — not at run time — +so misconfigurations are caught fast. +""" +from __future__ import annotations + +import logging +import time +from datetime import date, datetime +from pathlib import Path +from typing import Any, Callable, Dict, Iterable, List, Optional, Sequence, Tuple + +from Scripts.orchestration.run_state import Cadence, RunState, get_run_state +from Scripts.orchestration.stages import ( + ScriptStage, + Stage, + StageResult, +) + +log = logging.getLogger(__name__) + + +# --------------------------------------------------------------------------- +# Topological sort +# --------------------------------------------------------------------------- + + +def _toposort(stages: Sequence[Stage]) -> List[Stage]: + """Kahn's algorithm — stable w.r.t. insertion order for ties so the + CLI output is reproducible.""" + by_name: Dict[str, Stage] = {s.name: s for s in stages} + if len(by_name) != len(stages): + all_names = [s.name for s in stages] + dup = sorted({n for n in all_names if all_names.count(n) > 1}) + raise ValueError(f"Duplicate stage name(s): {dup}") + + incoming: Dict[str, int] = {n: 0 for n in by_name} + outgoing: Dict[str, List[str]] = {n: [] for n in by_name} + for s in stages: + for dep in s.depends_on: + if dep not in by_name: + raise ValueError( + f"Stage {s.name!r} depends on unknown stage {dep!r}" + ) + incoming[s.name] += 1 + outgoing[dep].append(s.name) + + ready: List[str] = [n for n, c in incoming.items() if c == 0] + ordered: List[Stage] = [] + while ready: + ready.sort() # determinism + current = ready.pop(0) + ordered.append(by_name[current]) + for child in outgoing[current]: + incoming[child] -= 1 + if incoming[child] == 0: + ready.append(child) + + if len(ordered) != len(stages): + remaining = [n for n, c in incoming.items() if c > 0] + raise ValueError(f"Stage dependency cycle involving: {remaining}") + return ordered + + +# --------------------------------------------------------------------------- +# Pipeline +# --------------------------------------------------------------------------- + + +class Pipeline: + """A topologically-ordered collection of :class:`Stage`s.""" + + def __init__( + self, + stages: Sequence[Stage], + *, + run_state: Optional[RunState] = None, + ) -> None: + self._stages: List[Stage] = _toposort(stages) + self._by_name: Dict[str, Stage] = {s.name: s for s in self._stages} + self.run_state: RunState = run_state or get_run_state() + + # ---- introspection ----------------------------------------------------- + + @property + def stage_names(self) -> List[str]: + return [s.name for s in self._stages] + + def stage(self, name: str) -> Stage: + return self._by_name[name] + + # ---- execution --------------------------------------------------------- + + def run_once( + self, + *, + only: Optional[Iterable[str]] = None, + force: bool = False, + dry_run: bool = False, + when: Optional[datetime] = None, + ) -> List[StageResult]: + """Run the pipeline exactly once. + + Parameters + ---------- + only + If provided, execute *only* these stage names (plus any of + their upstreams that are not up-to-date). Unknown names are + a ``ValueError``. + force + Ignore ``is_up_to_date`` — useful for manual backfills. + dry_run + Log what *would* run without executing. + when + Override the wall-clock. Used by tests and backfills. + """ + when = when or datetime.now() + targets = self._resolve_targets(only) + + results: List[StageResult] = [] + failed: set[str] = set() + + for stage in self._stages: + if stage.name not in targets: + continue + + # Short-circuit downstream work when a critical upstream failed. + upstream_failed = {d for d in stage.depends_on if d in failed} + if upstream_failed: + log.warning( + "stage=%s skipped — upstream failed: %s", + stage.name, + sorted(upstream_failed), + ) + results.append( + StageResult( + name=stage.name, + status="skipped", + error=f"upstream_failed={sorted(upstream_failed)}", + ) + ) + failed.add(stage.name) # propagate to deeper dependents + continue + + result = stage.run( + self.run_state, when=when, force=force, dry_run=dry_run + ) + results.append(result) + if not result.ok and stage.critical: + failed.add(stage.name) + + return results + + def run_forever( + self, + *, + poll_seconds: int = 30, + now_provider: Optional[Callable[[], datetime]] = None, + ) -> None: + """Long-lived scheduler loop. Calls :meth:`run_once` on every + tick — ``is_up_to_date`` guarantees each stage runs at most once + per cadence window. + + This replaces ``SchedulerService.run_forever`` in + ``Scripts/data_collection/collect_data.py`` but is fully backward + compatible because they share the same ``RunState`` on disk. + """ + now = now_provider or datetime.now + log.info( + "Pipeline.run_forever starting — %d stages, poll=%ds, state=%s", + len(self._stages), + poll_seconds, + self.run_state.state_path, + ) + while True: + try: + self.run_once(when=now()) + except Exception: + log.exception("unexpected tick failure — continuing") + time.sleep(poll_seconds) + + # ---- internals --------------------------------------------------------- + + def _resolve_targets(self, only: Optional[Iterable[str]]) -> set[str]: + """Expand ``only`` to include all upstream dependencies so partial + runs respect the DAG.""" + if only is None: + return set(self._by_name) + + requested = list(only) + unknown = [n for n in requested if n not in self._by_name] + if unknown: + raise ValueError( + f"Unknown stage name(s): {unknown}. " + f"Known: {sorted(self._by_name)}" + ) + + needed: set[str] = set() + stack = list(requested) + while stack: + current = stack.pop() + if current in needed: + continue + needed.add(current) + stack.extend(self._by_name[current].depends_on) + return needed + + +# --------------------------------------------------------------------------- +# Default factory — the 6 stages your project already runs +# --------------------------------------------------------------------------- + + +def _project_root() -> Path: + return Path(__file__).resolve().parents[2] + + +def build_default_pipeline( + *, + run_state: Optional[RunState] = None, + project_root: Optional[Path] = None, +) -> Pipeline: + """Build the production pipeline from the 5 scrapers + 1 processor + already present in ``Scripts/data_collection``. + + The DAG mirrors the reality of the data layer: + (gpr_monthly, macro_trading_daily, news_daily, options_daily) + │ + ▼ + sec_ingestion_weekly + │ + ▼ + sec_processor_weekly + + None of the daily sources depend on each other — they hit different + external endpoints and can run in parallel if you later switch the + runner to threads/async. ``sec_processor`` depends on ``sec_ingestion`` + because it parses the artefacts ingestion just wrote to Bronze. + """ + root = Path(project_root) if project_root else _project_root() + scrapers = root / "Scripts" / "data_collection" / "scrapers" + processors = root / "Scripts" / "data_collection" / "processors" + + stages: List[Stage] = [ + ScriptStage( + name="gpr_monthly", + script_path=scrapers / "GPR_index.py", + cadence=Cadence.MONTHLY, + project_root=root, + ), + ScriptStage( + name="macro_trading_daily", + script_path=scrapers / "macro_data_pipeline.py", + cadence=Cadence.TRADING_DAILY, + project_root=root, + ), + ScriptStage( + name="news_daily", + script_path=scrapers / "news_scraper.py", + cadence=Cadence.DAILY, + project_root=root, + ), + ScriptStage( + name="options_daily", + script_path=scrapers / "yfinance_options_history.py", + cadence=Cadence.DAILY, + project_root=root, + ), + ScriptStage( + name="sec_ingestion_weekly", + script_path=scrapers / "sec_ingestion.py", + cadence=Cadence.WEEKLY, + timeout_s=60 * 45, + project_root=root, + ), + ScriptStage( + name="sec_processor_weekly", + script_path=processors / "sec_processor.py", + cadence=Cadence.WEEKLY, + depends_on=("sec_ingestion_weekly",), + timeout_s=60 * 45, + project_root=root, + ), + ] + + return Pipeline(stages, run_state=run_state) + + +__all__ = [ + "Pipeline", + "build_default_pipeline", +] diff --git a/Scripts/orchestration/run_state.py b/Scripts/orchestration/run_state.py new file mode 100644 index 0000000..a6deab4 --- /dev/null +++ b/Scripts/orchestration/run_state.py @@ -0,0 +1,415 @@ +""" +RunState — the authoritative read/write handle for +``config/runtime/collect_data_state.json``. + +This module is the *single source of truth* for three things that used to +be duplicated across the codebase: + +1. **Cadence arithmetic** — turning a ``datetime`` into a ``run_key`` + (``"2026-04-21"`` / ``"2026-W16"`` / ``"2026-04"``) and vice versa. +2. **Idempotency check** — was job ``X`` already run this cadence window? +3. **Time-anchor lookup** — what is the latest successfully ingested + partition date for dataset ``Y``? Agents (``Checker``, ``Finalizer``, + ``time_adapter``, ``SilverSQLTool``) ask ``RunState.latest_anchor_date`` + instead of calling ``date.today()`` — surviving weekends, holidays and + manual backfills. + +Design choices +-------------- +* **Atomic writes.** ``write_run_key`` stages to ``*.json.tmp`` then + ``os.replace`` — on Windows this is the POSIX-equivalent atomic rename, + so a Ctrl+C in the middle of a scheduler tick cannot corrupt the file + that agents rely on for time anchoring. +* **No dependencies.** stdlib-only; safely importable from every layer + including the CLI bootstrap before any heavyweight packages are loaded. +* **Lenient reads / strict writes.** If the file is missing or broken the + readers return "unknown" sentinels so the agent layer degrades to + ``date.today()`` rather than crashing. Writes always produce a valid + JSON document. +""" +from __future__ import annotations + +import json +import os +import tempfile +from dataclasses import dataclass +from datetime import date, datetime, timedelta +from enum import Enum +from pathlib import Path +from typing import Any, Dict, Iterable, Optional, Tuple + + +# --------------------------------------------------------------------------- +# Path resolution +# --------------------------------------------------------------------------- + + +def _project_root() -> Path: + """Scripts/orchestration/run_state.py -> repo root (parents[2]).""" + return Path(__file__).resolve().parents[2] + + +def default_state_path() -> Path: + """Return the canonical path to ``collect_data_state.json``.""" + return _project_root() / "config" / "runtime" / "collect_data_state.json" + + +# --------------------------------------------------------------------------- +# Cadence +# --------------------------------------------------------------------------- + + +class Cadence(str, Enum): + """How often a pipeline stage should run. + + ``TRADING_DAILY`` is a specialization of ``DAILY`` that additionally + refuses to run on Saturdays/Sundays — used by ``macro_trading_daily`` + where FRED / yfinance emit no new data on weekends. + """ + + DAILY = "daily" + TRADING_DAILY = "trading_daily" + WEEKLY = "weekly" + MONTHLY = "monthly" + + +# --------------------------------------------------------------------------- +# run_key arithmetic — shared with the legacy `collect_data.py` scheduler +# --------------------------------------------------------------------------- + + +def run_key(cadence: Cadence, when: datetime) -> str: + """Compute the idempotency key for a given moment + cadence. + + Examples + -------- + >>> run_key(Cadence.DAILY, datetime(2026, 4, 21)) + '2026-04-21' + >>> run_key(Cadence.WEEKLY, datetime(2026, 4, 21)) # ISO week + '2026-W16' + >>> run_key(Cadence.MONTHLY, datetime(2026, 4, 21)) + '2026-04' + """ + if cadence in (Cadence.DAILY, Cadence.TRADING_DAILY): + return when.strftime("%Y-%m-%d") + if cadence == Cadence.WEEKLY: + iso = when.isocalendar() + return f"{iso.year}-W{iso.week:02d}" + if cadence == Cadence.MONTHLY: + return when.strftime("%Y-%m") + raise ValueError(f"Unsupported cadence: {cadence!r}") + + +def run_key_to_date(key: str) -> Optional[date]: + """Reverse ``run_key`` back to a representative ``date``. + + * Daily key ``"2026-04-21"`` -> ``date(2026, 4, 21)`` + * Weekly key ``"2026-W16"`` -> Monday of that ISO week + * Monthly key ``"2026-04"`` -> first day of that month + + Returns ``None`` when the string does not match any known pattern so + callers can fall back to ``date.today()``. + """ + if not key: + return None + try: + if len(key) == 10 and key[4] == "-" and key[7] == "-": # YYYY-MM-DD + return datetime.strptime(key, "%Y-%m-%d").date() + if len(key) == 7 and key[4] == "-": # YYYY-MM + return datetime.strptime(key + "-01", "%Y-%m-%d").date() + if "W" in key: # YYYY-Www + year_str, week_str = key.split("-W", 1) + return date.fromisocalendar(int(year_str), int(week_str), 1) + except (ValueError, IndexError): + pass + return None + + +# --------------------------------------------------------------------------- +# Dataset → anchor-key mapping +# --------------------------------------------------------------------------- + + +# The authoritative map between a *logical dataset* used by agents and the +# *run_key field* where scrapers announce freshness. Keep additions to this +# table in sync with ``Scripts.data_collection.collect_data.build_jobs``. +DATASET_ANCHOR_KEYS: Dict[str, str] = { + "options": "options_daily", + "macro": "macro_trading_daily", + "news": "news_daily", + "gpr": "gpr_monthly", + "sec": "sec_processor_weekly", # processor is the downstream-visible anchor + "sec_raw": "sec_ingestion_weekly", +} + + +# --------------------------------------------------------------------------- +# The state handle +# --------------------------------------------------------------------------- + + +@dataclass +class _StateDoc: + """Typed view of the JSON payload — kept internal for clarity.""" + + last_run_keys: Dict[str, str] + updated_at: Optional[str] = None + + def to_dict(self) -> Dict[str, Any]: + doc: Dict[str, Any] = {"last_run_keys": dict(self.last_run_keys)} + if self.updated_at: + doc["updated_at"] = self.updated_at + return doc + + @classmethod + def from_dict(cls, raw: Dict[str, Any]) -> "_StateDoc": + keys = raw.get("last_run_keys") or {} + if not isinstance(keys, dict): + keys = {} + return cls( + last_run_keys={str(k): str(v) for k, v in keys.items()}, + updated_at=raw.get("updated_at"), + ) + + +class RunState: + """Thread-safe-ish (process-level) handle to the runtime state file. + + *Not* multi-process safe — the scheduler daemon and the interactive + CLI should not both try to write the file at the same moment. In + practice the scheduler owns writes; agents/CLIs only read. Readers + tolerate half-written files by catching ``json.JSONDecodeError`` and + returning an empty document. + """ + + def __init__(self, state_path: Optional[Path] = None) -> None: + self.state_path: Path = Path(state_path) if state_path else default_state_path() + self._doc: _StateDoc = _StateDoc(last_run_keys={}) + self._loaded: bool = False + + # ---- low-level I/O ----------------------------------------------------- + + def _load(self) -> None: + if not self.state_path.exists(): + self._doc = _StateDoc(last_run_keys={}) + self._loaded = True + return + try: + raw = json.loads(self.state_path.read_text(encoding="utf-8")) + if not isinstance(raw, dict): + raw = {} + self._doc = _StateDoc.from_dict(raw) + except (OSError, json.JSONDecodeError): + # Tolerate a half-written file — agents must never crash because + # the scheduler was interrupted mid-write. + self._doc = _StateDoc(last_run_keys={}) + self._loaded = True + + def _ensure_loaded(self) -> None: + if not self._loaded: + self._load() + + def reload(self) -> "RunState": + """Force re-read from disk. Useful for long-lived agent processes + that want to pick up a fresh daily run without restarting.""" + self._loaded = False + self._load() + return self + + def _atomic_write(self) -> None: + self._doc.updated_at = datetime.now().isoformat(timespec="seconds") + payload = json.dumps(self._doc.to_dict(), ensure_ascii=False, indent=2) + self.state_path.parent.mkdir(parents=True, exist_ok=True) + + # Use NamedTemporaryFile in the *same directory* so os.replace is a + # rename within one filesystem — atomic on both Windows and POSIX. + fd, tmp_path = tempfile.mkstemp( + prefix=self.state_path.name + ".", + suffix=".tmp", + dir=str(self.state_path.parent), + ) + try: + with os.fdopen(fd, "w", encoding="utf-8") as f: + f.write(payload) + f.flush() + try: + os.fsync(f.fileno()) + except OSError: + # fsync is a best-effort durability hint; on some + # Windows filesystems it raises OSError(EINVAL). Swallow + # and rely on os.replace for atomicity. + pass + os.replace(tmp_path, self.state_path) + except Exception: + # Clean up the tmp file if the rename failed. + try: + os.unlink(tmp_path) + except OSError: + pass + raise + + # ---- public API -------------------------------------------------------- + + # --- job-keyed reads ----------------------------------------------- + + def get_run_key(self, job_name: str) -> Optional[str]: + """Return the stored ``run_key`` for a named job, or ``None`` if + the job has never recorded a successful run.""" + self._ensure_loaded() + return self._doc.last_run_keys.get(job_name) + + def all_run_keys(self) -> Dict[str, str]: + """Return a *copy* of the full ``last_run_keys`` mapping.""" + self._ensure_loaded() + return dict(self._doc.last_run_keys) + + # --- idempotency --------------------------------------------------- + + def is_up_to_date( + self, + job_name: str, + cadence: Cadence, + when: Optional[datetime] = None, + ) -> bool: + """True if the most recently recorded ``run_key`` matches what we + would compute now — i.e. the job does not need to run again this + cadence window.""" + when = when or datetime.now() + return self.get_run_key(job_name) == run_key(cadence, when) + + # --- writes (owned by scheduler / CLI ingest) ---------------------- + + def mark_job_complete( + self, + job_name: str, + cadence: Cadence, + when: Optional[datetime] = None, + ) -> str: + """Record that ``job_name`` just finished successfully. Returns + the ``run_key`` that was written so callers can log it.""" + self._ensure_loaded() + when = when or datetime.now() + key = run_key(cadence, when) + self._doc.last_run_keys[job_name] = key + self._atomic_write() + return key + + def write_run_key(self, job_name: str, key: str) -> None: + """Lower-level write for callers that already computed their own + ``run_key`` (e.g. backfill scripts replaying historical dates).""" + self._ensure_loaded() + self._doc.last_run_keys[job_name] = str(key) + self._atomic_write() + + # --- time anchor lookup (the single source of truth) --------------- + + def latest_anchor_date( + self, + dataset: str, + *, + fallback: Optional[date] = None, + ) -> date: + """Return the most recently ingested *data* date for ``dataset``. + + Parameters + ---------- + dataset + Logical dataset name — one of ``DATASET_ANCHOR_KEYS``'s keys + (``"options"``, ``"macro"``, ``"news"``, ``"gpr"``, ``"sec"``, + ``"sec_raw"``). Case-insensitive. + fallback + What to return when the state file is missing or the dataset + has no recorded anchor yet. Defaults to ``date.today()``. + + Never raises — the agent layer is expected to always get *some* + anchor so that ``yesterday`` can be computed deterministically. + """ + self._ensure_loaded() + key_field = DATASET_ANCHOR_KEYS.get(dataset.lower()) + if key_field: + raw = self._doc.last_run_keys.get(key_field) + anchor = run_key_to_date(raw or "") + if anchor: + return anchor + return fallback or date.today() + + def latest_anchor_for_granularity( + self, + granularity: str, + *, + fallback: Optional[date] = None, + ) -> date: + """Convenience mirror of :meth:`latest_anchor_date` keyed by the + ``TimeGranularity`` enum values used in ``time_adapter``: + ``"daily"``, ``"event"``, ``"monthly"``, ``"weekly"``. Events + anchor on news (the freshest event stream); weekly anchors on + SEC; monthly on GPR. + """ + mapping = { + "daily": "options", + "event": "news", + "weekly": "sec", + "monthly": "gpr", + } + dataset = mapping.get(granularity.lower(), "options") + return self.latest_anchor_date(dataset, fallback=fallback) + + # --- diagnostics --------------------------------------------------- + + def snapshot(self) -> Dict[str, Any]: + """Return a serialisable summary for ``cli.py status``.""" + self._ensure_loaded() + return { + "state_path": str(self.state_path), + "exists": self.state_path.exists(), + "updated_at": self._doc.updated_at, + "last_run_keys": dict(self._doc.last_run_keys), + "anchors": { + ds: self.latest_anchor_date(ds).isoformat() + for ds in DATASET_ANCHOR_KEYS + }, + } + + +# --------------------------------------------------------------------------- +# Module-level singleton +# --------------------------------------------------------------------------- + + +_SINGLETON: Optional[RunState] = None + + +def get_run_state(state_path: Optional[Path] = None) -> RunState: + """Process-wide singleton accessor. + + Agents that re-query the state repeatedly (``SilverSQLTool``, + ``time_adapter.build_anchor``) should call this rather than + instantiating ``RunState`` — avoids O(N) JSON parses per query. + Pass an explicit ``state_path`` only in tests. + """ + global _SINGLETON + if state_path is not None: + # Tests: bypass the cache so each test gets its own instance. + return RunState(state_path) + if _SINGLETON is None: + _SINGLETON = RunState() + return _SINGLETON + + +def reset_run_state_singleton() -> None: + """Drop the process-wide cache — used by long-lived daemons that want + to pick up a freshly rewritten state file without restarting.""" + global _SINGLETON + _SINGLETON = None + + +__all__ = [ + "Cadence", + "DATASET_ANCHOR_KEYS", + "RunState", + "default_state_path", + "get_run_state", + "reset_run_state_singleton", + "run_key", + "run_key_to_date", +] diff --git a/Scripts/orchestration/stages.py b/Scripts/orchestration/stages.py new file mode 100644 index 0000000..146f491 --- /dev/null +++ b/Scripts/orchestration/stages.py @@ -0,0 +1,298 @@ +""" +Stage abstractions for the pipeline DAG. + +Design +------ +A *Stage* is one unit of work in the ingest pipeline — typically +"scrape source X and land it in Bronze/Silver". Stages are: + +* **Idempotent** — asked to run twice in the same cadence window they + skip the second time. Ownership of that decision lives in ``RunState``. +* **Declarative about cadence** — the stage says *"I run weekly"* and + the scheduler / CLI decides whether today's the day. +* **Declarative about dependencies** — ``depends_on`` forms a DAG that + :class:`Scripts.orchestration.pipeline.Pipeline` topologically sorts. +* **Robust about failure** — raising is allowed; the runner converts + exceptions into ``StageResult(status="failed")`` and decides whether + to continue based on ``critical``. + +Two concrete Stage types are provided here: + +* :class:`ScriptStage` — thin wrapper around :class:`subprocess.run`, + fully compatible with your existing ``Scripts/data_collection/scrapers/*.py`` + scripts. No migration required. +* :class:`CallableStage` — for future in-process stages (e.g. the query + pipeline, embedding re-indexers). No subprocess overhead. +""" +from __future__ import annotations + +import logging +import subprocess +import sys +import time +from abc import ABC, abstractmethod +from dataclasses import dataclass, field +from datetime import datetime +from pathlib import Path +from typing import Any, Callable, Dict, List, Optional, Tuple + +from Scripts.orchestration.run_state import Cadence, RunState, run_key + +log = logging.getLogger(__name__) + + +# --------------------------------------------------------------------------- +# Status model +# --------------------------------------------------------------------------- + + +@dataclass +class StageResult: + """Outcome of a single Stage invocation.""" + + name: str + status: str # "ok" | "skipped" | "failed" | "degraded" + run_key: Optional[str] = None + latency_s: float = 0.0 + stdout: str = "" + stderr: str = "" + error: Optional[str] = None + metrics: Dict[str, Any] = field(default_factory=dict) + + @property + def ok(self) -> bool: + return self.status in ("ok", "skipped") + + +# --------------------------------------------------------------------------- +# Base class +# --------------------------------------------------------------------------- + + +class Stage(ABC): + """Abstract base for all pipeline stages. + + Subclasses must set the class-level ``name`` / ``cadence`` and + implement :meth:`_execute`. Everything else (logging, timing, + state bookkeeping) is handled here. + """ + + name: str + cadence: Cadence + depends_on: Tuple[str, ...] = () + critical: bool = True + timeout_s: int = 60 * 30 + max_retries: int = 2 + retry_backoff_s: int = 10 + + # ---- subclass hooks ---------------------------------------------------- + + @abstractmethod + def _execute(self, when: datetime) -> Tuple[str, str]: + """Perform the actual work. + + Returns + ------- + (stdout, stderr) + Captured output (empty strings are fine). Raise on failure. + """ + + # ---- framework methods ------------------------------------------------- + + def is_up_to_date(self, run_state: RunState, when: datetime) -> bool: + """Default freshness check: compare stored ``run_key`` vs current.""" + return run_state.is_up_to_date(self.name, self.cadence, when) + + def run( + self, + run_state: RunState, + when: Optional[datetime] = None, + *, + force: bool = False, + dry_run: bool = False, + ) -> StageResult: + when = when or datetime.now() + current_key = run_key(self.cadence, when) + + if not force and self.is_up_to_date(run_state, when): + log.info( + "stage=%s skipped (up-to-date, run_key=%s)", self.name, current_key + ) + return StageResult(name=self.name, status="skipped", run_key=current_key) + + if dry_run: + log.info("stage=%s dry_run (would execute run_key=%s)", self.name, current_key) + return StageResult( + name=self.name, + status="skipped", + run_key=current_key, + metrics={"dry_run": True}, + ) + + started = time.monotonic() + last_error: Optional[Exception] = None + + for attempt in range(1, self.max_retries + 2): + log.info( + "stage=%s attempt=%d cadence=%s run_key=%s", + self.name, + attempt, + self.cadence.value, + current_key, + ) + try: + stdout, stderr = self._execute(when) + run_state.mark_job_complete(self.name, self.cadence, when) + latency = time.monotonic() - started + log.info( + "stage=%s ok run_key=%s latency=%.2fs", + self.name, + current_key, + latency, + ) + return StageResult( + name=self.name, + status="ok", + run_key=current_key, + latency_s=latency, + stdout=stdout, + stderr=stderr, + ) + except Exception as exc: # noqa: BLE001 — we want the full trap + last_error = exc + log.warning( + "stage=%s attempt=%d failed: %s", + self.name, + attempt, + exc, + ) + if attempt <= self.max_retries: + backoff = min(60, self.retry_backoff_s * attempt) + time.sleep(backoff) + + latency = time.monotonic() - started + return StageResult( + name=self.name, + status="failed", + run_key=current_key, + latency_s=latency, + error=str(last_error) if last_error else "unknown error", + ) + + +# --------------------------------------------------------------------------- +# Concrete: subprocess adapter (today's default) +# --------------------------------------------------------------------------- + + +class ScriptStage(Stage): + """Stage that shells out to a Python script via ``subprocess.run``. + + This is the zero-migration wrapper for your existing scrapers in + ``Scripts/data_collection/scrapers/*.py`` and processors in + ``Scripts/data_collection/processors/*.py``. Those scripts continue + to run standalone ( ``python Scripts/...``) — the ScriptStage simply + adds orchestration concerns (retries, timing, run_key accounting). + """ + + def __init__( + self, + *, + name: str, + script_path: Path, + cadence: Cadence, + depends_on: Tuple[str, ...] = (), + critical: bool = True, + timeout_s: int = 60 * 30, + max_retries: int = 2, + project_root: Optional[Path] = None, + extra_args: Tuple[str, ...] = (), + ) -> None: + self.name = name + self.cadence = cadence + self.depends_on = depends_on + self.critical = critical + self.timeout_s = timeout_s + self.max_retries = max_retries + self.script_path = Path(script_path) + self.project_root = Path(project_root) if project_root else Path.cwd() + self.extra_args = extra_args + + if not self.script_path.exists(): + raise FileNotFoundError( + f"ScriptStage({name!r}): script not found at {self.script_path}" + ) + + def _execute(self, when: datetime) -> Tuple[str, str]: + cmd = [sys.executable, str(self.script_path), *self.extra_args] + completed = subprocess.run( + cmd, + capture_output=True, + text=True, + timeout=self.timeout_s, + cwd=str(self.project_root), + check=False, + ) + stdout = (completed.stdout or "").strip() + stderr = (completed.stderr or "").strip() + + if completed.returncode != 0: + # Include stderr tail in the raised message so the StageResult + # carries an actionable error without dumping the whole trace. + tail = stderr[-500:] if stderr else "(no stderr)" + raise RuntimeError( + f"script={self.script_path.name} rc={completed.returncode}: {tail}" + ) + return stdout, stderr + + +# --------------------------------------------------------------------------- +# Concrete: in-process callable (future-facing) +# --------------------------------------------------------------------------- + + +class CallableStage(Stage): + """Stage that runs an in-process Python callable. + + Prefer this for new stages written from scratch — avoids the cost + of spawning a Python subprocess and lets the callable accept typed + state (``RunState``, ``run_id``). The callable signature is: + + fn(when: datetime) -> Dict[str, Any] + + and the returned dict is stored in ``StageResult.metrics``. + """ + + def __init__( + self, + *, + name: str, + fn: Callable[[datetime], Dict[str, Any]], + cadence: Cadence, + depends_on: Tuple[str, ...] = (), + critical: bool = True, + timeout_s: int = 60 * 30, + max_retries: int = 2, + ) -> None: + self.name = name + self.cadence = cadence + self.depends_on = depends_on + self.critical = critical + self.timeout_s = timeout_s + self.max_retries = max_retries + self._fn = fn + + def _execute(self, when: datetime) -> Tuple[str, str]: + metrics = self._fn(when) or {} + # We return metrics via stdout JSON so StageResult.metrics picks + # it up; the Pipeline runner unpacks this for callers that care. + import json as _json # local to keep global imports minimal + return _json.dumps(metrics, default=str), "" + + +__all__ = [ + "Stage", + "StageResult", + "ScriptStage", + "CallableStage", +] diff --git a/Scripts/retrieval/__init__.py b/Scripts/retrieval/__init__.py new file mode 100644 index 0000000..4e54686 --- /dev/null +++ b/Scripts/retrieval/__init__.py @@ -0,0 +1,113 @@ +""" +`Scripts.retrieval` — public API of the retrieval / transformation layer. + +This facade is deliberately **lazy** (PEP 562). Until recently the module +eagerly imported ``query_transform`` / ``qdrant_retriever`` / +``master_retriever`` at package import time, which transitively dragged +``langchain_ollama`` / ``langchain_core`` / ``dotenv`` / heavy ontology +regex tables into every caller — including the CLI's ``status`` and +``ingest --dry-run`` paths which do *not* need the LLM. That made cold +starts slow and broke smoke tests that stub only the pieces they need. + +Rules of the road +----------------- +* **Pure-data types** from :mod:`Scripts.retrieval.schema` load eagerly + because they have no runtime dependencies — importing them is free + and they are referenced almost everywhere. +* **LLM-backed classes** (``QueryTransformer``, ``FinancialHybridRetriever``, + ``MasterRetriever``) load lazily on first attribute access and are + cached into module globals, so subsequent accesses are free. + +Example +------- +>>> from Scripts.retrieval import TimeWindow # eager — fast +>>> from Scripts.retrieval import MasterRetriever # triggers lazy +... # load; cached. +>>> # Equivalent direct-leaf import for agents that want to skip the +>>> # facade entirely (no LLM dep resolution until instance creation): +>>> from Scripts.retrieval.master_retriever import MasterRetriever +""" +from __future__ import annotations + +from importlib import import_module +from typing import TYPE_CHECKING, Any + +# --------------------------------------------------------------------------- +# Eager re-exports: dependency-free data types +# --------------------------------------------------------------------------- +from .schema import ( + ActionDirection, + AgentState, + FormTypeFilter, + FullTransformationResult, + HyDEGeneration, + MetadataExtraction, + QueryIntent, + RetrievedChunk, + SearchMode, + SECMetadata, + SentimentTarget, + SourceType, + SQLResult, + TIME_WINDOW_DAYS, + TimeWindow, + time_window_to_days, +) + +# --------------------------------------------------------------------------- +# Lazy attribute table — resolved on first access via PEP 562 __getattr__ +# --------------------------------------------------------------------------- + +_LAZY_ATTRS: dict[str, tuple[str, str]] = { + # attr_name -> (submodule, export_name) + "QueryTransformer": ("query_transform", "QueryTransformer"), + "FinancialHybridRetriever": ( + "qdrant_retriever", + "FinancialHybridRetriever", + ), + "MasterRetriever": ("master_retriever", "MasterRetriever"), +} + + +def __getattr__(name: str) -> Any: # PEP 562 — runs only on unknown attrs + if name in _LAZY_ATTRS: + submodule, export = _LAZY_ATTRS[name] + module = import_module(f"{__name__}.{submodule}") + obj = getattr(module, export) + globals()[name] = obj # cache so future lookups are free + return obj + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") + + +def __dir__() -> list[str]: # Tooling-friendly completion + return sorted(set(globals().keys()) | set(__all__)) + + +__all__ = [ + # Eager data types + "ActionDirection", + "AgentState", + "FormTypeFilter", + "FullTransformationResult", + "HyDEGeneration", + "MetadataExtraction", + "QueryIntent", + "RetrievedChunk", + "SearchMode", + "SECMetadata", + "SentimentTarget", + "SourceType", + "SQLResult", + "TIME_WINDOW_DAYS", + "TimeWindow", + "time_window_to_days", + # Lazy LLM-backed classes + "QueryTransformer", + "FinancialHybridRetriever", + "MasterRetriever", +] + +if TYPE_CHECKING: # Static analysers only — no runtime cost. + from .master_retriever import MasterRetriever # noqa: F401 + from .qdrant_retriever import FinancialHybridRetriever # noqa: F401 + from .query_transform import QueryTransformer # noqa: F401 diff --git a/Scripts/retrieval/macro_parser.py b/Scripts/retrieval/macro_parser.py new file mode 100644 index 0000000..f378821 --- /dev/null +++ b/Scripts/retrieval/macro_parser.py @@ -0,0 +1,409 @@ +""" +Macro-context utilities with Silver-first macro patch generation. + +Design intent +------------- +The macro markdown is an LLM readability layer, not the deterministic source +of truth. The authoritative numeric contract lives in +`Data/2_Silver_Processed/Macro_History/.../macro_snapshot_*.parquet`. + +This module therefore serves two roles: +1. Ticker extraction helpers used by the retrieval stack. +2. A macro patch builder that promotes Silver macro values into + `silver_context` so Checker/Analyst can consume them directly. + +Primary path: + Silver Macro_History parquet -> values + anchors + schema/status snapshot + +Fallback path: + latest_macro_context.md regex parsing (only when parquet is unavailable) + +The status snapshot is intentionally persisted into `silver_context` so the +retriever/checker pipeline can retain a stable view of: + - which parquet schema was used, + - which symbols were materialized, + - which observation date anchored the patch. +""" +from __future__ import annotations + +import hashlib +import logging +import re +from datetime import date +from pathlib import Path +from typing import Any, Dict, List, Optional, Tuple + +logger = logging.getLogger(__name__) + +__all__ = [ + "TICKER_RE", + "TICKER_STOPWORDS", + "MACRO_LINE_PATTERNS", + "MACRO_GENERATED_RE", + "parse_macro_snapshot", + "build_macro_silver_patch", +] + +_PROJECT_ROOT = Path(__file__).resolve().parents[2] +_MACRO_HISTORY_ROOT = _PROJECT_ROOT / "Data" / "2_Silver_Processed" / "Macro_History" +_MACRO_HISTORY_GLOB = "macro_snapshot_*.parquet" +_MACRO_NUMERIC_FIELDS: tuple[str, ...] = ( + "value", + "daily_change_pct", + "mom_change_pct", + "yoy_change_pct", +) +_MACRO_REQUIRED_COLUMNS: tuple[str, ...] = ( + "retrieval_date", + "observation_date", + "symbol", + "name", + "asset_class", + "value", + "unit", + "frequency", + "daily_change_pct", + "mom_change_pct", + "yoy_change_pct", +) +_SYMBOL_ALIAS_MAP: Dict[str, str] = { + "^GSPC": "GSPC", + "^IXIC": "IXIC", + "^VIX": "VIX", + "DX-Y.NYB": "DXY", + "GLD": "GLD_SPOT", + "SLV": "SLV_SPOT", +} + + +# --------------------------------------------------------------------------- +# Ticker extraction (used by the HyDE "novel ticker" back-injection path) +# --------------------------------------------------------------------------- + +# Regex for ticker-shaped tokens. We deliberately accept 1–5 upper-case +# letters with optional leading "$" (Bloomberg style). Multi-word / +# punctuation tickers (e.g. ^GSPC, BRK.B) are NOT captured here — they +# require a richer tokenizer and almost never appear verbatim in HyDE. +TICKER_RE: re.Pattern = re.compile(r"(? str: + if not symbol: + return "UNKNOWN" + if symbol in _SYMBOL_ALIAS_MAP: + return _SYMBOL_ALIAS_MAP[symbol] + return symbol.lstrip("^").replace("-", "_").replace(".", "_").replace("/", "_") + + +def _latest_macro_parquet() -> Optional[Path]: + if not _MACRO_HISTORY_ROOT.exists(): + return None + files = sorted(_MACRO_HISTORY_ROOT.rglob(_MACRO_HISTORY_GLOB)) + return files[-1] if files else None + + +def _to_float(v: Any) -> Optional[float]: + if v is None: + return None + if isinstance(v, (int, float)): + return round(float(v), 6) + if isinstance(v, str): + s = v.replace(",", "").rstrip("%").strip() + if not s: + return None + try: + return round(float(s), 6) + except ValueError: + return None + return None + + +def _build_macro_patch_from_parquet(anchor_date: date) -> Dict[str, Any]: + """Build the authoritative macro patch from the latest Silver parquet.""" + fp = _latest_macro_parquet() + if fp is None: + return {"values": {}, "lineage_anchors": [], "status": {}} + + try: + import duckdb + except ImportError as exc: + logger.warning("Macro parquet patch unavailable — duckdb import failed: %s", exc) + return {"values": {}, "lineage_anchors": [], "status": {}} + + sql_path = fp.as_posix() + con = duckdb.connect() + try: + schema_rows = con.execute( + f"DESCRIBE SELECT * FROM read_parquet('{sql_path}')" + ).fetchall() + schema_types = {str(col): str(dtype) for col, dtype, *_ in schema_rows} + present_columns = list(schema_types.keys()) + missing_columns = [c for c in _MACRO_REQUIRED_COLUMNS if c not in schema_types] + + latest_obs_row = con.execute( + f"SELECT MAX(observation_date) FROM read_parquet('{sql_path}')" + ).fetchone() + latest_obs = str(latest_obs_row[0]) if latest_obs_row and latest_obs_row[0] is not None else anchor_date.isoformat() + + rows = con.execute( + f""" + SELECT retrieval_date, observation_date, symbol, name, asset_class, + value, unit, frequency, daily_change_pct, mom_change_pct, yoy_change_pct + FROM read_parquet('{sql_path}') + WHERE observation_date = ? + ORDER BY symbol + """, + [latest_obs], + ).fetchall() + finally: + con.close() + + values: Dict[str, float] = {} + lineage: List[str] = [] + symbol_status: Dict[str, Dict[str, Any]] = {} + + for ( + retrieval_date, + observation_date, + symbol, + name, + asset_class, + value, + unit, + frequency, + daily_change_pct, + mom_change_pct, + yoy_change_pct, + ) in rows: + code = _safe_symbol(str(symbol)) + row_map = { + "value": value, + "daily_change_pct": daily_change_pct, + "mom_change_pct": mom_change_pct, + "yoy_change_pct": yoy_change_pct, + } + + numeric_written = False + for field_name, raw_val in row_map.items(): + fv = _to_float(raw_val) + if fv is None: + continue + values[f"{code}_{field_name}"] = fv + numeric_written = True + + # Backward-compatible alias used by existing prompts/checkers: + # prefer MoM for monthly macro rows, otherwise daily change, then YoY. + compat_change = ( + _to_float(mom_change_pct) + if _to_float(mom_change_pct) is not None + else _to_float(daily_change_pct) + if _to_float(daily_change_pct) is not None + else _to_float(yoy_change_pct) + ) + if compat_change is not None: + values[f"{code}_change_pct"] = compat_change + numeric_written = True + + if numeric_written: + anchor_id = f"MACRO_{code}_{observation_date or latest_obs}" + lineage.append(anchor_id) + + symbol_status[code] = { + "symbol": symbol, + "display_name": name, + "asset_class": asset_class, + "unit": unit, + "frequency": frequency, + "retrieval_date": retrieval_date, + "observation_date": observation_date, + } + + schema_hash = hashlib.sha1( + "|".join(f"{k}:{v}" for k, v in sorted(schema_types.items())).encode("utf-8") + ).hexdigest()[:12] + + status = { + "macro_source": "silver_macro_history", + "macro_schema": { + "source_file": str(fp), + "schema_columns": present_columns, + "schema_types": schema_types, + "missing_required_columns": missing_columns, + "required_columns": list(_MACRO_REQUIRED_COLUMNS), + "schema_hash": schema_hash, + "effective_observation_date": latest_obs, + "requested_anchor_date": anchor_date.isoformat(), + "row_count": len(rows), + }, + "macro_symbols": symbol_status, + } + return {"values": values, "lineage_anchors": sorted(set(lineage)), "status": status} + + +def parse_macro_snapshot( + markdown: str, +) -> Tuple[Dict[str, float], Optional[str]]: + """Parse ``latest_macro_context.md`` into silver-like values. + + Returns + ------- + values + Legacy markdown-derived values. This path exists as a fallback only. + The authoritative path is `_build_macro_patch_from_parquet()`. + snapshot_date + The ISO date from the "Generated on" header or ``None``. + Used only by the fallback path. + """ + values: Dict[str, float] = {} + if not markdown: + return values, None + + gen_match = MACRO_GENERATED_RE.search(markdown) + snapshot_date = gen_match.group(1) if gen_match else None + + for pattern, key, has_pct in MACRO_LINE_PATTERNS: + m = pattern.search(markdown) + if not m: + continue + try: + val = float(m.group(1).replace(",", "")) + except (ValueError, IndexError): + continue + values[f"{key}_value"] = val + if has_pct: + try: + pct_raw = m.group(2) + if pct_raw is not None: + values[f"{key}_change_pct"] = float(pct_raw) + except (ValueError, IndexError): + pass + + return values, snapshot_date + + +def build_macro_silver_patch( + macro_md: Optional[str], + anchor_date: date, +) -> Dict[str, Any]: + """Produce the Silver macro patch. + + Primary source: + latest Silver Macro_History parquet + + Fallback source: + `latest_macro_context.md` + + Returned shape: + { + "values": {...}, + "lineage_anchors": [...], + "status": {...} + } + """ + parquet_patch = _build_macro_patch_from_parquet(anchor_date) + if parquet_patch.get("values"): + return parquet_patch + + values, snapshot_date = parse_macro_snapshot(macro_md or "") + if not values: + return {"values": {}, "lineage_anchors": [], "status": {}} + + effective_date = snapshot_date or anchor_date.isoformat() + distinct_codes: set = set() + for k in values.keys(): + if k.endswith("_value"): + distinct_codes.add(k[: -len("_value")]) + elif k.endswith("_change_pct"): + distinct_codes.add(k[: -len("_change_pct")]) + lineage = [f"MACRO_{code}_{effective_date}" for code in sorted(distinct_codes)] + return { + "values": values, + "lineage_anchors": lineage, + "status": { + "macro_source": "macro_markdown_fallback", + "macro_schema": { + "source_file": str(_PROJECT_ROOT / "Data" / "Agent_Context" / "latest_macro_context.md"), + "schema_columns": ["markdown_fallback"], + "schema_types": {"markdown_fallback": "regex_extracted"}, + "missing_required_columns": list(_MACRO_REQUIRED_COLUMNS), + "required_columns": list(_MACRO_REQUIRED_COLUMNS), + "schema_hash": "fallback", + "effective_observation_date": effective_date, + "requested_anchor_date": anchor_date.isoformat(), + "row_count": len(distinct_codes), + }, + "macro_symbols": {}, + }, + } diff --git a/Scripts/retrieval/master_retriever.py b/Scripts/retrieval/master_retriever.py new file mode 100644 index 0000000..ef58c59 --- /dev/null +++ b/Scripts/retrieval/master_retriever.py @@ -0,0 +1,803 @@ +""" +Scripts/retrieval/master_retriever.py + +Financial RAG orchestration layer (Master Retriever). + +Design patterns: Facade + Wrapper. + +Core capabilities (this version): +1. Prompt decoupling — all prompts live under Scripts/core/. +2. Per-engine timeouts — Gold (vector) and Silver (SQL) get independent + asyncio.wait_for budgets so one slow engine never stalls the other. +3. Graceful degradation — engine failures surface as structured error dicts + so the Analyst can honestly say "INSUFFICIENT DATA" instead of hallucinating. +4. End-to-end telemetry — per-node latency is persisted on the return payload. +5. **Semantic-SQL Parallelism** (new): under `sql_only` we also fire HyDE so + the Analyst has LLM prior knowledge to hedge when Parquet returns empty. +6. **HyDE Entity Back-Injection** (new): under `vector_only` we regex-extract + tickers from the HE paragraph, intersect with the ontology whitelist, and + trigger compensation Silver queries for the *novel* tickers. This turns + "no data" into "Silver penetration via semantic expansion". +7. **HE Guardrail** (new): HE-extracted tickers MUST pass the ontology + whitelist before they can touch Parquet. No whitelist, no SQL. +8. **Source-channel tagging** (new): every slice of silver_context is tagged + with `source_channel ∈ {primary, hyde_expansion}` so the Checker agent + can relax numeric audit for HE-triggered data (avoiding false fatal). +9. **Time-range audit** (new): the final `start_date` / `end_date` used by + Silver is exposed on the return payload so the Analyst can print the + compliance footer ("data interval: YYYY-MM-DD ~ YYYY-MM-DD"). +""" + +import asyncio +import copy +import logging +import os +import re +import time +from datetime import date, timedelta +from pathlib import Path +from typing import Any, Dict, List, Optional + +from dotenv import load_dotenv +from langchain_core.prompts import ChatPromptTemplate +from langchain_ollama import ChatOllama + +from Scripts.core.few_shot_intent import INTENT_FEW_SHOT_EXAMPLES +from Scripts.core.intent_router_prompt_templates import ROUTER_SYSTEM_PROMPT +from Scripts.retrieval.qdrant_retriever import FinancialHybridRetriever +from Scripts.retrieval.query_transform import QueryTransformer +from Scripts.retrieval.schema import ( + FullTransformationResult, + MetadataExtraction, + QueryIntent, + TimeWindow, + # Re-exported global time-window policy. The physical constants live in + # schema.py to keep Gold/Silver free of a circular import against this + # facade; `from Scripts.retrieval.master_retriever import TIME_WINDOW_DAYS` + # still works for downstream callers. + TIME_WINDOW_DAYS, + time_window_to_days, +) +from Scripts.retrieval.sql_tools import SilverSQLTool +from Scripts.retrieval.time_adapter import ( + SourceTimeKey, + TimePredicate, + compile_all as compile_all_time_predicates, +) + +# Public re-export surface — keeps `__all__` explicit for static analysers. +__all__ = ["MasterRetriever", "TIME_WINDOW_DAYS", "time_window_to_days"] + +load_dotenv() +logger = logging.getLogger(__name__) + +# --------------------------------------------------------------------------- +# Module-level constants (tuned to real-world Ollama throughput, not defaults) +# --------------------------------------------------------------------------- + +# Top_k for the Gold probe that runs when the router chose sql_only. Purpose: +# if SQL succeeds the LLM will prefer precise numerics; if SQL fails there is +# always at least one news anchor. This does NOT change business routing. +_SQL_ONLY_FALLBACK_TOPK = 2 + +# Max number of novel tickers the HE back-injection can promote to a real +# Silver compensation query. A hard cap protects the silver_timeout budget: +# three tickers × ~8s each is already on the order of one-third of a browser's +# patience threshold. +_HE_NOVEL_TICKERS_CAP = int(os.getenv("HE_NOVEL_TICKERS_CAP", "3")) + + +# --------------------------------------------------------------------------- +# Ticker / macro parsing — delegated to `Scripts.retrieval.macro_parser`. +# +# Rationale: the regex tables + macro markdown parser are orthogonal to +# the retrieval orchestration logic in this file. Moving them to a +# dedicated module keeps `master_retriever.py` focused on *wiring* +# (router + Qdrant + SQL) while enabling isolated unit tests. +# +# The underscored aliases below are preserved for backwards compatibility +# with any downstream code or test that imported the private names from +# this module; new callers should import directly from +# `Scripts.retrieval.macro_parser`. +# --------------------------------------------------------------------------- +from Scripts.retrieval.macro_parser import ( # noqa: E402 — kept near usage + MACRO_GENERATED_RE as _MACRO_GENERATED_RE, + MACRO_LINE_PATTERNS as _MACRO_LINE_PATTERNS, + TICKER_RE as _TICKER_RE, + TICKER_STOPWORDS as _TICKER_STOPWORDS, + build_macro_silver_patch as _build_macro_silver_patch, + parse_macro_snapshot as _parse_macro_snapshot, +) + + +class MasterRetriever: + """Facade over QueryTransformer + Qdrant + Silver SQL with per-route + retrieval plans and full HyDE semantic-hedge support. + """ + + def __init__(self): + # --- 1. Engine initialisation (heavy) --- + self.qdrant = FinancialHybridRetriever() + self.sql_tool = SilverSQLTool() + self.transformer = QueryTransformer() + + # --- 2. Router LLM configuration (cheap, short responses) --- + self.router_llm = ChatOllama( + model=os.getenv("OLLAMA_ROUTER_MODEL", "llama3:latest"), + temperature=float(os.getenv("ROUTER_TEMPERATURE", 0.0)), + num_predict=20, + ) + + # --- 3. Runtime knobs (env-tunable without code change) --- + self.gold_timeout = float(os.getenv("GOLD_TIMEOUT", 10.0)) + self.silver_timeout = float(os.getenv("SILVER_TIMEOUT", 10.0)) + + logger.info( + f"🏛️ MasterRetriever ready | Gold_TO: {self.gold_timeout}s | " + f"Silver_TO: {self.silver_timeout}s | HE_novel_cap: {_HE_NOVEL_TICKERS_CAP}" + ) + + # ====================================================================== + # A. Intent classification (unchanged — proven in production) + # ====================================================================== + + async def _classify_intent(self, query: str) -> QueryIntent: + """Lightweight intent routing after prompt decoupling.""" + prompt = ChatPromptTemplate.from_template(ROUTER_SYSTEM_PROMPT) + chain = prompt | self.router_llm + + start_t = time.time() + try: + response = await chain.ainvoke({ + "examples": INTENT_FEW_SHOT_EXAMPLES, + "query": query, + }) + intent_str = response.content.strip().lower() + + route = "hybrid_both" + for p in ["sql_only", "vector_only", "hybrid_both"]: + if p in intent_str: + route = p + break + + logger.info(f"⚡ [Telemetry] Router choice: {route} | Cost: {time.time() - start_t:.3f}s") + return QueryIntent(primary_route=route) + except Exception as e: + logger.error(f"❌ [Router Error] {e}. Falling back to hybrid.") + return QueryIntent(primary_route="hybrid_both") + + # ====================================================================== + # B. Engine wrappers (per-engine timeouts + exception isolation) + # ====================================================================== + + async def _fetch_gold_with_telemetry( + self, + query: str, + transform_result: FullTransformationResult, + top_k: int = 5, + ) -> List[Any]: + """Gold wrapper with independent timeout + exception isolation. + + Forwards the live `time_predicates` dict (compiled once upstream in + `_compute_time_range`) so Qdrant can build source-specific time + filters rather than rederiving the window on every call. + """ + t0 = time.time() + predicates = getattr(self, "_current_predicate_set", None) + try: + res = await asyncio.wait_for( + self.qdrant.retrieve_async( + original_query=query, + transform_result=transform_result, + top_k=top_k, + time_predicates=predicates, + ), + timeout=self.gold_timeout, + ) + logger.debug(f"📊 [Telemetry] Gold engine finished in {time.time() - t0:.3f}s (top_k={top_k})") + return res + except asyncio.TimeoutError: + logger.warning(f"⚠️ [Gold Timeout] Exceeded {self.gold_timeout}s. Returning empty context.") + return [] + except Exception as e: + logger.error(f"❌ [Gold Failure] {repr(e)}") + return [] + + async def _fetch_silver_with_telemetry(self, metadata: MetadataExtraction) -> Dict[str, Any]: + """Silver wrapper with structured degradation on failure. + + Threads the live `time_predicates` dict through to `SilverSQLTool` + so handler-side time alignment (DAILY weekend-safe, MONTHLY month- + widened) lands on the same compiled predicate the Gold retriever + consumes — one window, one audit trail. + """ + t0 = time.time() + predicates = getattr(self, "_current_predicate_set", None) + try: + res = await asyncio.wait_for( + self.sql_tool.query_parquet_by_metadata( + metadata, time_predicates=predicates, + ), + timeout=self.silver_timeout, + ) + logger.debug(f"📊 [Telemetry] Silver engine finished in {time.time() - t0:.3f}s") + return res or {"values": {}, "lineage_anchors": []} + except asyncio.TimeoutError: + logger.warning(f"⚠️ [Silver Timeout] Exceeded {self.silver_timeout}s.") + return {"values": {}, "lineage_anchors": [], "error": "Timeout"} + except Exception as e: + logger.error(f"❌ [Silver Failure] {repr(e)}") + return {"values": {}, "lineage_anchors": [], "error": str(type(e).__name__)} + + # ====================================================================== + # C. NEW helpers — Time-range audit / HE back-injection / compensation + # ====================================================================== + + def _compute_time_range( + self, + metadata: MetadataExtraction, + default_applied: bool, + ) -> Dict[str, Any]: + """Derive the authoritative (anchor, start, end) triple for this query. + + Uses SilverSQLTool's Dynamic Time Anchor so the date aligns with the + last successfully ingested Silver partition (survives weekends, holidays, + backfills). Exposed on the return payload so the Analyst can emit a + compliance footer verbatim, e.g. + + "数据统计区间: 2025-10-20 ~ 2026-04-18 (window_days=180, default)" + + Also compiles a **per-source `TimePredicate` set** (news / SEC / GPR / + options / macro / silver_gpr) via `time_adapter.compile_all`. These + predicates are attached to the payload under `source_predicates` so + the Gold retriever and every Silver handler can apply a time window + aligned to its own physical schema (MONTHLY widened, DAILY weekend- + safe, EVENT respects the raw semantic window) without duplicating + the widening logic across layers. See docs/Data_source_docs/ + Time_Schema_Audit.md for the full per-source contract. + """ + tw_value = getattr(metadata.time_window, "value", metadata.time_window) + window_days = time_window_to_days(metadata.time_window, default=180) + + try: + # "options" is the most common Silver dataset; the anchor logic + # falls back to date.today() if the runtime state is missing. + anchor: date = self.sql_tool._get_anchor_date("options") + except Exception as e: + logger.warning(f"time_range: anchor lookup failed, defaulting to today(): {e}") + anchor = date.today() + + start = anchor - timedelta(days=window_days) + + # Compile per-source predicates once; they ride along the payload so + # audit logs capture exactly which window hit each source. + predicate_set = compile_all_time_predicates( + metadata.time_window, anchor, + label=str(tw_value) if tw_value else None, + ) + serialised_predicates = { + key.value: pred.to_dict() for key, pred in predicate_set.items() + } + + payload = { + "time_window_label": str(tw_value) if tw_value else "past_six_months", + "window_days": window_days, + "anchor_date": anchor.isoformat(), + "start_date": start.isoformat(), + "end_date": anchor.isoformat(), + "is_default_window_applied": bool(default_applied), + # Per-source compiled predicates (serialised dict form). Live, + # runtime-usable objects are kept on `self._predicate_set_cache` + # for the retrievers via `_current_predicate_set`. + "source_predicates": serialised_predicates, + } + logger.info( + f"🕒 [TimeRange] {payload['start_date']} → {payload['end_date']} " + f"(label={payload['time_window_label']}, days={window_days}, " + f"default_applied={default_applied}) | sources_compiled=" + f"{list(serialised_predicates.keys())}" + ) + # Stash the live dict so `retrieve()` can pass it to Gold/Silver + # without re-running the compiler. Cleared at the end of each call. + self._current_predicate_set: Dict[SourceTimeKey, TimePredicate] = predicate_set + return payload + + def _extract_hyde_entities( + self, + hyde_paragraph: str, + seed_tickers: List[str], + ) -> Dict[str, Any]: + """Back-inject tickers mentioned in HyDE, filtered by ontology whitelist. + + Pipeline: + 1. Regex `[A-Z]{1,5}` candidates + 2. Subtract `_TICKER_STOPWORDS` (IV, CPI, THE, …) + 3. Intersect with `self.transformer.allowed_tickers` (HE Guardrail) + 4. Subtract the seed tickers already on the metadata + 5. Cap at `_HE_NOVEL_TICKERS_CAP` + + Returns a structured payload so the Analyst can see: + - What HE thought of + - What survived the guardrail + - What is *novel* (i.e. should trigger compensation SQL) + """ + paragraph = hyde_paragraph or "" + raw_candidates = set(m.group(1) for m in _TICKER_RE.finditer(paragraph)) + post_stopword = raw_candidates - _TICKER_STOPWORDS + + allowed = set(getattr(self.transformer, "allowed_tickers", []) or []) + whitelisted = sorted(post_stopword & allowed) + + seed_set = {t.upper() for t in (seed_tickers or [])} + novel = [t for t in whitelisted if t not in seed_set][:_HE_NOVEL_TICKERS_CAP] + + if novel: + logger.info( + f"🧠 [HyDE-BackInjection] Novel tickers (whitelisted): {novel} " + f"| raw={sorted(raw_candidates)} | allowed_hit={whitelisted}" + ) + + return { + "paragraph": paragraph, + "raw_candidates": sorted(raw_candidates), + "whitelisted": whitelisted, + "novel_tickers": novel, + } + + async def _run_silver_compensation( + self, + base_metadata: MetadataExtraction, + novel_tickers: List[str], + ) -> Dict[str, Any]: + """Fire one Silver query per HE-derived novel ticker and aggregate. + + Rationale: + - SilverSQLTool consumes `metadata.tickers[0]` (see sql_tools.py). + So we dispatch N independent calls in parallel rather than one + multi-ticker call. + - Each sub-query reuses the SAME timeout budget as the primary + Silver task (`_fetch_silver_with_telemetry`) — no new knob, + no new surprise. + - Deep-copies the base metadata so audit logs never conflate + "primary intent" with "HE-derived probe". + + Returns a dict with `source_channel = hyde_expansion` so the Checker + agent can relax numeric audit for this slice (these values were NOT + requested by the user). + """ + if not novel_tickers: + return { + "values": {}, + "lineage_anchors": [], + "source_channel": "hyde_expansion", + "trigger_entities": [], + } + + tasks = [] + for tk in novel_tickers: + m_copy = base_metadata.model_copy(deep=True) + m_copy.tickers = [tk.upper()] + tasks.append(self._fetch_silver_with_telemetry(m_copy)) + + results = await asyncio.gather(*tasks, return_exceptions=True) + + aggregated: Dict[str, Any] = { + "values": {}, + "lineage_anchors": [], + "source_channel": "hyde_expansion", + "trigger_entities": list(novel_tickers), + "per_ticker_errors": {}, + } + for tk, r in zip(novel_tickers, results): + if isinstance(r, Exception): + aggregated["per_ticker_errors"][tk] = str(type(r).__name__) + continue + if not isinstance(r, dict): + continue + if r.get("error"): + aggregated["per_ticker_errors"][tk] = r["error"] + aggregated["values"].update(r.get("values", {})) + aggregated["lineage_anchors"].extend(r.get("lineage_anchors", [])) + + logger.info( + f"🔁 [HyDE-Compensation] tickers={novel_tickers} | " + f"values={len(aggregated['values'])} | " + f"anchors={len(aggregated['lineage_anchors'])} | " + f"errors={aggregated['per_ticker_errors'] or '{}'}" + ) + return aggregated + + # ====================================================================== + # D. Main entry — Orchestrator with per-route plan + # ====================================================================== + + async def retrieve(self, user_query: str) -> Dict[str, Any]: + """Main pipeline: intent → transform → per-route concurrent fetch → assemble. + + Per-route plan (in plain English): + + hybrid_both : full Gold(top_k=5) + full Silver(metadata) + + optional Silver compensation on novel HE tickers + + vector_only : full Gold(top_k=5) as primary + + Silver compensation ONLY via HE back-injection + (the whole point of "Entity Back-Injection") + + sql_only : full Silver(metadata) as primary + + tiny Gold probe(top_k=2) as news-anchor safety + + HyDE paragraph surfaced as `hyde_anticipation` for + the Analyst's LLM prior-knowledge hedge + """ + overall_start = time.time() + + # ================================================================== + # 1. Intent classification + # ================================================================== + intent = await self._classify_intent(user_query) + route = intent.primary_route + + # ================================================================== + # 2. Two-stage transform (metadata + HyDE) + # ================================================================== + transform_start = time.time() + transform_res = await self.transformer.transform_for_dual_rag(user_query, intent) + logger.info(f"🧠 [Telemetry] Transform cost: {time.time() - transform_start:.3f}s") + + metadata = transform_res.metadata if transform_res else None + if metadata is None: + # Transformer failure is unrecoverable here — return a structured + # empty payload so the Analyst can surface INSUFFICIENT DATA. + return self._empty_payload( + intent=route, + reason="transform_failed", + start_ts=overall_start, + ) + + # ================================================================== + # 3. Time-window guardrail + canonical TimeRange + # ================================================================== + # schema.handle_empty_window already forces PAST_SIX_MONTHS on + # invalid/missing input (so this branch almost never fires). We + # double-check here so a future schema refactor can't silently regress. + default_applied = False + if not metadata.time_window: + metadata.time_window = TimeWindow.PAST_SIX_MONTHS + default_applied = True + logger.info("🕒 [TimePolicy] Applied default window: past_six_months (180d)") + + time_range = self._compute_time_range(metadata, default_applied=default_applied) + + # ================================================================== + # 4. HyDE Entity Back-Injection (regex + whitelist) + # ================================================================== + hyde_info = self._extract_hyde_entities( + hyde_paragraph=transform_res.hyde.hyde_paragraph if transform_res.hyde else "", + seed_tickers=metadata.tickers, + ) + novel_tickers: List[str] = hyde_info["novel_tickers"] + + # ================================================================== + # 5. Build per-route task plan (all three may be None) + # ================================================================== + gold_task = None + silver_task = None + compensation_task = None + + if route == "hybrid_both": + gold_task = self._fetch_gold_with_telemetry(user_query, transform_res, top_k=5) + if metadata.tickers: + silver_task = self._fetch_silver_with_telemetry(metadata) + # Optional HE compensation — only fires when the HE introduced + # NEW tickers the user didn't mention. + if novel_tickers: + compensation_task = self._run_silver_compensation(metadata, novel_tickers) + + elif route == "vector_only": + gold_task = self._fetch_gold_with_telemetry(user_query, transform_res, top_k=5) + # Primary Silver is OFF by design for vector_only; compensation is + # the ONLY path into Parquet — realises "Entity Back-Injection". + if novel_tickers: + compensation_task = self._run_silver_compensation(metadata, novel_tickers) + elif metadata.tickers: + # If HE produced nothing novel but the user explicitly named + # tickers, still run Silver as a courtesy (labelled primary). + silver_task = self._fetch_silver_with_telemetry(metadata) + + elif route == "sql_only": + # Primary = Silver; Gold is a tiny fallback probe. + if metadata.tickers: + silver_task = self._fetch_silver_with_telemetry(metadata) + gold_task = self._fetch_gold_with_telemetry( + user_query, transform_res, top_k=_SQL_ONLY_FALLBACK_TOPK + ) + # HE compensation is still available when HE produces novel tickers — + # realises "Semantic-SQL Parallelism". The hyde_anticipation payload + # below also exposes the full HyDE paragraph to the Analyst so the + # LLM prior knowledge can fill the gap when Parquet is empty. + if novel_tickers: + compensation_task = self._run_silver_compensation(metadata, novel_tickers) + + else: + # Unknown route — degrade to hybrid. + logger.warning(f"[Route] Unknown primary_route={route} — falling back to hybrid_both.") + gold_task = self._fetch_gold_with_telemetry(user_query, transform_res, top_k=5) + if metadata.tickers: + silver_task = self._fetch_silver_with_telemetry(metadata) + + # ================================================================== + # 6. Execute plan concurrently with per-task isolation + # ================================================================== + awaitables = [] + slots: List[str] = [] + for name, t in (("gold", gold_task), ("silver", silver_task), ("compensation", compensation_task)): + if t is not None: + awaitables.append(t) + slots.append(name) + + results = await asyncio.gather(*awaitables, return_exceptions=True) if awaitables else [] + + # ================================================================== + # 7. Assemble the final context + # ================================================================== + final_context: Dict[str, Any] = { + "intent": route, + "metadata": metadata, + "time_range": time_range, + "gold_context": [], + "silver_context": { + "values": {}, + "lineage_anchors": [], + "source_channel": "primary", + }, + "hyde_anticipation": { + "paragraph": hyde_info["paragraph"], + "rerank_query": (transform_res.hyde.rerank_query if transform_res.hyde else ""), + "raw_candidates": hyde_info["raw_candidates"], + "whitelisted_tickers": hyde_info["whitelisted"], + "novel_tickers": novel_tickers, + # Only sql_only lifts the HE paragraph as a semantic hedge; + # the other routes still expose it for auditability but the + # Analyst will weight it lower. + "source_channel": "semantic_hedge" if route == "sql_only" else "reference", + }, + "status": "success", + "latency_stats": {}, + } + + partial_failure = False + for slot, res in zip(slots, results): + if isinstance(res, Exception): + logger.critical(f"🔥 Slot {slot} raised: {repr(res)}") + partial_failure = True + continue + + if slot == "gold": + final_context["gold_context"] = res or [] + elif slot == "silver": + primary_silver = res or {"values": {}, "lineage_anchors": []} + if primary_silver.get("error"): + partial_failure = True + final_context["silver_context"] = { + "values": primary_silver.get("values", {}), + "lineage_anchors": primary_silver.get("lineage_anchors", []), + "source_channel": "primary", + **( + {"error": primary_silver["error"]} + if primary_silver.get("error") else {} + ), + } + elif slot == "compensation": + comp = res or {} + # Physical separation: HE-triggered data lives under + # `silver_context.compensation`, NOT merged into primary + # values. Downstream the Checker agent reads this key to + # relax numeric drift rules for HE data. + final_context["silver_context"]["compensation"] = { + "values": comp.get("values", {}), + "lineage_anchors": comp.get("lineage_anchors", []), + "source_channel": "silver_layer_via_hyde_expansion", + "trigger_entities": comp.get("trigger_entities", []), + "per_ticker_errors": comp.get("per_ticker_errors", {}), + } + + if partial_failure: + final_context["status"] = "partial_failure" + + # ================================================================== + # 7.5 Macro → Silver anchor injection (Root Cause A fix, 2026-04-22) + # ================================================================== + # Promote macro data into Silver context. The primary source is now + # Silver Macro_History parquet (authoritative numeric truth); markdown + # is only a fallback if parquet is unavailable. This gives the Analyst + # citable MACRO_* anchors while preserving schema/status metadata for + # downstream deterministic checking and drift audits. + try: + macro_md = self._read_macro_snapshot() + anchor_for_macro = date.fromisoformat(time_range["anchor_date"]) \ + if time_range and time_range.get("anchor_date") else date.today() + macro_patch = _build_macro_silver_patch(macro_md, anchor_for_macro) + if macro_patch["values"]: + sv = final_context["silver_context"] + sv.setdefault("values", {}).update(macro_patch["values"]) + existing_anchors = sv.setdefault("lineage_anchors", []) + patch_status = macro_patch.get("status") or {} + if patch_status: + existing_status = sv.setdefault("status", {}) + for k, v in patch_status.items(): + if isinstance(v, dict) and isinstance(existing_status.get(k), dict): + existing_status[k].update(v) + else: + existing_status[k] = v + # De-duplicate while preserving ordering of the existing anchors. + seen = set(existing_anchors) + for a in macro_patch["lineage_anchors"]: + if a not in seen: + existing_anchors.append(a) + seen.add(a) + logger.info( + f"🌐 [MacroSilverPatch] injected {len(macro_patch['values'])} values + " + f"{len(macro_patch['lineage_anchors'])} MACRO_* anchors." + ) + except Exception as e: + # Non-fatal: the pipeline still produces a full context without + # macro anchors; the Analyst simply loses macro citability. + logger.warning(f"MacroSilverPatch failed ({type(e).__name__}): {e}") + + # ================================================================== + # 7.6 GPR always-on patch (Root Cause gap-2 fix, 2026-04-23) + # ================================================================== + # Inject the latest GPR row unconditionally — previously this only + # ran when the query routed to _handle_geopolitical_analysis (i.e. + # user explicitly asked about geopolitics). The Analyst prompt's + # MACRO_CHAIN_DIRECTIVE mandates a "GPR index" mention in the Macro + # Regime Snapshot section regardless of query type, so the anchor + # must always be available for citation. + try: + import copy as _copy + gpr_result = self.sql_tool._handle_geopolitical_analysis( + ticker="GPR", meta=metadata + ) + if gpr_result and gpr_result.get("values"): + sv = final_context["silver_context"] + sv.setdefault("values", {}).update(gpr_result["values"]) + existing = set(sv.setdefault("lineage_anchors", [])) + for a in gpr_result.get("lineage_anchors", []): + if a not in existing: + sv["lineage_anchors"].append(a) + existing.add(a) + logger.info( + f"🌍 [GPRPatch] injected {len(gpr_result['values'])} values " + f"+ {len(gpr_result.get('lineage_anchors', []))} GPR anchors." + ) + except Exception as e: + logger.warning(f"GPRPatch failed ({type(e).__name__}): {e}") + + # ================================================================== + # 7.7 Macro Parquet full-scan patch (Root Cause gap-1 fix, 2026-04-23) + # ================================================================== + # Read ALL symbols from Macro_History for the latest observation date + # and inject them into silver_context. This supersedes the markdown + # regex parser for any symbol that parquet already covers (parquet wins + # on precision) and adds long-tail symbols the regex never handled. + try: + macro_glob = self.sql_tool.macro_glob + macro_query = f""" + SELECT symbol, value, daily_change_pct, mom_change_pct, observation_date + FROM read_parquet('{macro_glob}') + WHERE observation_date = ( + SELECT MAX(observation_date) FROM read_parquet('{macro_glob}') + ) + """ + rows = self.sql_tool.conn.execute(macro_query).fetchall() + if rows: + sv = final_context["silver_context"] + pq_values: dict = {} + pq_anchors: list = [] + existing_anchors = set(sv.setdefault("lineage_anchors", [])) + for sym, val, daily_chg, mom_chg, obs_date in rows: + # Sanitise symbol for use as a dict key / anchor name. + safe = sym.lstrip("^").replace("-", "_").replace(".", "_") + if val is not None: + pq_values[f"{safe}_value"] = round(float(val), 4) + chg = mom_chg if mom_chg is not None else daily_chg + if chg is not None: + pq_values[f"{safe}_change_pct"] = round(float(chg), 4) + anchor_id = f"MACRO_{safe}_{obs_date}" + if anchor_id not in existing_anchors: + pq_anchors.append(anchor_id) + existing_anchors.add(anchor_id) + sv["values"].update(pq_values) + sv["lineage_anchors"].extend(pq_anchors) + logger.info( + f"📊 [MacroParquetPatch] injected {len(pq_values)} values " + f"+ {len(pq_anchors)} anchors from {len(rows)} Macro symbols." + ) + except Exception as e: + logger.warning(f"MacroParquetPatch failed ({type(e).__name__}): {e}") + + # ================================================================== + # 7.8 Write immutable silver_context_frozen (P1 fix, 2026-04-23) + # ================================================================== + # After ALL patch steps are complete, snapshot the Silver context so + # CheckerAgent always has a stable, rescue-independent ground truth. + # Rescue passes may still update `silver_context` (used by the NEXT + # analyst revision for additive data), but the Checker's deterministic + # numeric audit uses `silver_context_frozen` exclusively — preventing + # atm_iv oscillation and cross-revision anchor drift. + try: + import copy as _copy + final_context["silver_context_frozen"] = _copy.deepcopy( + final_context["silver_context"] + ) + except Exception as e: + logger.warning(f"silver_context_frozen deepcopy failed ({type(e).__name__}): {e}") + final_context["silver_context_frozen"] = None + + final_context["latency_stats"]["total_e2e"] = f"{time.time() - overall_start:.3f}s" + logger.info( + f"✅ [Master Retriever] route={route} | E2E: {final_context['latency_stats']['total_e2e']} " + f"| status={final_context['status']} | HE_compensation=" + f"{'YES' if novel_tickers else 'NO'}" + ) + return final_context + + # ====================================================================== + # D.5 Utility — macro snapshot loader (lookup, cached per process) + # ====================================================================== + + _MACRO_SNAPSHOT_CACHE: Optional[str] = None + _MACRO_SNAPSHOT_MTIME: Optional[float] = None + + def _read_macro_snapshot(self) -> Optional[str]: + """Read `Data/Agent_Context/latest_macro_context.md` with a per-process + mtime cache. Router also reads this file for the Analyst prompt, but + we re-read here so master_retriever's Silver patch stays self- + contained (retriever owns the silver_context contract end-to-end). + + Returns None if the file is absent — `_build_macro_silver_patch` + then no-ops cleanly. Any IO error is swallowed: a missing or + malformed macro snapshot must NEVER take down retrieval. + """ + try: + project_root = Path(__file__).resolve().parents[2] + fp = project_root / "Data" / "Agent_Context" / "latest_macro_context.md" + if not fp.exists(): + return None + mtime = fp.stat().st_mtime + if ( + self._MACRO_SNAPSHOT_CACHE is not None + and self._MACRO_SNAPSHOT_MTIME == mtime + ): + return self._MACRO_SNAPSHOT_CACHE + content = fp.read_text(encoding="utf-8") + # Cache on the instance (class attribute holder) so concurrent + # calls within the same process reuse the parsed result. + MasterRetriever._MACRO_SNAPSHOT_CACHE = content + MasterRetriever._MACRO_SNAPSHOT_MTIME = mtime + return content + except Exception as e: + logger.debug(f"_read_macro_snapshot: non-fatal {type(e).__name__}: {e}") + return None + + # ====================================================================== + # E. Utility — structured empty payload on hard failure + # ====================================================================== + + def _empty_payload(self, intent: str, reason: str, start_ts: float) -> Dict[str, Any]: + """Return a fully-typed, Analyst-safe payload when Transform blows up.""" + logger.error(f"❌ [Master Retriever] Hard failure: {reason}") + return { + "intent": intent, + "metadata": None, + "time_range": None, + "gold_context": [], + "silver_context": { + "values": {}, + "lineage_anchors": [], + "source_channel": "primary", + "error": reason, + }, + "hyde_anticipation": None, + "status": "partial_failure", + "latency_stats": {"total_e2e": f"{time.time() - start_ts:.3f}s"}, + } diff --git a/Scripts/retrieval/qdrant_retriever.py b/Scripts/retrieval/qdrant_retriever.py new file mode 100644 index 0000000..a4e1f4f --- /dev/null +++ b/Scripts/retrieval/qdrant_retriever.py @@ -0,0 +1,645 @@ +""" +Scripts/retrieval/qdrant_retriever.py + +Industrial-grade dual-track retriever (Gold Layer - asymmetric hybrid retriever) +Senior Architect Version: RRF Fusion, Defensive Enum Extraction, Exception Tracing +""" + +import logging +import sys +import os +import json +import time +import asyncio +from typing import List, Optional, Dict, Any +from datetime import datetime, timedelta +from pathlib import Path +from dotenv import load_dotenv + +project_root = str(Path(__file__).resolve().parents[2]) +if project_root not in sys.path: + sys.path.insert(0, project_root) + +# Load environment variables (including model cache related settings). +load_dotenv(os.path.join(project_root, ".env")) + +from qdrant_client import QdrantClient, models +from fastembed import SparseTextEmbedding +from sentence_transformers import CrossEncoder + +try: + # Prefer package-relative imports when used as part of Scripts.retrieval. + from ..vector_store.connection import get_qdrant_client, get_embedding_model + from .schema import ( + RetrievedChunk, SourceType, FullTransformationResult, TimeWindow, ActionDirection, SentimentTarget, + TIME_WINDOW_DAYS, + ) + from ..core.financial_ontology import ( + EVENT_KEYWORDS_MAPPING, NEWS_TOPICS, normalize_news_topic, + ) + from .time_adapter import ( + SourceTimeKey, + TimePredicate, + union_epoch_range, + ) +except ImportError as e: + try: + # Fallback to absolute imports when this file is executed directly. + from Scripts.vector_store.connection import get_qdrant_client, get_embedding_model + from Scripts.retrieval.schema import ( + RetrievedChunk, SourceType, FullTransformationResult, TimeWindow, ActionDirection, SentimentTarget, + TIME_WINDOW_DAYS, + ) + from Scripts.core.financial_ontology import ( + EVENT_KEYWORDS_MAPPING, NEWS_TOPICS, normalize_news_topic, + ) + from Scripts.retrieval.time_adapter import ( + SourceTimeKey, + TimePredicate, + union_epoch_range, + ) + except ImportError: + print(f"❌ Initialization Error: {e}") + sys.exit(1) + +logger = logging.getLogger("QdrantRetriever") + +class FinancialHybridRetriever: + _instance = None # Singleton instance for shared model/client reuse. + + def __new__(cls, *args, **kwargs): + if cls._instance is None: + cls._instance = super(FinancialHybridRetriever, cls).__new__(cls) + cls._instance._is_initialized = False + return cls._instance + + def __init__(self, collection_name: str = "financial_rag_gold"): + if getattr(self, "_is_initialized", False): + return + + self.collection_name = collection_name + self.client = get_qdrant_client() + + device = os.getenv("RETRIEVER_DEVICE", "cpu") + threads = int(os.getenv("FASTEMBED_THREADS", 4)) + + logger.info("Initializing Models for Retrieval Pipeline (Using Cached Weights)...") + + self.dense_model = get_embedding_model() + sparse_model_name = os.getenv("SPARSE_MODEL_NAME", "prithivida/Splade_PP_en_v1") + self.sparse_model = SparseTextEmbedding(model_name=sparse_model_name,threads=threads) + + reranker_model_name = os.getenv("RERANKER_MODEL_NAME", "BAAI/bge-reranker-v2-m3") + self.reranker = CrossEncoder(reranker_model_name, device=device) + + logger.info(f"✅ Models initialized. Reranker: {reranker_model_name}") + self._is_initialized = True + + # ------------------------------------------------------------------ + # Topic derivation — bridges LLM metadata to news_scraper's `topic` field. + # ------------------------------------------------------------------ + @staticmethod + def _derive_news_topics(metadata: Any) -> List[str]: + """Return the news `topic` values worth filtering on for this query. + + Resolution order (most-specific first): + 1. `event_keyword` → category via EVENT_KEYWORDS_MAPPING. + 2. The category itself, if the LLM wrote one that already matches + a canonical news topic (covers "macro_central_banks" etc.). + 3. Empty list → no topic constraint. + + The result is normalised to the news-scraper topic form via + `normalize_news_topic` so queries carrying the short alias + (e.g. "precious_metals_spot") still match ingested docs written + with the long form ("asset_precious_metals_spot"). + """ + candidates: List[str] = [] + ev = getattr(metadata, "event_keyword", "") or "" + if ev: + mapped = EVENT_KEYWORDS_MAPPING.get(ev.strip().lower(), "") + if mapped: + candidates.append(mapped) + + # Some Extractor outputs put the category verbatim into event_keyword + # (e.g. "macro_central_banks"). Try to land that directly. + if ev: + candidates.append(ev.strip().lower()) + + normalised = [] + for c in candidates: + n = normalize_news_topic(c) + if n and n in NEWS_TOPICS and n not in normalised: + normalised.append(n) + return normalised + + # ------------------------------------------------------------------ + # Time-predicate helpers (Gold uses the union of per-source windows) + # ------------------------------------------------------------------ + # Mapping from Qdrant `source_type` payload value → SourceTimeKey. + # Used to pick exactly the predicates relevant to this query so the + # union range is never wider than needed. + _SOURCE_TYPE_TO_KEY: Dict[str, "SourceTimeKey"] = { + "news": SourceTimeKey.GOLD_NEWS, + "sec": SourceTimeKey.GOLD_SEC, + "gpr": SourceTimeKey.GOLD_GPR, + } + + def _select_gold_predicates( + self, + source_vals: List[str], + time_predicates: Optional[Dict["SourceTimeKey", "TimePredicate"]], + ) -> List["TimePredicate"]: + """Pick the predicates that actually apply to the selected Gold sources. + + If `time_predicates` is None (legacy caller / standalone test), return + `[]` — the caller will fall back to the inline day-count logic. + If `source_vals` is empty (all-source scan), every Gold predicate + applies; callers typically avoid this path in production. + """ + if not time_predicates: + return [] + keys = [self._SOURCE_TYPE_TO_KEY[v] for v in source_vals if v in self._SOURCE_TYPE_TO_KEY] + if not keys: + keys = list(self._SOURCE_TYPE_TO_KEY.values()) + return [time_predicates[k] for k in keys if k in time_predicates] + + # ------------------------------------------------------------------ + # Filter builder — now three-mode (hard / soft-ticker / no-ticker). + # ------------------------------------------------------------------ + def _build_smart_filter( + self, + metadata: Any, + ignore_time: bool = False, + fallback_days: Optional[int] = None, + ticker_mode: str = "hard", # one of: "hard", "soft", "drop" + time_predicates: Optional[Dict["SourceTimeKey", "TimePredicate"]] = None, + ) -> Optional[models.Filter]: + """Compose a Qdrant filter with configurable ticker strictness. + + ticker_mode semantics (critical — this is the fix for "Gold layer + returns 0 even though ticker exists"): + + * "hard" — ticker goes into `must`. Every returned doc MUST have + a matching ticker payload. Historical behaviour; use when the + caller is confident the payload is always present (SEC). + + * "soft" — ticker goes into `should` together with a `topic` + condition (when derivable). `min_should=1` means a doc is + accepted if EITHER it matches a ticker OR it matches a news + topic for this query. Restores recall for news docs whose + `ticker` field is still NULL pre-enrichment. + + * "drop" — ticker is omitted entirely. Retains source_type + + time window + (optional) topic. Used as a last-resort third + fallback so "no ticker anywhere" queries still surface macro + articles — better to return thematic context than silence. + """ + must_conditions: List[models.FieldCondition] = [] + should_conditions: List[models.FieldCondition] = [] + + def _val(obj): + return getattr(obj, "value", obj) + + # Gold Layer is the vector store for {news, sec, gpr} ONLY. The + # LLM extractor occasionally emits labels like "options" or "macro" + # which are semantic domains, not physical source types — those + # datasets live in Silver (Parquet). Keeping them in the filter + # guarantees zero results, so we strip them HERE (single choke + # point) and keep the rest of the pipeline untouched. + _GOLD_SOURCE_TYPES = {"news", "sec", "gpr"} + raw_source_vals = [_val(s) for s in metadata.source_types] if metadata.source_types else [] + source_vals = [s for s in raw_source_vals if str(s).lower() in _GOLD_SOURCE_TYPES] + dropped_src = set(raw_source_vals) - set(source_vals) + if dropped_src: + logger.info( + f"🧹 [GoldFilter] Dropped Silver-only source_types {sorted(dropped_src)}; " + f"Gold kept={source_vals or 'ALL (no filter)'}" + ) + + # --- Ticker placement (hard / soft / drop) ----------------------- + ticker_list = list(metadata.tickers) if metadata.tickers else [] + if ticker_list and ticker_mode == "hard": + must_conditions.append( + models.FieldCondition(key="ticker", match=models.MatchAny(any=ticker_list)) + ) + elif ticker_list and ticker_mode == "soft": + should_conditions.append( + models.FieldCondition(key="ticker", match=models.MatchAny(any=ticker_list)) + ) + # ticker_mode == "drop" → omit entirely. + + # --- Topic enrichment (news only) -------------------------------- + # Emitted only when the query's event/category maps to a known + # news topic. Placed in `should` so it widens recall; combined + # with ticker-soft via min_should=1. + if "news" in source_vals: + topics = self._derive_news_topics(metadata) + if topics: + should_conditions.append( + models.FieldCondition(key="topic", match=models.MatchAny(any=topics)) + ) + + # --- source_type filter (hard) ----------------------------------- + if source_vals: + must_conditions.append( + models.FieldCondition(key="source_type", match=models.MatchAny(any=source_vals)) + ) + + # --- SEC-specific refinements (hard) ----------------------------- + if "sec" in source_vals: + action_val = _val(metadata.action_direction) + if str(action_val).upper() == "SELL": + must_conditions.append(models.FieldCondition(key="action_direction", match=models.MatchAny(any=["SELL", "ACQUIRE/VEST"]))) + elif str(action_val).upper() == "BUY": + must_conditions.append(models.FieldCondition(key="action_direction", match=models.MatchAny(any=["BUY", "ACQUIRE/VEST"]))) + elif str(action_val).upper() != "NONE": + must_conditions.append(models.FieldCondition(key="action_direction", match=models.MatchValue(value=action_val))) + + form_val = _val(metadata.form_type) + if str(form_val).upper() != "ALL": + must_conditions.append(models.FieldCondition(key="form_type", match=models.MatchValue(value=form_val))) + + # --- News sentiment filter (hard) -------------------------------- + if "news" in source_vals: + sentiment_val = _val(metadata.sentiment_target) + if str(sentiment_val).upper() == "NEGATIVE": + must_conditions.append(models.FieldCondition(key="tone_score", range=models.Range(lt=0))) + elif str(sentiment_val).upper() == "POSITIVE": + must_conditions.append(models.FieldCondition(key="tone_score", range=models.Range(gt=0))) + + # --- Time barrier (MUST — matches ANY of several timestamp keys) --- + # Two-layer design, landed 2026-04-22: + # + # 1. **Per-source alignment** (primary path, when `time_predicates` + # is supplied by master_retriever): + # Each Gold source has its own physical cadence — news is event- + # level, SEC is event-level but 3-day weekend-safe, GPR is + # MONTHLY and must widen a "yesterday" request to the full + # current month. We take the UNION of epoch windows for the + # sources actually selected (respecting `source_vals`), which + # produces a single numeric Range wide enough to satisfy every + # picked source's cadence without widening further. + # + # 2. **Legacy inline fallback** (when `time_predicates` is None — + # standalone retriever test, e.g. the `__main__` block): + # Reverts to the 2026-04-22-era single-window inline logic so + # existing tests keep working without a MasterRetriever. + # + # Both paths wrap the Range in a nested `Filter(should=[...])` + # inside the outer `must`. Qdrant evaluates the nested filter as + # "at least one timestamp key must land in range" — this preserves + # the hard-time contract while supporting BOTH the new + # `unified_timestamp` key and the legacy `publish_timestamp` key + # without forcing a full re-ingest. + if not ignore_time: + start_timestamp: int + end_timestamp: int + time_source_tag = "union_per_source" + + if fallback_days is not None: + # Legacy fallback-tier escalation path (Tier 2/3) — force + # a single wide window; ignore per-source widening so the + # retry is deterministic. + now = datetime.now() + start_timestamp = int((now - timedelta(days=fallback_days)).timestamp()) + end_timestamp = int(time.time()) + time_source_tag = f"legacy_fallback_{fallback_days}d" + elif time_predicates: + selected = self._select_gold_predicates(source_vals, time_predicates) + if selected: + start_timestamp, end_timestamp = union_epoch_range(selected) + widened = [p.source.value for p in selected if p.widened] + if widened: + logger.info( + f"🕒 [GoldTime] Per-source widening applied: {widened} | " + f"union window: {datetime.fromtimestamp(start_timestamp).date()}..{datetime.fromtimestamp(end_timestamp).date()}" + ) + else: + # source_vals was empty AND no predicates matched — fall + # back to the inline legacy window. + now = datetime.now() + time_val = _val(metadata.time_window) + time_key = getattr(time_val, "value", time_val) + if not isinstance(time_key, str): + time_key = str(time_key) if time_key is not None else "" + days_delta = TIME_WINDOW_DAYS.get(time_key.lower(), 30) + start_timestamp = int((now - timedelta(days=days_delta)).timestamp()) + end_timestamp = int(time.time()) + time_source_tag = f"inline_{days_delta}d" + else: + # time_predicates not supplied — legacy inline window. + now = datetime.now() + time_val = _val(metadata.time_window) + time_key = getattr(time_val, "value", time_val) + if not isinstance(time_key, str): + time_key = str(time_key) if time_key is not None else "" + days_delta = TIME_WINDOW_DAYS.get(time_key.lower(), 30) + start_timestamp = int((now - timedelta(days=days_delta)).timestamp()) + end_timestamp = int(time.time()) + time_source_tag = f"inline_{days_delta}d" + + time_range = models.Range(gte=start_timestamp, lte=end_timestamp) + must_conditions.append( + models.Filter( + should=[ + models.FieldCondition(key="unified_timestamp", range=time_range), + models.FieldCondition(key="publish_timestamp", range=time_range), + ] + ) + ) + logger.debug( + f"🕒 [GoldTime] mode={time_source_tag} | " + f"range=[{datetime.fromtimestamp(start_timestamp).date()}..{datetime.fromtimestamp(end_timestamp).date()}] " + f"| gte_epoch_s={start_timestamp} lte_epoch_s={end_timestamp}" + ) + + # --- Assemble final filter --------------------------------------- + # Qdrant default semantic (stable since v1.x): when `should` is set + # alongside `must`, a point is accepted iff ALL must conditions pass + # AND at least one should condition matches. That's exactly the + # "ticker OR topic" recall we want — no MinShould wrapper needed, + # keeping the call portable across qdrant-client minor versions. + if not must_conditions and not should_conditions: + return None + + kwargs: Dict[str, Any] = {} + if must_conditions: + kwargs["must"] = must_conditions + if should_conditions: + kwargs["should"] = should_conditions + return models.Filter(**kwargs) + + async def retrieve_async( + self, + original_query: str, + transform_result: FullTransformationResult, + top_k: int = 5, + time_predicates: Optional[Dict["SourceTimeKey", "TimePredicate"]] = None, + ) -> List[RetrievedChunk]: + """Run the hybrid Gold retrieval cascade. + + Parameters + ---------- + time_predicates + Per-source `TimePredicate` dict compiled upstream by + `MasterRetriever._compute_time_range`. When provided, the Gold + filter builds a UNION epoch window across the sources named in + `metadata.source_types` — so a mixed `["sec", "news"]` query + gets news's tight event window AND sec's 3-day weekend-safe + window combined into a single Range, while `["gpr"]` widens to + the full month. When None, the legacy inline day-count window + is used (preserves standalone test behaviour). + """ + start_time = time.time() + clean_search_query = getattr(transform_result.hyde, "rerank_query", original_query) + + logger.info(f"🔍 Original Query: {original_query[:40]}...") + logger.info(f"🎯 Denoised Rerank Query: {clean_search_query}") + + qdrant_filter = None + try: + # Keep compatibility with LangChain embedding invocation API. + dense_query_task = asyncio.to_thread( + lambda: self.dense_model.embed_query(transform_result.hyde.hyde_paragraph) + ) + sparse_query_task = asyncio.to_thread( + lambda: list(self.sparse_model.query_embed(clean_search_query))[0] + ) + dense_vec, sparse_vec = await asyncio.gather(dense_query_task, sparse_query_task) + + async def _execute_search(q_filter): + prefetch = [ + models.Prefetch(query=dense_vec, using="dense", limit=top_k * 3, filter=q_filter), + models.Prefetch( + query=models.SparseVector(indices=sparse_vec.indices.tolist(), values=sparse_vec.values.tolist()), + using="sparse", limit=top_k * 3, filter=q_filter + ) + ] + return await asyncio.to_thread( + self.client.query_points, + collection_name=self.collection_name, + prefetch=prefetch, + query=models.FusionQuery(fusion=models.Fusion.RRF), + limit=top_k * 2 + ) + + # --------------------------------------------------------------- + # Three-tier retrieval cascade (added 2026-04-22). + # Each tier progressively loosens constraints; the first tier + # that returns >=1 point wins. The tier that fired is logged in + # the audit trail so operators can see WHICH relaxation unlocked + # recall (this is the "fallback visibility" fix). + # --------------------------------------------------------------- + fallback_tier = "strict" # telemetry label + fallback_used = False # legacy boolean, kept for payload compat + + # Tier 1 — strict ticker, user's requested time window (aligned + # per-source via `time_predicates` when provided). + qdrant_filter = self._build_smart_filter( + transform_result.metadata, + ignore_time=False, + ticker_mode="hard", + time_predicates=time_predicates, + ) + search_results = await _execute_search(qdrant_filter) + points = search_results.points + + # Tier 2 — soft ticker (OR topic) + 180-day widened window. + # Targets the "ticker-not-tagged on news payloads" failure mode: + # old news docs without a `ticker` field still match via topic. + # Tier 2/3 deliberately OVERRIDE per-source predicates via + # `fallback_days` so the escalation stays deterministic. + if not points: + logger.warning("⚠️ Tier1 (strict) returned 0. Escalating to Tier2: soft-ticker + 180d.") + qdrant_filter = self._build_smart_filter( + transform_result.metadata, + ignore_time=False, + fallback_days=180, + ticker_mode="soft", + time_predicates=time_predicates, + ) + search_results = await _execute_search(qdrant_filter) + points = search_results.points + fallback_used = True + fallback_tier = "soft_ticker_180d" + + # Tier 3 — drop ticker entirely. Keeps source_type + topic + time. + # Intent: if neither ticker nor topic carried a match, surface + # broadly-relevant macro context rather than stay silent. The + # Analyst downstream can still honestly label these as weak. + if not points: + logger.warning("⚠️ Tier2 (soft) returned 0. Escalating to Tier3: drop-ticker + 180d.") + qdrant_filter = self._build_smart_filter( + transform_result.metadata, + ignore_time=False, + fallback_days=180, + ticker_mode="drop", + time_predicates=time_predicates, + ) + search_results = await _execute_search(qdrant_filter) + points = search_results.points + fallback_tier = "drop_ticker_180d" + + if not points: + self._log_audit( + original_query, clean_search_query, qdrant_filter, [], + time.time() - start_time, fallback_used, fallback_tier=fallback_tier, + ) + return [] + + # Apply precision reranking scores. + pairs = [[clean_search_query, p.payload.get("text", "")] for p in points] + + rerank_scores = await asyncio.to_thread(self.reranker.predict, pairs) + + for idx, p in enumerate(points): + p.score = float(rerank_scores[idx]) + + points.sort(key=lambda x: x.score, reverse=True) + + valid_points = [p for p in points if p.score > 0.00001] + top_k_results = valid_points[:top_k] + + formatted_results = self._format_results(top_k_results, fallback_used) + self._log_audit( + original_query, clean_search_query, qdrant_filter, formatted_results, + time.time() - start_time, fallback_used, fallback_tier=fallback_tier, + ) + return formatted_results + + except Exception as e: + # Use logger.exception to preserve stack trace and line numbers. + logger.exception(f"❌ Async Retrieval Pipeline failed: {e}") + self._log_audit( + original_query, clean_search_query, qdrant_filter, [], + time.time() - start_time, False, fallback_tier="error", error=str(e), + ) + return [] + + def _format_results(self, points: List[Any], fallback_used: bool = False) -> List[RetrievedChunk]: + retrieved_chunks = [] + for hit in points: + payload = hit.payload + bronze_anchor = payload.get("accession_no") or payload.get("url") or str(hit.id) + record_date = "Unknown" + if "unified_timestamp" in payload: + try: + record_date = datetime.fromtimestamp(payload["unified_timestamp"]).strftime('%Y-%m-%d') + except Exception: + pass + + excluded_keys = {"text", "document_sparse_embedding"} + refined_metadata = {k: v for k, v in payload.items() if k not in excluded_keys} + + # Add explicit tags for downstream router/agent consumers. + refined_metadata["record_date"] = record_date + refined_metadata["is_fallback_180_days"] = fallback_used + + chunk = RetrievedChunk( + content=payload.get("text", ""), + source_type=payload.get("source_type", SourceType.NEWS), + score=hit.score, + metadata=refined_metadata, + bronze_ref=bronze_anchor + ) + retrieved_chunks.append(chunk) + + return retrieved_chunks + + def _log_audit( + self, + query: str, + rerank_query: str, + qdrant_filter: Optional[models.Filter], + results: List[RetrievedChunk], + latency: float, + fallback_used: bool, + fallback_tier: str = "strict", + error: str = None, + ): + audit_payload = { + "timestamp": datetime.now().isoformat(), + "original_query": query, + "rerank_query_used": rerank_query, # Preserve exact retrieval text for observability. + "filter_applied": qdrant_filter.model_dump() if qdrant_filter else None, + "fallback_triggered": fallback_used, + # New: exact tier that fired — "strict" | "soft_ticker_180d" | + # "drop_ticker_180d" | "error". Use this field to diagnose which + # relaxation was necessary, instead of inferring from the legacy + # boolean which overwrites across retries. + "fallback_tier": fallback_tier, + "results_count": len(results), + "top_k_scores": [round(r.score, 4) for r in results], + "latency_sec": round(latency, 3), + "status": "ERROR" if error else "SUCCESS", + "error_msg": error + } + + logger.info(f"[AUDIT_RAG_RETRIEVAL] {json.dumps(audit_payload)}") + + try: + date_str = datetime.now().strftime("%Y-%m-%d") + log_dir = Path(project_root) / "logs" / "retrieval" / date_str + log_dir.mkdir(parents=True, exist_ok=True) + log_file = log_dir / "retriever_audit_trail.jsonl" + + with open(log_file, 'a', encoding='utf-8') as f: + f.write(json.dumps(audit_payload, ensure_ascii=False) + "\n") + except Exception as log_e: + logger.error(f"Failed to write audit log to file: {log_e}") + + +# ========================================== +# Local sandbox test (end-to-end retrieval chain) +# ========================================== +if __name__ == "__main__": + import asyncio + # Import query transformation and intent schema for standalone E2E test. + try: + from .query_transform import QueryTransformer + from .schema import QueryIntent + except ImportError: + from Scripts.retrieval.query_transform import QueryTransformer + from Scripts.retrieval.schema import QueryIntent + + async def test_end_to_end(): + # 1) Initialize both engines. + print("⚙️ Initializing RAG Pipeline Engines...") + transformer = QueryTransformer() + retriever = FinancialHybridRetriever() + + # 2) Example user query. + #query = "How did AAPL executives' Form 4 offloading past week impact IV skew?" + query = "What recent insider buying activity has there been for TSLA and how did the market react?" + mock_intent = QueryIntent(primary_route="hybrid_both") + + print(f"\n🗣️ User Query: {query}") + print("-" * 60) + + try: + # 3) Stage 1: run transformer (LLM) for metadata + HyDE. + print("🧠 Stage 1: LLM Transforming Query...") + transform_result = await transformer.transform_for_dual_rag(query, mock_intent) + + # Print extraction outputs for debug visibility. + print(f" -> 🎯 Extracted Tickers: {transform_result.metadata.tickers}") + print(f" -> 🎯 Extracted Time: {transform_result.metadata.time_window}") + print(f" -> 🎯 Generated HyDE: {transform_result.hyde.hyde_paragraph[:80]}...") + print("-" * 60) + + # 4) Stage 2: pass transformed payload into retriever. + print("🔍 Stage 2: Qdrant Hybrid Retrieving...") + results = await retriever.retrieve_async(original_query=query, transform_result=transform_result) + + # 5) Print retrieval results. + print(f"\n✅ Final Retrieved: {len(results)} chunks.") + for i, res in enumerate(results): + print(f"[{i+1}] Score: {res.score:.4f} | Bronze Ref: {res.bronze_ref}") + print(f" Fallback Used: {res.metadata.get('fallback_used', False)}") + print(f" Source: {res.source_type} | Ticker: {res.metadata.get('ticker')}") + print(f" Snippet: {res.content[:150]}...\n") + + except Exception as e: + print(f"\n❌ Pipeline Test Failed: {e}") + + asyncio.run(test_end_to_end()) \ No newline at end of file diff --git a/Scripts/retrieval/query_transform.py b/Scripts/retrieval/query_transform.py new file mode 100644 index 0000000..9d0d83c --- /dev/null +++ b/Scripts/retrieval/query_transform.py @@ -0,0 +1,313 @@ +""" +Scripts/retrieval/query_transform.py + +Industrial-grade query transformation engine (context-anchored two-stage transformer) +Senior Architect Version: Fully Decoupled Prompts + Robust Guardrails +""" + +import os +import sys +import logging +import asyncio +import json +from datetime import datetime +from pathlib import Path +from typing import List, Dict, Any, Optional +from dotenv import load_dotenv + +from langchain_ollama import ChatOllama +from langchain_core.prompts import ChatPromptTemplate +from langchain_core.messages import AIMessage, HumanMessage, SystemMessage + +# --- 1. Path and environment bootstrap --- +SCRIPT_PATH = Path(__file__).resolve() +PROJECT_ROOT = SCRIPT_PATH.parents[2] +load_dotenv(PROJECT_ROOT / ".env") + +if str(PROJECT_ROOT) not in sys.path: + sys.path.insert(0, str(PROJECT_ROOT)) + +# --- 2. Core dependency imports (robust fallback) --- +try: + # Prefer package-relative imports when used as part of Scripts.retrieval. + from ..core.financial_ontology import ( + ALLOWED_METRICS, ALLOWED_SOURCES, ALLOWED_CATEGORIES, METRIC_TO_COLUMN_MAPPING + ) + # Import local retrieval schemas. + from .schema import ( + QueryIntent, MetadataExtraction, HyDEGeneration, FullTransformationResult, TimeWindow + ) + # Import decoupled prompt templates. + from ..core.prompt_templates import EXTRACTOR_SYSTEM_PROMPT, HYDE_WRITER_SYSTEM_PROMPT +except ImportError as e: + try: + # Fallback to absolute imports when running this file directly. + from Scripts.core.financial_ontology import ( + ALLOWED_METRICS, ALLOWED_SOURCES, ALLOWED_CATEGORIES, METRIC_TO_COLUMN_MAPPING + ) + from Scripts.retrieval.schema import ( + QueryIntent, MetadataExtraction, HyDEGeneration, FullTransformationResult, TimeWindow + ) + from Scripts.core.prompt_templates import EXTRACTOR_SYSTEM_PROMPT, HYDE_WRITER_SYSTEM_PROMPT + except ImportError: + print(f"❌ Initialization Error: Missing core dependency: {e}") + sys.exit(1) + +# Fault-tolerant few-shot loading. If unavailable, degrade to zero-shot. +try: + from ..core.few_shot_config import FEW_SHOT_EXAMPLES +except ImportError: + try: + from Scripts.core.few_shot_config import FEW_SHOT_EXAMPLES + except ImportError: + FEW_SHOT_EXAMPLES = [] + +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger("QueryTransformer") + +class QueryTransformer: + def __init__(self): + self.model_name = os.getenv("OLLAMA_CUSTOM_MODEL_NAME", "options-expert-v1:latest") + + # Load ticker allowlist for prompt injection and post-LLM guardrails. + self.allowed_tickers = self._load_allowed_tickers() + + # --- LLM initialization --- + # Stage 1: strict extractor model. + self.extractor_llm = ChatOllama( + model=self.model_name, temperature=0, format="json" + ).with_structured_output(MetadataExtraction) + + # Stage 2: semantic writer model. + self.hyde_llm = ChatOllama( + model=self.model_name, temperature=0.2, format="json" + ).with_structured_output(HyDEGeneration) + + self._build_prompts() + + def _load_allowed_tickers(self) -> List[str]: + """Build a global ticker pool (equities + ETFs + macro indices).""" + # 1) Load SEC filer universe through the central UniverseLoader. This is + # now the single source of truth; there is no file-path fallback. + sec_tickers: List[str] = [] + try: + from Scripts.core.universe import universe as _universe + sec_tickers = [t.upper() for t in _universe.get("sec.filers")] + except Exception as e: + logger.warning( + f"UniverseLoader unavailable ({e}); allowed-ticker pool will " + "only contain the hard-coded macro/ETF baseline." + ) + + # 2) Add macro-index symbols that are NOT in the universe manifest + # (these are ^-prefixed indices / DX-Y.NYB used by retrieval prompts). + macro_index_tickers = ["^GSPC", "^IXIC", "^VIX", "DX-Y.NYB"] + + # 3) Best-effort: pull ETF tickers from the universe too, so adding a + # new ETF to config/universe/ automatically propagates here. + try: + from Scripts.core.universe import universe as _universe + etf_tickers = [t.upper() for t in _universe.get("etf.all")] + except Exception: + etf_tickers = ["GLD", "SLV", "SPY", "QQQ", "IWM"] + + return list(set(sec_tickers + etf_tickers + macro_index_tickers)) + + def _build_prompts(self): + """Build decoupled prompts aligned with external template variables.""" + + # --- STAGE 1 PROMPT --- + extractor_messages = [("system", EXTRACTOR_SYSTEM_PROMPT)] + + # Dynamically assemble few-shot blocks to avoid template brace collisions. + if FEW_SHOT_EXAMPLES: + for ex in FEW_SHOT_EXAMPLES: + extractor_messages.append(HumanMessage(content=f"Query: {ex['user_query']}")) + extractor_messages.append(AIMessage(content=json.dumps(ex['extraction']))) + + extractor_messages.append(("human", "Query: {user_query}")) + self.extractor_prompt = ChatPromptTemplate.from_messages(extractor_messages) + + # --- STAGE 2 PROMPT --- + # Macro/background/metadata/reasoning placeholders are injected in the SYSTEM template. + self.hyde_prompt = ChatPromptTemplate.from_messages([ + ("system", HYDE_WRITER_SYSTEM_PROMPT), + ("human", "User Query: {user_query}") + ]) + + def _get_macro_context(self) -> str: + """Load macro context used by HyDE generation.""" + context_path = PROJECT_ROOT / "Data" / "Agent_Context" / "latest_macro_context.md" + if context_path.exists(): + return context_path.read_text(encoding='utf-8') + return "Market conditions are currently stable." + + def _save_audit_trail(self, query: str, intent: QueryIntent, result_data: dict, latency: float): + """Persist query transformation audit logs.""" + try: + date_str = datetime.now().strftime("%Y-%m-%d") + log_dir = PROJECT_ROOT / "logs" / "query_transform" / date_str + log_dir.mkdir(parents=True, exist_ok=True) + log_file = log_dir / "query_audit_trail.jsonl" + + audit_payload = { + "timestamp": datetime.now().isoformat(), + "latency_seconds": round(latency, 2), + "original_query": query, + "primary_route": intent.primary_route if intent else "unknown", + "transformation_result": result_data + } + with open(log_file, 'a', encoding='utf-8') as f: + f.write(json.dumps(audit_payload, ensure_ascii=False) + "\n") + logger.info(f"💡 Audit Log saved to {log_file}") + except Exception as e: + logger.error(f"Failed to save audit log: {e}") + + async def transform_for_dual_rag(self, query: str, intent: QueryIntent) -> FullTransformationResult: + start_time = datetime.now() + logger.info(f"🚀 Starting Two-Stage Pipeline for query: {query[:50]}...") + + try: + # ========================================== + # STAGE 1: Extract Metadata + # ========================================== + metadata: MetadataExtraction = await self.extractor_llm.ainvoke( + self.extractor_prompt.format_prompt( + user_query=query, + allowed_tickers_str=", ".join(self.allowed_tickers), + allowed_metrics=", ".join(ALLOWED_METRICS), + allowed_sources=", ".join(ALLOWED_SOURCES), + allowed_categories=", ".join(ALLOWED_CATEGORIES) + ) + ) + + # [GUARDRAIL 1] Post-clean extracted tickers using allowlist. + valid_tickers = [t for t in metadata.tickers if t in self.allowed_tickers] + if len(valid_tickers) != len(metadata.tickers): + logger.warning(f"⚠️ Guardrail triggered: Dropped invalid tickers: {set(metadata.tickers) - set(valid_tickers)}") + metadata.tickers = valid_tickers + + # [GUARDRAIL 2] Apply a default time window fallback. + if not metadata.time_window: + metadata.time_window = TimeWindow.PAST_SIX_MONTHS + + # [GUARDRAIL 3] Ticker-explosion cap. + # Defends against LLM hallucination on vague phrases like + # "recommended tickers" / "all major stocks", which on 2026-04-22 + # produced 57 tickers in a single extraction. Downstream Silver + # SQL executes one query per metric × ticker → latency blows up + # and the Analyst can't reason over 57 separate anchors. + # + # Policy: + # - > _TICKER_HARD_CAP (default 8) => keep first _TICKER_KEEP (default 5), + # drop the rest, log LOUD so the audit trail shows degradation. + # - <= _TICKER_HARD_CAP => pass through. + _TICKER_HARD_CAP = int(os.getenv("TICKER_EXPLOSION_CAP", "8")) + _TICKER_KEEP = int(os.getenv("TICKER_EXPLOSION_KEEP", "5")) + if len(metadata.tickers) > _TICKER_HARD_CAP: + dropped = metadata.tickers[_TICKER_KEEP:] + metadata.tickers = metadata.tickers[:_TICKER_KEEP] + logger.warning( + f"⚠️ Guardrail 3 (ticker explosion): original={len(dropped) + _TICKER_KEEP} " + f"kept={metadata.tickers} dropped={dropped}" + ) + + # Map semantic metrics to physical database columns. + mapped_cols = set() + for m in metadata.metrics: + if m in METRIC_TO_COLUMN_MAPPING: + # Mapping values are lists, so set.update is required here. + mapped_cols.update(METRIC_TO_COLUMN_MAPPING[m]) + mapped_physical_columns = list(mapped_cols) + + # ========================================== + # STAGE 2: Generate HyDE + # ========================================== + hyde_result: HyDEGeneration = await self.hyde_llm.ainvoke( + self.hyde_prompt.format_prompt( + user_query=query, + macro_background=self._get_macro_context(), + extracted_metadata=metadata.model_dump_json(indent=2, exclude={'logical_reasoning'}), + reasoning_chain=metadata.logical_reasoning + ) + ) + + # [GUARDRAIL 4] HyDE empty-paragraph fallback. + # Production audit on 2026-04-22 caught a live case where the + # structured-output LLM returned hyde_paragraph="" for a + # perfectly well-formed "yesterday PCR + IV Skew for AAPL" query, + # blanking out dense retrieval entirely. Rather than let the Gold + # engine get an empty vector, we synthesise a deterministic + # one-liner from the metadata so the dense embedder always has a + # coherent sentence to embed. The rerank_query is also reproduced + # so sparse retrieval stays aligned. + hyde_para = (hyde_result.hyde_paragraph or "").strip() + hyde_rr = (hyde_result.rerank_query or "").strip() + if not hyde_para: + metric_str = ", ".join(metadata.metrics) if metadata.metrics else "market data" + ticker_str = ", ".join(metadata.tickers) if metadata.tickers else "the broader market" + tw_val = getattr(metadata.time_window, "value", metadata.time_window) or "recent" + hyde_para = ( + f"Analysis of {metric_str} for {ticker_str} over the {tw_val} window " + f"reflects the current implied-volatility regime and " + f"options-flow sentiment relevant to the query." + ) + logger.warning( + f"⚠️ Guardrail 4 (HyDE empty): synthesised fallback paragraph " + f"({len(hyde_para)} chars) from metadata." + ) + if not hyde_rr: + parts = [] + if metadata.tickers: + parts.extend(metadata.tickers) + if metadata.metrics: + parts.extend(metadata.metrics) + if getattr(metadata, "event_keyword", None): + parts.append(metadata.event_keyword) + hyde_rr = " ".join(parts) if parts else query + hyde_result = HyDEGeneration(hyde_paragraph=hyde_para, rerank_query=hyde_rr) + + # Aggregate stage outputs into one typed payload. + final_result = FullTransformationResult( + metadata=metadata, + hyde=hyde_result, + mapped_physical_columns=mapped_physical_columns + ) + + latency = (datetime.now() - start_time).total_seconds() + self._save_audit_trail(query, intent, final_result.model_dump(), latency) + logger.info(f"✅ Pipeline completed perfectly in {latency:.2f}s") + return final_result + + except Exception as e: + logger.error(f"❌ Two-Stage Transformation Failure: {e}") + latency = (datetime.now() - start_time).total_seconds() + self._save_audit_trail(query, intent, {"error": str(e), "stage": "transformation_failed"}, latency) + raise e + +# ========================================== +# Standalone test entrypoint +# ========================================== +if __name__ == "__main__": + async def test(): + transformer = QueryTransformer() + mock_intent = QueryIntent(primary_route="hybrid_both") + + #query = "How did NVDA's recent insider sales from the past week impact its options IV skew, given the current macro climate?" + #query = "How did gold and silver price changes from recent weeks impact their options IV skew, given the current geopolitical climate?" + query = "what is the current put/call ratio for SPY and how does it compare to historical levels? Also, how has the institutional flow been for SPY options in the past month?" + result = await transformer.transform_for_dual_rag(query, mock_intent) + + print("\n" + "="*60) + print("[STAGE 1: (Metadata & Reasoning)]") + print(f"🧠 Reasoning: {result.metadata.logical_reasoning}") + print(f"📊 Tickers: {result.metadata.tickers}") + print(f"📈 Metrics: {result.metadata.metrics}") + print(f"🏛️ Action: {result.metadata.action_direction}") + print(f"🕒 Time Window: {result.metadata.time_window}") + print("-" * 60) + print("[STAGE 2: HyDE (Gold Layer)]") + print(result.hyde.hyde_paragraph) + print("="*60) + + asyncio.run(test()) \ No newline at end of file diff --git a/Scripts/retrieval/schema.py b/Scripts/retrieval/schema.py new file mode 100644 index 0000000..f82f30a --- /dev/null +++ b/Scripts/retrieval/schema.py @@ -0,0 +1,196 @@ +""" +Scripts/retrieval/schema.py +Core Protocol for Financial Multi-Agent RAG. +Senior Architect Version: Two-Stage Pipeline (Extractor + HyDE) +""" + +from pydantic import BaseModel, Field, field_validator, ConfigDict +from typing import List, Optional, Dict, Any +from enum import Enum +from datetime import datetime + +# ========================================== +# 1. ENUMS FOR STRICT VALIDATION (Retained) +# ========================================== + +class SourceType(str, Enum): + SEC = "sec" + NEWS = "news" + GPR = "gpr" + MACRO_HISTORY = "macro_history" + OPTIONS = "options" + +class ActionDirection(str, Enum): + BUY = "BUY" + SELL = "SELL" + ACQUIRE = "ACQUIRE/VEST" + NONE = "NONE" + +class SearchMode(str, Enum): + VECTOR_ONLY = "vector_only" + HYBRID = "hybrid" + METADATA_ONLY = "metadata_only" + +class TimeWindow(str, Enum): + TODAY = "today" + YESTERDAY = "yesterday" + PAST_WEEK = "past_week" + PAST_MONTH = "past_month" + PAST_SIX_MONTHS = "past_six_months" + ALL = "all" + +# --------------------------------------------------------------------- +# Global TimeWindow -> day-count policy (single source of truth). +# +# Rationale: +# - Kept in schema.py (not master_retriever.py) so the Gold retriever +# (qdrant_retriever.py) and the Silver retriever (sql_tools.py) can +# both consume it without creating a circular import against the +# Master Retriever facade. +# - master_retriever.py re-exports `TIME_WINDOW_DAYS` and +# `time_window_to_days` at module-level, so downstream callers can +# still treat master_retriever as the canonical global access point. +# - `ALL` is set to 365 days: treated as the hard ceiling for "all history" +# requests. Historical-data checks without an explicit time signal fall +# back to PAST_SIX_MONTHS (180 days) via the MetadataExtraction validator +# below — NOT to ALL — so default recall doesn't silently scan a year of +# data. Gold time filtering can still override via `fallback_days`. +# --------------------------------------------------------------------- +TIME_WINDOW_DAYS: Dict[str, int] = { + TimeWindow.TODAY.value: 1, + # "yesterday" = 2 days so that Friday's anchor still covers Monday queries + # (weekend gap). Downstream SQL handlers that pick `ORDER BY DESC LIMIT 1` + # will naturally grab the most recent available trading day. + TimeWindow.YESTERDAY.value: 2, + TimeWindow.PAST_WEEK.value: 7, + TimeWindow.PAST_MONTH.value: 30, + TimeWindow.PAST_SIX_MONTHS.value: 180, + TimeWindow.ALL.value: 365, +} + + +def time_window_to_days(tw: Any, default: int = 30) -> int: + """ + Translate a metadata.time_window value (str or TimeWindow enum) into + a day count using the global `TIME_WINDOW_DAYS` policy. + + Returns `default` when the input is missing or unrecognised. This is + the ONLY function both Gold and Silver layers should use to reason + about lookback windows — do not hard-code day counts elsewhere. + """ + val = getattr(tw, "value", tw) + if not isinstance(val, str): + return default + return TIME_WINDOW_DAYS.get(val.lower(), default) + +class FormTypeFilter(str, Enum): + FORM_4 = "4" + FORM_8K = "8-K" + ALL = "ALL" + +class SentimentTarget(str, Enum): + POSITIVE = "POSITIVE" + NEGATIVE = "NEGATIVE" + ANY = "ANY" + +# ========================================== +# 2. TWO-STAGE LLM OUTPUT SCHEMAS +# ========================================== + +class MetadataExtraction(BaseModel): + """ + STAGE 1: Pure Metadata Extraction (The Extractor) + Forces the LLM to output ONLY strict analytical parameters. + """ + logical_reasoning: str = Field(..., description="Mandatory Analysis: Use 'Macro -> Meso -> Micro' framework. Analyze When, How, and Why before extraction.") + tickers: List[str] = Field(..., description="Extracted stock symbols. Output empty list [] if none.") + metrics: List[str] = Field(..., description="Quantitative metrics mentioned. Output empty list [] if none.") + source_types: List[SourceType] = Field(..., description="Inferred data sources. MUST choose at least one.") + action_direction: ActionDirection = Field(..., description="Insider trading action. MUST output 'NONE' if not applicable.") + form_type: FormTypeFilter = Field(..., description="SEC form types. MUST output 'ALL' if not applicable.") + sentiment_target: SentimentTarget = Field(..., description="User's sentiment bias. MUST output 'ANY' if not applicable.") + event_keyword: str = Field(..., description="A 1-to-3 word keyword of the trigger. Output empty string '' if none.") + time_window: TimeWindow = Field(..., description="Default to 'past_six_months' if not specified.") + + model_config = ConfigDict(use_enum_values=True, populate_by_name=True, arbitrary_types_allowed=True) + + @field_validator('tickers') + @classmethod + def normalize_tickers(cls, v: List[str]) -> List[str]: + return [ticker.upper().strip() for ticker in v] + + @field_validator('time_window', mode='before') + @classmethod + def handle_empty_window(cls, v: Any) -> TimeWindow: + # Time-window fallback policy (single source of truth): + # - User says "all history" / explicit "all" -> TimeWindow.ALL (365 days) + # - User omits time / LLM hallucinates an invalid value -> PAST_SIX_MONTHS (180 days) + # - All other canonical windows (today / past_week / past_month / past_six_months) + # are passed through unchanged. + # Matches the extractor prompt ("Default to 6 months if unspecified") and + # the Silver/Gold retrievers that read TIME_WINDOW_DAYS. + if v not in [item.value for item in TimeWindow]: + return TimeWindow.PAST_SIX_MONTHS + return v + +class HyDEGeneration(BaseModel): + """ + STAGE 2: Semantic Paragraph Generation (The Writer) + Generates a rich causal chain for Vector Search. + """ + hyde_paragraph: str = Field(..., description="A 100 word high-density financial simulation based strictly on the metadata.") + rerank_query: str = Field( + ..., + description=( + "A clean, factual search query stripped of analytical noise (like 'impact', 'skew', 'why'). " + "Focus ONLY on the core entities and events to be found in the database. " + "Example: If user asks 'How did AAPL Form 4 offloading impact IV skew?', " + "you MUST output exactly 'AAPL executive insider selling Form 4 transactions'." + ) + ) + +class FullTransformationResult(BaseModel): + """Aggregates the results of the Two-Stage Pipeline for the Router.""" + metadata: MetadataExtraction + hyde: HyDEGeneration + mapped_physical_columns: List[str] = Field(default_factory=list) + +# ========================================== +# 3. ROUTING SCHEMAS (System State) +# ========================================== + +class SECMetadata(BaseModel): + ticker: str + form_type: str + accession_no: str + filed_at: str + transaction_date: Optional[str] = None + action_direction: ActionDirection = ActionDirection.NONE + tone_score: int + url: str + +class QueryIntent(BaseModel): + primary_route: str = Field(description="One of: 'hybrid_both', 'gold_only', 'silver_only'") + is_complex: bool = Field(default=False) + search_top_k: int = Field(default=5) + requires_hyde: bool = Field(default=True) + +class RetrievedChunk(BaseModel): + content: str + source_type: SourceType + score: float + metadata: Dict[str, Any] = Field(default_factory=dict) + bronze_ref: Optional[str] = "UNKNOWN" + +class SQLResult(BaseModel): + df_json: str + query_executed: str + summary: str + +class AgentState(BaseModel): + input_query: str + macro_context: str = Field("", description="Daily market background injected into prompts") + intent: Optional[QueryIntent] = None + transformation_result: Optional[FullTransformationResult] = None + raw_retrieved_chunks: List[RetrievedChunk] = [] + sql_context: Optional[SQLResult] = None \ No newline at end of file diff --git a/Scripts/retrieval/sql_tools.py b/Scripts/retrieval/sql_tools.py new file mode 100644 index 0000000..7a43005 --- /dev/null +++ b/Scripts/retrieval/sql_tools.py @@ -0,0 +1,830 @@ +""" +Scripts/retrieval/sql_tools.py + +Institutional-grade quantitative retrieval tool for the Silver Layer. + +Design pillars: +1. Ontology decoupling: metric whitelist and mapping come from Scripts.core.financial_ontology. +2. Fuzzy metric resolution: LLM-extracted metric names are canonicalised via difflib-backed + ontology matching. Ticker symbols are NEVER fuzzy-matched — they remain strict. +3. Dynamic Time Anchor: CURRENT_DATE usage is replaced with anchors derived from + config/runtime/collect_data_state.json (last_run_keys), keeping SQL correct during + backfills, weekends and holidays. +4. Aggregation engine: computes derived metrics such as Put/Call Ratio (PCR). +5. Auditability: daily-partitioned structured logs capture SQL, latency and lineage anchors. +6. Path robustness: expands '~' and resolves absolute paths on start-up. +""" + +import os +import glob as _glob_mod +import json +import difflib +import duckdb +import logging +from datetime import datetime, date, timedelta +from pathlib import Path +from typing import Dict, Any, List, Optional, Set +from dotenv import load_dotenv + +# Core ontology (metrics whitelist + metric -> physical column map). +# Categories are for Gold/Qdrant prompts, not Silver SQL routing. +from Scripts.core.financial_ontology import ( + ALLOWED_METRICS, + METRIC_TO_COLUMN_MAPPING, + ETF_TO_MACRO_ALIAS, +) +# Shared retrieval contract: +# - MetadataExtraction: LLM structured output consumed by every handler. +# - time_window_to_days / TIME_WINDOW_DAYS: global TimeWindow policy, same one +# used by qdrant_retriever.py (Gold Layer). Single source of truth. +from Scripts.retrieval.schema import MetadataExtraction, TIME_WINDOW_DAYS, time_window_to_days +# Per-source time predicates (landed 2026-04-22). The Silver handlers can +# optionally consume a pre-compiled `TimePredicate` from master_retriever so +# monthly GPR queries get month-widened windows and daily sources get +# weekend-safe windows — without re-deriving the policy per handler. +from Scripts.retrieval.time_adapter import SourceTimeKey, TimePredicate + +# Load environment variables +load_dotenv() + +class SilverSQLTool: + # ----------------------------------------------------------------- + # Dataset -> last_run_keys mapping (see config/runtime/collect_data_state.json). + # Used by _get_anchor_date() to build a Dynamic Time Anchor instead of + # relying on CURRENT_DATE — keeps SQL correct during backfills, weekends, + # and holidays when wall-clock and actual data-latest diverge. + # ----------------------------------------------------------------- + _ANCHOR_KEY: Dict[str, str] = { + "options": "options_daily", + "macro": "macro_trading_daily", + "gpr": "gpr_monthly", + "news": "news_daily", + } + + # ----------------------------------------------------------------- + # Silver-Layer physical contract. + # Every dataset here is validated at startup via _validate_parquet_contract(): + # 1. The glob resolves to >= 1 parquet file on disk. + # 2. The actual parquet schema contains every column this tool consumes. + # Drift (rename, missing column, moved folder) is surfaced in the daily + # audit log as SCHEMA_CHECK | status=MISSING_COLUMNS / NO_FILES / READ_FAILED + # so wrong-path regressions (e.g. GPR_History vs GPR_index) no longer + # degrade into silent empty results. + # ----------------------------------------------------------------- + _EXPECTED_SCHEMA: Dict[str, Dict[str, Any]] = { + "options": { + "glob_attr": "options_glob", + "required": { + "snapshot_date", "symbol", "option_type", "volume", + "open_interest", "implied_volatility", "moneyness_pct", + "spread_pct", "dte", "is_liquid", "contract_symbol", + }, + }, + "macro": { + "glob_attr": "macro_glob", + "required": { + "observation_date", "symbol", "value", + "daily_change_pct", "mom_change_pct", + }, + }, + "gpr": { + "glob_attr": "gpr_path", + "required": {"date", "gpr", "gpr_percentile", "gpr_mom_pct"}, + }, + } + + def __init__(self): + # 1) Robust path resolution (expands ~, resolves env). + raw_root = os.getenv("DATA_LAKE_ROOT", "./Data") + self.data_root = Path(raw_root).expanduser().resolve() + self._init_paths() + + # 2) Runtime data-freshness state (dynamic time anchors). + self.runtime_state = self._load_runtime_state() + + # 3) Rolling audit logger (daily partitioned). + self.audit_logger = self._setup_audit_logger() + + # 4) High-performance in-memory DuckDB session. + self.conn = duckdb.connect(database=':memory:') + self.conn.execute("SET threads TO 4; SET memory_limit='2GB';") + + # 4b) Deep Silver-Layer contract validation (path + column schema). + # Non-fatal — dev environments with partial data still boot, but + # misalignments are loudly logged so they can't rot silently. + self._validate_parquet_contract() + + # 5) Metric dispatch table. + # Keys MUST exist as-is (or resolve via fuzzy match) in + # Scripts.core.financial_ontology.METRIC_TO_COLUMN_MAPPING. + # Grouped by data domain for readability. + self.metric_dispatcher = { + # --- Options: IV-centric ----------------------------------- + "IV Skew": self._handle_options_analysis, + "Implied Volatility (IV)": self._handle_options_analysis, + "Implied Volatility": self._handle_options_analysis, + + # --- Options: liquidity / flow ----------------------------- + # All three share the same physical columns (volume, OI, + # is_liquid, spread_pct) so they route to the same handler. + # Keeping distinct keys helps the Analyst prompt reason about + # intent even though SQL is identical. + "Options Liquidity": self._handle_liquidity_analysis, + "Open Interest": self._handle_liquidity_analysis, + "Options Volume": self._handle_liquidity_analysis, + "Institutional Flows": self._handle_liquidity_analysis, # legacy alias + "Institutional Flow": self._handle_liquidity_analysis, # legacy alias + + # --- Options: pricing / spread ----------------------------- + # Dedicated handler so quote/spread queries don't hijack the + # IV-centric _handle_options_analysis result shape. + "Options Pricing / Spread": self._handle_pricing_spread, + "Underlying Price": self._handle_pricing_spread, + + # --- Options: aggregates ----------------------------------- + "Put/Call Ratio": self._handle_put_call_ratio, + + # --- Macro series ------------------------------------------ + # "Price" / "Price Change (%)" apply to both macro symbols + # (^GSPC, FEDFUNDS, …) and options underlyings. The handler + # applies the ETF_TO_MACRO_ALIAS translation so SPY/QQQ land + # on ^GSPC/^IXIC — see _handle_macro_analysis below. + "Macro Trend": self._handle_macro_analysis, + "Price": self._handle_macro_analysis, + "Price Change (%)": self._handle_macro_analysis, + "Daily Change (%)": self._handle_macro_analysis, + "Monthly Change (%)":self._handle_macro_analysis, + "Yearly Change (%)": self._handle_macro_analysis, + + # --- GPR ---------------------------------------------------- + "GPR Index": self._handle_geopolitical_analysis, + "GPR Threats": self._handle_geopolitical_analysis, + "GPR Acts": self._handle_geopolitical_analysis, + "GPR Components": self._handle_geopolitical_analysis, + "GPR Country-level": self._handle_geopolitical_analysis, + } + + def _init_paths(self): + """Build robust Parquet globs and warn when DATA_LAKE_ROOT is missing. + + Folder names below MUST match the Silver-Layer writers exactly: + - Options : Scripts/data_collection/scrapers/yfinance_options_history.py + writes /2_Silver_Processed/Options_Market_Data/ + /_options_.parquet + - Macro : Scripts/data_collection/scrapers/macro_data_pipeline.py + writes /2_Silver_Processed/Macro_History/ + /macro_snapshot_.parquet + - GPR : Scripts/data_collection/scrapers/GPR_index.py + writes /2_Silver_Processed/GPR_index/ + gpr_monthly_enriched.parquet (NOTE: lowercase 'index', + single canonical file — writer overwrites in place). + Any drift is surfaced loudly by _validate_parquet_contract(). + """ + self.options_glob = str(self.data_root / "2_Silver_Processed/Options_Market_Data/*/*.parquet") + self.macro_glob = str(self.data_root / "2_Silver_Processed/Macro_History/*/*.parquet") + self.gpr_path = str(self.data_root / "2_Silver_Processed/GPR_index/*.parquet") + + # Startup sanity check (robust against missing data lake). + if not self.data_root.exists(): + print(f"⚠️ Warning: DATA_LAKE_ROOT {self.data_root} does not exist.") + + def _setup_audit_logger(self): + """Daily-partitioned audit log at logs/Parquet_Query/YYYY-MM-DD/sql_retrieval_audit.log.""" + today = datetime.now().strftime("%Y-%m-%d") + log_dir = Path(f"logs/Parquet_Query/{today}") + log_dir.mkdir(parents=True, exist_ok=True) + + log_file = log_dir / "sql_retrieval_audit.log" + + logger = logging.getLogger("SilverSQLAudit") + logger.setLevel(logging.INFO) + + if not logger.handlers: + fh = logging.FileHandler(log_file, encoding='utf-8') + # Structured line format, friendly for ELK / downstream log analytics. + formatter = logging.Formatter('%(asctime)s | %(levelname)s | %(message)s') + fh.setFormatter(formatter) + logger.addHandler(fh) + return logger + + # ========================================================= + # Startup contract validation (Silver-Layer deep alignment check) + # ========================================================= + def _validate_parquet_contract(self) -> None: + """ + Deep path + column alignment check against _EXPECTED_SCHEMA. + + For every Silver dataset this tool consumes, verify: + 1. The resolved glob expands to at least one parquet file on disk + (catches folder renames such as 'GPR_History' vs 'GPR_index'). + 2. The physical parquet schema contains every column the handler + SQL references (catches upstream writer schema drift). + + Emitted audit lines (one per dataset): + SCHEMA_CHECK | dataset= | glob=<...> | files= + | columns= | missing= | status= + + Statuses: + OK — path resolves, all required columns present. + NO_FILES — glob matches zero parquet files. + MISSING_COLUMNS — physical schema is missing expected columns. + READ_FAILED — DuckDB could not probe the parquet (corrupt + / unreadable / bad path). + This method is NON-FATAL by design: dev environments without a full + data lake must still boot. Any failure is loud in the audit log. + """ + for dataset, spec in self._EXPECTED_SCHEMA.items(): + glob_pattern = getattr(self, spec["glob_attr"], None) + required: Set[str] = set(spec["required"]) + + if not glob_pattern: + self.audit_logger.error( + f"SCHEMA_CHECK | dataset={dataset} | status=NO_GLOB_ATTR" + ) + continue + + files = _glob_mod.glob(glob_pattern) + if not files: + self.audit_logger.error( + f"SCHEMA_CHECK | dataset={dataset} | glob={glob_pattern} " + f"| files=0 | status=NO_FILES" + ) + continue + + try: + # DESCRIBE is cheap: it reads only Parquet footer metadata. + desc_df = self.conn.execute( + f"DESCRIBE SELECT * FROM read_parquet('{glob_pattern}') LIMIT 0" + ).df() + actual_cols = set(desc_df["column_name"].tolist()) + missing = required - actual_cols + status = "OK" if not missing else "MISSING_COLUMNS" + self.audit_logger.info( + f"SCHEMA_CHECK | dataset={dataset} | glob={glob_pattern} " + f"| files={len(files)} | columns={len(actual_cols)} " + f"| missing={sorted(missing)} | status={status}" + ) + except Exception as e: + self.audit_logger.error( + f"SCHEMA_CHECK | dataset={dataset} | glob={glob_pattern} " + f"| files={len(files)} | status=READ_FAILED " + f"| error={str(e)[:200]}" + ) + + # ========================================================= + # Structured SQL time-range audit (one line per handler invocation) + # ========================================================= + def _audit_sql_range( + self, + handler: str, + ticker: Optional[str], + meta: MetadataExtraction, + mode: str, + start: Optional[Any] = None, + end: Optional[Any] = None, + window_days: Optional[int] = None, + extra: Optional[str] = None, + ) -> None: + """ + Emit a structured SQL_RANGE line *before* executing a handler query. + + Two modes captured: + - mode=window : explicit WHERE filter on a date column. + start / end / window_days are the filter params. + - mode=latest_only : ORDER BY DESC LIMIT 1 (no WHERE on date). + end = anchor / latest-known data date; window_days + is logged for traceability but NOT in the SQL. + + Format (pipe-separated for log analytics): + SQL_RANGE | handler=<> | ticker=<> | mode=<> | time_window= + | start=<> | end=<> | window_days=<> | extra=<> + """ + tw_val = getattr(meta.time_window, "value", meta.time_window) if meta else None + parts = ["SQL_RANGE", f"handler={handler}"] + if ticker is not None: + parts.append(f"ticker={ticker}") + parts.append(f"mode={mode}") + parts.append(f"time_window={tw_val}") + if start is not None: + parts.append(f"start={start}") + if end is not None: + parts.append(f"end={end}") + if window_days is not None: + parts.append(f"window_days={window_days}") + if extra: + parts.append(f"extra={extra}") + self.audit_logger.info(" | ".join(parts)) + + # ========================================================= + # Dynamic Time-Anchor helpers (replaces CURRENT_DATE semantics) + # ========================================================= + def _load_runtime_state(self) -> Dict[str, Any]: + """ + Load dataset-freshness state from config/runtime/collect_data_state.json. + Returns the raw dict. If the file is missing/broken this is NON-FATAL: + _get_anchor_date() falls back to date.today() so the tool stays usable + in dev environments that don't have the runtime state file yet. + """ + try: + # project root = Scripts/retrieval/sql_tools.py -> parents[2] + project_root = Path(__file__).resolve().parents[2] + state_path = project_root / "config" / "runtime" / "collect_data_state.json" + if state_path.exists(): + with open(state_path, "r", encoding="utf-8") as f: + return json.load(f) + except Exception as e: + # Audit logger may not exist yet at __init__ time — keep this as print. + print(f"⚠️ SilverSQLTool: failed to load runtime state: {e}") + return {} + + def _get_anchor_date(self, dataset: str) -> date: + """ + Return the most recently verified data date for `dataset`, derived from + config/runtime/collect_data_state.json. This is the institutional + replacement for CURRENT_DATE — it survives weekends, holidays and + backfill runs (wall-clock != last successful data ingestion). + Accepts both 'YYYY-MM-DD' daily keys and 'YYYY-MM' monthly keys. + Falls back to today() if no state key is available. + """ + key = self._ANCHOR_KEY.get(dataset) + last_keys = (self.runtime_state or {}).get("last_run_keys", {}) + raw = last_keys.get(key) if key else None + if raw: + try: + if len(raw) == 7: # Monthly: "YYYY-MM" + return datetime.strptime(raw + "-01", "%Y-%m-%d").date() + if len(raw) == 10: # Daily: "YYYY-MM-DD" + return datetime.strptime(raw, "%Y-%m-%d").date() + except Exception: + pass + return date.today() + + def _time_window_to_days(self, tw: Any, default: int = 5) -> int: + """ + Translate metadata.time_window (str | TimeWindow) into a day count via the + global TIME_WINDOW_DAYS policy in Scripts.retrieval.schema. Thin wrapper + so every handler reads through the same API — never hard-code day counts. + """ + return time_window_to_days(tw, default=default) + + # ========================================================= + # Metric fuzzy matching (ontology-aware; ticker is NEVER fuzzy) + # ========================================================= + @staticmethod + def _normalize(s: str) -> str: + """Lowercase + strip non-alphanumerics to collapse punctuation/space variants.""" + return "".join(ch for ch in str(s).lower() if ch.isalnum()) + + def _fuzzy_match_metric(self, metric: str) -> Optional[str]: + """ + Map the LLM-extracted metric label to a canonical dispatcher key. + Resolution order: + 1. Exact match on dispatcher key. + 2. Case/punctuation-insensitive exact match. + 3. difflib close-match against dispatcher keys + ontology + (ALLOWED_METRICS and METRIC_TO_COLUMN_MAPPING keys). + Ticker symbols NEVER pass through this path — they remain strict + .upper().strip() lookups to prevent SQL executing against the wrong symbol. + """ + if not metric: + return None + if metric in self.metric_dispatcher: + return metric + + norm_target = self._normalize(metric) + # Normalized exact match (covers "implied volatility" vs "Implied Volatility (IV)"). + for key in self.metric_dispatcher.keys(): + if self._normalize(key) == norm_target: + return key + + # Ontology-aware fuzzy candidates — union of every known metric surface + # form so LLM-side aliases still route to a valid handler. + candidates = ( + list(self.metric_dispatcher.keys()) + + list(ALLOWED_METRICS) + + list(METRIC_TO_COLUMN_MAPPING.keys()) + ) + norm_map: Dict[str, str] = {} + for k in candidates: + norm_map.setdefault(self._normalize(k), k) + + match = difflib.get_close_matches( + norm_target, list(norm_map.keys()), n=1, cutoff=0.75 + ) + if match: + canonical = norm_map[match[0]] + # Only return if we can actually dispatch it — ontology members + # without a handler must surface as UNAUTHORIZED_METRIC, not silently drop. + return canonical if canonical in self.metric_dispatcher else None + return None + + # Cap on tickers actually dispatched. Even if the Transformer produces + # N tickers, we execute at most this many SQL round-trips per request + # to keep Silver latency bounded (each ticker = 1 DuckDB read per + # metric). Excess tickers are logged and dropped LOUDLY. + _MAX_TICKERS_PER_QUERY = int(os.getenv("SILVER_MAX_TICKERS", "5")) + + # Per-call predicate cache. Set at the top of query_parquet_by_metadata + # so handlers can look up their source's window via + # `self._current_predicates.get(SourceTimeKey.SILVER_*)`. Cleared at the + # end of the call so the tool stays thread-ish-safe for sequential awaits + # (DuckDB connection is already single-threaded). + _current_predicates: Optional[Dict[SourceTimeKey, TimePredicate]] = None + + def _predicate_for(self, key: SourceTimeKey) -> Optional[TimePredicate]: + """Return the compiled predicate for a Silver source, or None when the + caller didn't supply `time_predicates`. Handlers that want per-source + alignment should branch on `None` and fall back to the legacy + `_time_window_to_days` path for backward compatibility. + """ + if not self._current_predicates: + return None + return self._current_predicates.get(key) + + async def query_parquet_by_metadata( + self, + metadata: MetadataExtraction, + time_predicates: Optional[Dict[SourceTimeKey, TimePredicate]] = None, + ) -> Dict[str, Any]: + """Main entry: route extracted metrics to DuckDB handlers and aggregate results. + + Fixes landed here (2026-04-22): + 1. **Iterates ALL tickers** (capped at _MAX_TICKERS_PER_QUERY) instead + of silently using only tickers[0]. Today's Q3 audit shows 57 + tickers in metadata but anchors for only 1 — root cause. + 2. Results carry per-ticker lineage so the Analyst can cite + "data anchor for SPY" vs "data anchor for QQQ" precisely. + 3. **Per-source time alignment** — when `time_predicates` is + provided by MasterRetriever, handlers read a pre-compiled + `TimePredicate` that already handled MONTHLY-widening for GPR + and weekend-safety for DAILY sources. Handlers that don't need + it are a no-op. + """ + start_ts = datetime.now() + results: Dict[str, Any] = {"values": {}, "lineage_anchors": []} + # Publish predicates on the instance so handlers can pull them + # without changing every handler signature. Cleared in the finally. + self._current_predicates = time_predicates + + if not metadata.tickers: + self.audit_logger.warning("EMPTY_TICKERS | Skipping SQL execution.") + return results + + # Ticker MUST stay exact — we only ever .upper() + .strip() it, no fuzzy match. + tickers_all = [t.upper().strip() for t in metadata.tickers if t and t.strip()] + tickers = tickers_all[: self._MAX_TICKERS_PER_QUERY] + if len(tickers_all) > len(tickers): + self.audit_logger.warning( + f"TICKER_CAP | received={len(tickers_all)} executing={len(tickers)} " + f"dropped={tickers_all[len(tickers):]}" + ) + self.audit_logger.info( + f"START_QUERY | Tickers: {tickers} | Requested: {metadata.metrics}" + ) + + for ticker in tickers: + for metric in metadata.metrics: + # Metric strings come from an LLM and may drift from dispatcher + # keys. Canonicalise via ontology-backed fuzzy match. Ticker is + # NOT fuzzy — see above. + canonical_key = self._fuzzy_match_metric(metric) + if canonical_key is None: + self.audit_logger.warning(f"UNAUTHORIZED_METRIC: {metric}") + continue + + if canonical_key != metric: + self.audit_logger.info(f"FUZZY_MATCH | '{metric}' -> '{canonical_key}'") + + handler = self.metric_dispatcher.get(canonical_key) + if not handler: + continue + + try: + res = handler(ticker, metadata) + if res: + results["values"].update(res.get("values", {})) + results["lineage_anchors"].extend(res.get("lineage_anchors", [])) + except Exception as e: + self.audit_logger.error( + f"EXECUTION_ERROR | Ticker: {ticker} | Metric: {metric} | Error: {str(e)}" + ) + + latency = (datetime.now() - start_ts).total_seconds() + self.audit_logger.info( + f"FINISH_QUERY | Latency: {latency:.3f}s | Anchors_Found: {len(results['lineage_anchors'])}" + ) + # Always clear — predicates are per-call and must not leak to the + # next metadata invocation. + self._current_predicates = None + return results + + # ========================================================= + # Business handlers — deep mapping of schema metrics. + # ========================================================= + + def _handle_put_call_ratio(self, ticker: str, meta: MetadataExtraction) -> Dict[str, Any]: + """ + Put/Call Ratio with a Dynamic Time Anchor. + - Anchor date is sourced from config/runtime/collect_data_state.json (options_daily), + replacing CURRENT_DATE so backfills, weekends, and holidays are handled correctly. + - Lookback window honors metadata.time_window via the global TIME_WINDOW_DAYS policy. + Explicit short windows (today / yesterday) are HONOURED verbatim so PCR and IV-skew + anchor on the SAME day — production audit on 2026-04-22 showed a previous + `max(5, …)` floor caused `yesterday` to return a 5-day average while IV Skew + returned a 2-day snapshot, producing inconsistent time semantics in one report. + The 5-day floor is still applied ONLY when the user gave no time signal at all + (raw time_window empty / unknown), preserving the original "short-sample noise" + guard for under-specified queries. + - Per-source time alignment (2026-04-22): when MasterRetriever supplied a + pre-compiled `TimePredicate` for `silver.options`, we honour its + (start_date, end_date) directly — this is weekend-safe (the adapter + widens DAILY sources to a 3-day floor) so Monday-anchored "yesterday" + queries automatically reach back to Friday without per-handler logic. + - Parameters are SQL-bound (no string interpolation) — ticker stays strict. + """ + anchor = self._get_anchor_date("options") + predicate = self._predicate_for(SourceTimeKey.SILVER_OPTIONS) + tw_val = getattr(meta.time_window, "value", meta.time_window) + + if predicate is not None: + # Adapter already resolved weekend-safety + min-lookback; use it. + start_date = predicate.start_date + anchor = predicate.end_date # source-aligned anchor (same day by default) + window_days = predicate.window_days + else: + # Legacy path — honour explicit short-window intents, apply the + # 5-day floor only when the user gave no time signal at all. + explicit_short = isinstance(tw_val, str) and tw_val.lower() in {"today", "yesterday", "past_week"} + if explicit_short: + window_days = self._time_window_to_days(meta.time_window, default=2) + else: + window_days = max(5, self._time_window_to_days(meta.time_window, default=5)) + start_date = anchor - timedelta(days=window_days) + + # Explicit SQL time-range audit: this handler applies a real WHERE filter, + # so start/end/window_days are logged verbatim for traceability. + self._audit_sql_range( + handler="put_call_ratio", ticker=ticker, meta=meta, + mode="window", start=start_date, end=anchor, window_days=window_days, + ) + + query = f""" + SELECT + snapshot_date, + SUM(CASE WHEN option_type = 'put' THEN volume ELSE 0 END) as put_vol, + SUM(CASE WHEN option_type = 'call' THEN volume ELSE 0 END) as call_vol, + SUM(CASE WHEN option_type = 'put' THEN open_interest ELSE 0 END) as put_oi, + SUM(CASE WHEN option_type = 'call' THEN open_interest ELSE 0 END) as call_oi + FROM read_parquet('{self.options_glob}') + WHERE symbol = ? + AND CAST(snapshot_date AS DATE) BETWEEN CAST(? AS DATE) AND CAST(? AS DATE) + GROUP BY snapshot_date + ORDER BY snapshot_date DESC + LIMIT 1 + """ + df = self.conn.execute(query, [ticker, start_date, anchor]).df() + if df.empty: return None + + row = df.iloc[0] + pcr_vol = row['put_vol'] / row['call_vol'] if row['call_vol'] > 0 else 0 + pcr_oi = row['put_oi'] / row['call_oi'] if row['call_oi'] > 0 else 0 + + return { + "values": { + "pcr_volume": round(pcr_vol, 3), + "pcr_open_interest": round(pcr_oi, 3), + "pcr_status": "Bearish Sentiment" if pcr_vol > 1.0 else "Bullish/Neutral" + }, + "lineage_anchors": [f"PCR_AGG_{ticker}_{row['snapshot_date']}"] + } + + def _handle_options_analysis(self, ticker: str, meta: MetadataExtraction) -> Dict[str, Any]: + """Surface latest ATM IV + freshness using schema fields: implied_volatility, moneyness_pct, spread_pct.""" + # This handler applies no WHERE filter on snapshot_date; it picks the + # latest available row. Log the anchor + requested window so the audit + # trail still captures intended temporal context (useful when debugging + # "why did the model see data older than expected"). + anchor = self._get_anchor_date("options") + window_days = self._time_window_to_days(meta.time_window, default=180) + self._audit_sql_range( + handler="options_analysis", ticker=ticker, meta=meta, + mode="latest_only", end=anchor, window_days=window_days, + extra="filter=is_liquid=true;dte_in_[7,45]", + ) + + query = f""" + SELECT + snapshot_date, contract_symbol, implied_volatility, + moneyness_pct, spread_pct, dte + FROM read_parquet('{self.options_glob}') + WHERE symbol = ? AND is_liquid = true AND dte BETWEEN 7 AND 45 + ORDER BY snapshot_date DESC, moneyness_pct ASC + """ + df = self.conn.execute(query, [ticker]).df() + if df.empty: return None + + latest_date = df['snapshot_date'].iloc[0] + # ATM definition: smallest |moneyness_pct| — already guaranteed by ORDER BY moneyness_pct ASC. + atm_iv = df[df['snapshot_date'] == latest_date]['implied_volatility'].iloc[0] + + return { + "values": { + "latest_atm_iv": round(atm_iv, 4), + "data_freshness": latest_date + }, + "lineage_anchors": df['contract_symbol'].head(2).tolist() + } + + def _handle_liquidity_analysis(self, ticker: str, meta: MetadataExtraction) -> Dict[str, Any]: + """Liquidity & execution-risk snapshot. + + Upgrade note (2026-04-22): + - Now surfaces OPEN INTEREST and LIQUID_CONTRACT_COUNT so the + "Options Liquidity" / "Open Interest" dispatches carry the data + the Analyst expects (previously only total_vol + avg_spread). + - Still `latest_only` — picks the most recent snapshot_date with + rows for this symbol so the result survives weekends/holidays. + """ + anchor = self._get_anchor_date("options") + window_days = self._time_window_to_days(meta.time_window, default=180) + self._audit_sql_range( + handler="liquidity_analysis", ticker=ticker, meta=meta, + mode="latest_only", end=anchor, window_days=window_days, + ) + + query = f""" + SELECT + snapshot_date, + SUM(volume) AS total_vol, + SUM(open_interest) AS total_oi, + AVG(spread_pct) AS avg_spread, + SUM(CASE WHEN is_liquid THEN 1 ELSE 0 END) AS liquid_contracts + FROM read_parquet('{self.options_glob}') + WHERE symbol = ? + GROUP BY snapshot_date + ORDER BY snapshot_date DESC + LIMIT 1 + """ + res = self.conn.execute(query, [ticker]).fetchone() + if not res: + return None + + total_vol = int(res[1] or 0) + total_oi = int(res[2] or 0) + avg_spread = float(res[3] or 0.0) + liquid_ct = int(res[4] or 0) + + return { + "values": { + f"{ticker}_daily_option_volume": total_vol, + f"{ticker}_open_interest": total_oi, + f"{ticker}_avg_spread_pct": round(avg_spread * 100, 3), + f"{ticker}_liquid_contracts": liquid_ct, + f"{ticker}_market_impact_risk": "High" if avg_spread > 0.02 else "Low", + }, + "lineage_anchors": [f"LIQ_{ticker}_{res[0]}"], + } + + def _handle_pricing_spread(self, ticker: str, meta: MetadataExtraction) -> Dict[str, Any]: + """Pricing / spread / underlying-price snapshot. + + Returns the latest-snapshot ATM-adjacent bid/ask mid so queries like + "what's the current SPY option spread" land on quote data instead + of the IV-centric options-analysis handler. + """ + anchor = self._get_anchor_date("options") + window_days = self._time_window_to_days(meta.time_window, default=180) + self._audit_sql_range( + handler="pricing_spread", ticker=ticker, meta=meta, + mode="latest_only", end=anchor, window_days=window_days, + extra="filter=is_liquid=true;dte_in_[7,45]", + ) + + query = f""" + SELECT + snapshot_date, + underlying_price, + AVG(bid) AS avg_bid, + AVG(ask) AS avg_ask, + AVG(spread_pct) AS avg_spread_pct, + AVG(last_price) AS avg_last_price + FROM read_parquet('{self.options_glob}') + WHERE symbol = ? + AND is_liquid = true + AND dte BETWEEN 7 AND 45 + GROUP BY snapshot_date, underlying_price + ORDER BY snapshot_date DESC + LIMIT 1 + """ + res = self.conn.execute(query, [ticker]).fetchone() + if not res: + return None + + return { + "values": { + f"{ticker}_underlying_price": float(res[1] or 0), + f"{ticker}_avg_bid": round(float(res[2] or 0), 3), + f"{ticker}_avg_ask": round(float(res[3] or 0), 3), + f"{ticker}_avg_spread_pct": round(float(res[4] or 0) * 100, 3), + f"{ticker}_avg_last_price": round(float(res[5] or 0), 3), + }, + "lineage_anchors": [f"PX_{ticker}_{res[0]}"], + } + + def _handle_macro_analysis(self, ticker: str, meta: MetadataExtraction) -> Dict[str, Any]: + """Macro-series latest-value read. + + Storage vs. query reconciliation (the ETF→index alias fix): + - Our Macro_History parquet stores canonical *indices* (^GSPC, + ^IXIC, FEDFUNDS, …). Users and the LLM write *ETFs* (SPY, QQQ). + - ETF_TO_MACRO_ALIAS (config/financial_ontology.py) translates + the common ETF tickers to the index the table actually holds. + - Translation is LOCAL to this handler; options / SEC handlers + keep the ETF symbol because their tables store ETFs. + + Schema note (Scripts/data_collection/scrapers/macro_data_pipeline.py): + - Yahoo Finance / daily series -> daily_change_pct populated, mom_change_pct = NULL. + - FRED / monthly macro series -> mom_change_pct populated, daily_change_pct = NULL. + - BOTH change columns are stored ALREADY as percentage points + (e.g. 2.35 means +2.35%). Do NOT multiply by 100 again here. + Defensive fallback: + - If mom_change is NULL, prefer daily_change; if both are NULL, emit 'n/a'. + """ + anchor = self._get_anchor_date("macro") + window_days = self._time_window_to_days(meta.time_window, default=180) + + # ETF → underlying-index translation (handler-local, audit-logged). + query_ticker = ETF_TO_MACRO_ALIAS.get(ticker, ticker) + alias_applied = query_ticker != ticker + + self._audit_sql_range( + handler="macro_analysis", ticker=ticker, meta=meta, + mode="latest_only", end=anchor, window_days=window_days, + extra=(f"alias={ticker}->{query_ticker}" if alias_applied else None), + ) + + query = f""" + SELECT observation_date, value, daily_change_pct, mom_change_pct + FROM read_parquet('{self.macro_glob}') + WHERE symbol = ? + ORDER BY observation_date DESC LIMIT 1 + """ + res = self.conn.execute(query, [query_ticker]).fetchone() + if not res: return None + + obs_date, last_value, daily_chg, mom_chg = res[0], res[1], res[2], res[3] + # Lineage always records BOTH the user-facing ticker and the queried + # symbol so the Analyst can explain the alias in the compliance footer. + lineage_prefix = f"MACRO_{ticker}" if not alias_applied else f"MACRO_{ticker}_AS_{query_ticker}" + + if mom_chg is not None: + change_label, change_val = f"{ticker}_mom_change", mom_chg + elif daily_chg is not None: + change_label, change_val = f"{ticker}_daily_change", daily_chg + else: + change_label, change_val = f"{ticker}_change", None + + change_str = f"{round(change_val, 2)}%" if change_val is not None else "n/a" + + return { + "values": { + f"{ticker}_last_value": last_value, + change_label: change_str, + }, + "lineage_anchors": [f"{lineage_prefix}_{obs_date}"] + } + + def _handle_geopolitical_analysis(self, ticker: str, meta: MetadataExtraction) -> Dict[str, Any]: + """GPR regime snapshot using gpr_percentile + gpr_mom_pct per GPR_Index schema. + + GPR is monthly; anchor resolves to the first-of-month of the last + successfully ingested month (collect_data_state.json -> gpr_monthly). + No WHERE filter is applied here — we always return the latest month — + but the anchor is logged so the audit trail is still decisive. + """ + anchor = self._get_anchor_date("gpr") + window_days = self._time_window_to_days(meta.time_window, default=180) + self._audit_sql_range( + handler="geopolitical_analysis", ticker=ticker, meta=meta, + mode="latest_only", end=anchor, window_days=window_days, + extra="cadence=monthly", + ) + + query = f""" + SELECT date, gpr, gpr_percentile, gpr_mom_pct + FROM read_parquet('{self.gpr_path}') + ORDER BY date DESC LIMIT 1 + """ + res = self.conn.execute(query).fetchone() + if not res: return None + + mom = res[3] + trend = "Rising" if (mom is not None and mom > 0) else ("Falling" if mom is not None else "Unknown") + return { + "values": { + "gpr_index_level": res[1], + "gpr_percentile": f"{res[2]}%", + "gpr_trend": trend + }, + "lineage_anchors": [f"GPR_{res[0].strftime('%Y%m')}"] + } \ No newline at end of file diff --git a/Scripts/retrieval/time_adapter.py b/Scripts/retrieval/time_adapter.py new file mode 100644 index 0000000..56ed520 --- /dev/null +++ b/Scripts/retrieval/time_adapter.py @@ -0,0 +1,482 @@ +""" + Different data sources use different time types and granularities: + + Gold.News : `unified_timestamp` / `publish_timestamp` (Unix seconds, event-level) + Gold.SEC : `unified_timestamp` / `filed_at` / `transaction_date` + (Unix seconds + ISO-8601 strings, event-level) + Gold.GPR : `unified_timestamp` / `publish_timestamp` (Unix seconds, MONTHLY) + Silver.Options : `snapshot_date` (VARCHAR ISO date, trading-day) + Silver.Macro : `observation_date` / `retrieval_date` (VARCHAR ISO date, daily) + Silver.GPR : `date` / `month` (TIMESTAMP_NS, MONTHLY) + + Applying a single (start_ts, end_ts) window to all of them is wrong: + - "yesterday" against a MONTHLY source = 0 rows (should widen to the + current month so GPR always returns its most recent observation). + - "yesterday" against a DAILY source on a Monday = 0 rows (weekend + gap; we must widen at least to Friday). + - A naive Unix-seconds filter against SEC returns 0 because legacy + SEC payloads only carry ISO-8601 strings, not an epoch key. + + This adapter compiles **one `TimePredicate` per source**, pre-widened + for the source's granularity, so every downstream retriever receives + semantics that match its physical schema without branching logic + sprinkled across the codebase. + +Design: + - Stateless. + - No Qdrant / DuckDB dependency (this is the *contract*, not the + execution). Both layers consume a `TimePredicate` but decide how + to bind it to their physical APIs. + - Fully auditable: every predicate serialises via `.to_dict()` for the + retriever audit trail. +""" + +from __future__ import annotations + +import logging +from dataclasses import dataclass, field +from datetime import date, datetime, timedelta, timezone +from enum import Enum +from typing import Any, Dict, List, Optional, Tuple + +from Scripts.core.trading_calendar import is_business_day, previous_business_day +from Scripts.retrieval.schema import TIME_WINDOW_DAYS, TimeWindow, time_window_to_days + +logger = logging.getLogger(__name__) + +__all__ = [ + "TimeGranularity", + "SourceTimeKey", + "SourceTimeSpec", + "TimePredicate", + "SOURCE_SPECS", + "compile_predicate", + "compile_all", + "predicates_from_serialised", + "union_epoch_range", +] + + +# Semantic labels for which DAILY sources should use business-day semantics +# rather than calendar-day widening. Matches the user-visible TimeWindow +# values so routing is legible in logs. +_DAILY_BUSDAY_LABELS: set = {"today", "yesterday"} + + +# --------------------------------------------------------------------------- +# Registry +# --------------------------------------------------------------------------- + + +class TimeGranularity(str, Enum): + """Physical cadence of a data source. + + Determines how a sub-granularity semantic window (e.g. "yesterday") + must be widened so the source has any chance of returning data. + """ + + EVENT = "event" # News, SEC — sub-daily individual timestamps. + DAILY = "daily" # Options snapshots, macro daily series. + MONTHLY = "monthly" # GPR, FRED monthly macro series. + + +class SourceTimeKey(str, Enum): + """Logical handle used by upstream callers to reference a data source. + + Strings chosen to be stable over refactors so audit logs stay diffable. + """ + + GOLD_NEWS = "gold.news" + GOLD_SEC = "gold.sec" + GOLD_GPR = "gold.gpr" + SILVER_OPTIONS = "silver.options" + SILVER_MACRO = "silver.macro" + SILVER_GPR = "silver.gpr" + + +@dataclass(frozen=True) +class SourceTimeSpec: + """Physical time contract for one data source. + + Attributes + ---------- + granularity + Event / Daily / Monthly — drives widening policy. + time_keys + Ordered tuple of physical payload/column names that carry a parseable + instant. Retrievers should attempt them in order (most specific first). + For Qdrant this is the payload key; for Parquet this is the column. + key_units + Physical type, aligned 1:1 with `time_keys`. One of: + - "epoch_s" : Unix seconds (int/float) + - "epoch_ms" : Unix milliseconds (int/float) + - "iso_date" : 'YYYY-MM-DD' + - "iso_datetime" : ISO-8601 (may carry timezone offset or 'Z') + - "ts_ns" : pandas/arrow TIMESTAMP_NS (nanoseconds since epoch) + min_lookback_days + Floor on the widening when the semantic window is narrower than the + source's cadence. MONTHLY sources take 35 days so GPR's first-of- + month row is always inside the window. DAILY sources take 3 days to + survive weekend gaps. + """ + + granularity: TimeGranularity + time_keys: Tuple[str, ...] + key_units: Tuple[str, ...] + min_lookback_days: int = 1 + + +# Authoritative registry. Keep this in sync with +# docs/Data_source_docs/Time_Schema_Audit.md. +SOURCE_SPECS: Dict[SourceTimeKey, SourceTimeSpec] = { + SourceTimeKey.GOLD_NEWS: SourceTimeSpec( + granularity=TimeGranularity.EVENT, + # `unified_timestamp` is the post-2026-04-22 standard; `publish_timestamp` + # is the legacy key that news_scraper has always written. Both carry + # Unix seconds, so Qdrant `Range` binds against either transparently. + time_keys=("unified_timestamp", "publish_timestamp"), + key_units=("epoch_s", "epoch_s"), + min_lookback_days=1, + ), + SourceTimeKey.GOLD_SEC: SourceTimeSpec( + granularity=TimeGranularity.EVENT, + # Legacy SEC payloads only carry ISO strings. Post-2026-04-22 + # ingestion stamps a numeric `unified_timestamp` derived from + # `transaction_date` → the Qdrant numeric Range now binds. + time_keys=("unified_timestamp", "filed_at", "transaction_date"), + key_units=("epoch_s", "iso_datetime", "iso_date"), + # SEC filings land in bursts; a 3-day floor keeps weekend-edge + # "yesterday" queries non-empty without widening the semantic intent. + min_lookback_days=3, + ), + SourceTimeKey.GOLD_GPR: SourceTimeSpec( + granularity=TimeGranularity.MONTHLY, + time_keys=("unified_timestamp", "publish_timestamp"), + key_units=("epoch_s", "epoch_s"), + # 35 days = "always catches the latest first-of-month anchor", + # regardless of which calendar day the user queried on. + min_lookback_days=35, + ), + SourceTimeKey.SILVER_OPTIONS: SourceTimeSpec( + granularity=TimeGranularity.DAILY, + time_keys=("snapshot_date",), + key_units=("iso_date",), + min_lookback_days=3, + ), + SourceTimeKey.SILVER_MACRO: SourceTimeSpec( + granularity=TimeGranularity.DAILY, + # `observation_date` is the authoritative series date; `retrieval_date` + # is the ingestion day — kept second so callers can fall back. + time_keys=("observation_date", "retrieval_date"), + key_units=("iso_date", "iso_date"), + min_lookback_days=3, + ), + SourceTimeKey.SILVER_GPR: SourceTimeSpec( + granularity=TimeGranularity.MONTHLY, + time_keys=("date", "month"), + key_units=("ts_ns", "ts_ns"), + min_lookback_days=35, + ), +} + + +# --------------------------------------------------------------------------- +# Compiled predicate +# --------------------------------------------------------------------------- + + +@dataclass(frozen=True) +class TimePredicate: + """A physically-executable time window, pre-aligned for one source. + + A predicate is the *compiled* artefact of (semantic TimeWindow + anchor + + source spec). Retrievers must never re-derive these values: they should + consume `start_epoch_s` / `end_epoch_s` for Qdrant numeric Ranges, or + `start_date` / `end_date` for Parquet/DuckDB BETWEEN filters. + """ + + source: SourceTimeKey + label: str + granularity: TimeGranularity + start_date: date + end_date: date + start_epoch_s: int + end_epoch_s: int + window_days: int + widened: bool = False + widen_reason: Optional[str] = None + # The physical keys the retriever should build range filters on. Copied + # off `SourceTimeSpec` at compile time so a consumer can operate on just + # the predicate, without another registry lookup. + time_keys: Tuple[str, ...] = field(default_factory=tuple) + key_units: Tuple[str, ...] = field(default_factory=tuple) + + def to_dict(self) -> Dict[str, Any]: + return { + "source": self.source.value, + "label": self.label, + "granularity": self.granularity.value, + "start_date": self.start_date.isoformat(), + "end_date": self.end_date.isoformat(), + "start_epoch_s": self.start_epoch_s, + "end_epoch_s": self.end_epoch_s, + "window_days": self.window_days, + "widened": self.widened, + "widen_reason": self.widen_reason, + "time_keys": list(self.time_keys), + "key_units": list(self.key_units), + } + + @classmethod + def from_dict(cls, d: Dict[str, Any]) -> "TimePredicate": + """Rebuild a live predicate from the serialised `to_dict()` form. + + This is the round-trip counterpart used by agents that pick the + predicate set off AgentState (e.g. the Checker's rescue path): + the master retriever serialises once into + `state["time_range"]["source_predicates"]`, and every downstream + consumer rehydrates via this classmethod so it never has to + recompute the window. Guaranteed to be predicate-identical to the + one that produced the serialisation — this is what makes the + initial-vs-rescue windows match in lockstep (was the 3d/2d drift + in docs/test/2026-04-22/router_e2e_deep_analysis.md). + """ + return cls( + source=SourceTimeKey(d["source"]), + label=str(d.get("label", "")), + granularity=TimeGranularity(d["granularity"]), + start_date=date.fromisoformat(d["start_date"]), + end_date=date.fromisoformat(d["end_date"]), + start_epoch_s=int(d["start_epoch_s"]), + end_epoch_s=int(d["end_epoch_s"]), + window_days=int(d["window_days"]), + widened=bool(d.get("widened", False)), + widen_reason=d.get("widen_reason"), + time_keys=tuple(d.get("time_keys", ()) or ()), + key_units=tuple(d.get("key_units", ()) or ()), + ) + + +# --------------------------------------------------------------------------- +# Internal helpers +# --------------------------------------------------------------------------- + + +def _first_of_month(d: date) -> date: + return d.replace(day=1) + + +def _to_epoch_bounds(start: date, end: date) -> Tuple[int, int]: + """Convert a (start_date, end_date) pair to Unix-seconds bounds in UTC. + + End-inclusive: we push `end` to 23:59:59 so a same-day predicate + (e.g. "today") still covers every event that occurred during that day. + """ + start_dt = datetime(start.year, start.month, start.day, tzinfo=timezone.utc) + end_dt = datetime(end.year, end.month, end.day, 23, 59, 59, tzinfo=timezone.utc) + return int(start_dt.timestamp()), int(end_dt.timestamp()) + + +# --------------------------------------------------------------------------- +# Public API +# --------------------------------------------------------------------------- + + +def compile_predicate( + time_window: Any, + source: SourceTimeKey, + anchor: date, + *, + label: Optional[str] = None, +) -> TimePredicate: + """Compile a single source-specific `TimePredicate`. + + Parameters + ---------- + time_window + A `TimeWindow` enum, its string value, or anything `time_window_to_days` + accepts. Missing/unknown inputs fall back to PAST_SIX_MONTHS (180d) + via `time_window_to_days(default=180)`. + source + The `SourceTimeKey` that identifies the data source. + anchor + The "end of window" date — usually the most recent successful + ingestion date (Silver's `_get_anchor_date`), NOT `date.today()`. + This is what makes the predicate robust over weekends/holidays. + label + Human-readable label for audit logs. Defaults to the semantic value + of `time_window`. + + Returns + ------- + TimePredicate + Ready-to-execute predicate. For MONTHLY sources with a sub-month + request, the start_date is snapped to the first of the anchor month. + """ + spec = SOURCE_SPECS[source] + + base_days = time_window_to_days(time_window, default=180) + resolved_label = label or ( + getattr(time_window, "value", None) or (str(time_window) if time_window is not None else "past_six_months") + ) + label_norm = str(resolved_label).lower() + + # Anchor is usually the most recent ingestion day (options_daily from + # config/runtime/collect_data_state.json). If — for any reason — that + # value lands on a weekend (e.g. a manual backfill wrote a Saturday key) + # snap the end of the window onto the previous trading day so DAILY + # sources do not anchor on a non-existent partition. EVENT and MONTHLY + # sources leave the anchor alone because their physical data is calendar- + # day based (news can publish on weekends; GPR is first-of-month). + end: date = anchor + if spec.granularity == TimeGranularity.DAILY and not is_business_day(anchor): + end = previous_business_day(anchor) + + start: date = end - timedelta(days=base_days) + widened = False + widen_reason: Optional[str] = None + + # --- Source-specific widening rules -------------------------------------- + # Branch A: DAILY + explicit business-day semantics ("today" / "yesterday"). + # This is the fix for docs/test/2026-04-22/router_e2e_deep_analysis.md + # lines 120-133: a 2-calendar-day window on a Tuesday anchor silently + # sampled Sunday (no partition), which caused `latest_atm_iv` to flip + # between revisions. Business-day semantics pin the window to the actual + # trading day before `end`, so rescue re-queries return the same row. + if ( + spec.granularity == TimeGranularity.DAILY + and label_norm in _DAILY_BUSDAY_LABELS + ): + if label_norm == "today": + start = end + widened = False + widen_reason = "daily_today_busday (start=end=anchor)" + else: # yesterday + start = previous_business_day(end) + widened = True + widen_reason = ( + f"daily_yesterday_busday " + f"(prev_business_day({end.isoformat()})={start.isoformat()})" + ) + elif base_days < spec.min_lookback_days: + if spec.granularity == TimeGranularity.MONTHLY: + # Always include the full anchor month so the source's first-of- + # month row is inside the window. If the user asked for a span + # wider than one month (e.g. PAST_SIX_MONTHS=180d) this branch + # doesn't fire and the natural window is used. + new_start = _first_of_month(end) + start = min(start, new_start) + widened = True + widen_reason = ( + f"monthly_widen_to_{(end - start).days}d " + f"(base={base_days}d < min={spec.min_lookback_days}d)" + ) + elif spec.granularity == TimeGranularity.DAILY: + # Non-YESTERDAY short windows (PAST_WEEK etc.) still get the + # calendar-day floor so the window survives weekends without + # forcing a full business-day walk. + start = end - timedelta(days=spec.min_lookback_days) + widened = True + widen_reason = f"daily_min_{spec.min_lookback_days}d (base={base_days}d)" + elif spec.granularity == TimeGranularity.EVENT: + start = end - timedelta(days=spec.min_lookback_days) + widened = True + widen_reason = f"event_min_{spec.min_lookback_days}d (base={base_days}d)" + + start_epoch, end_epoch = _to_epoch_bounds(start, end) + window_days = (end - start).days + + predicate = TimePredicate( + source=source, + label=resolved_label, + granularity=spec.granularity, + start_date=start, + end_date=end, + start_epoch_s=start_epoch, + end_epoch_s=end_epoch, + window_days=window_days, + widened=widened, + widen_reason=widen_reason, + time_keys=spec.time_keys, + key_units=spec.key_units, + ) + + if widened: + logger.info( + f"🕒 [TimeAdapter] {source.value}: widened → " + f"{start.isoformat()}..{end.isoformat()} ({window_days}d) | " + f"reason={widen_reason}" + ) + return predicate + + +def compile_all( + time_window: Any, + anchor: date, + *, + label: Optional[str] = None, +) -> Dict[SourceTimeKey, TimePredicate]: + """Compile predicates for every registered source in one call. + + Convenience for upstream orchestration (master_retriever) so the + full per-source predicate set is materialised once, attached to the + run payload for audit, and dispatched to Gold/Silver without + re-derivation. + """ + return { + src: compile_predicate(time_window, src, anchor, label=label) + for src in SOURCE_SPECS + } + + +def predicates_from_serialised( + serialised: Dict[str, Any], +) -> Dict[SourceTimeKey, TimePredicate]: + """Inverse of `{key.value: pred.to_dict() for …}` — round-trips predicates. + + Accepts the dict shape attached to + `state["time_range"]["source_predicates"]` by `MasterRetriever. + _compute_time_range` and returns the live `{SourceTimeKey: TimePredicate}` + mapping that `SilverSQLTool.query_parquet_by_metadata` and + `QdrantRetriever.retrieve_async` already consume. + + Silently skips keys that fail to deserialise so a partially-broken + audit payload never crashes a rescue call — the caller can still fall + back to its own anchor math for the missing sources. + """ + out: Dict[SourceTimeKey, TimePredicate] = {} + if not isinstance(serialised, dict): + return out + for k, v in serialised.items(): + if not isinstance(v, dict): + continue + try: + key = SourceTimeKey(k) + except ValueError: + logger.debug(f"predicates_from_serialised: unknown source_key '{k}' — skipped.") + continue + try: + out[key] = TimePredicate.from_dict(v) + except Exception as e: + logger.warning( + f"predicates_from_serialised: failed to rehydrate {k}: " + f"{type(e).__name__}: {e} — skipped." + ) + return out + + +def union_epoch_range(predicates: List[TimePredicate]) -> Tuple[int, int]: + """Return the `(min_start, max_end)` epoch-second bounds over predicates. + + Used by the Gold retriever to build ONE numeric Range on + `unified_timestamp` / `publish_timestamp` that covers every selected + Gold source (news/sec/gpr). Each source's own widening is preserved: + a mixed {news, gpr} query still has a window large enough for GPR. + + Returns `(0, 0)` on empty input so callers can skip the filter. + """ + if not predicates: + return (0, 0) + start = min(p.start_epoch_s for p in predicates) + end = max(p.end_epoch_s for p in predicates) + return start, end diff --git a/Scripts/tests/router_e2e_queries.json b/Scripts/tests/router_e2e_queries.json new file mode 100644 index 0000000..85365d8 --- /dev/null +++ b/Scripts/tests/router_e2e_queries.json @@ -0,0 +1,42 @@ +{ + "schema_version": "1.0", + "description": "End-to-end router test catalogue. Each case is designed to exercise a distinct slice of the retrieval matrix (Silver options vs Silver macro vs Gold news vs Gold SEC) and a distinct time window. Consumed by Scripts/tests/test_router_e2e.py — do NOT rely on ordering, the harness keys on `name`.", + "last_reviewed": "2026-04-22", + "cases": [ + { + "name": "SEC Gold - Insider Flow Driven", + "query": "Given the recent AAPL Form-4 executive selling activity over the past month, how should I position with options if I still expect short-term momentum?", + "expected_sources": ["sec", "options"], + "expected_time_window": "past_month", + "notes": "Targets SEC Form-4 Qdrant path (action_direction=SELL filter) combined with current options chain. Tests the Critic's insider-vs-IV contradiction backstop when IV happens to be elevated." + }, + { + "name": "News Gold + Commodity ETF - Geopolitics", + "query": "How are escalating Middle East tensions and geopolitical-risk news from the past week moving gold, and what GLD options exposure would you consider?", + "expected_sources": ["news", "options", "macro_history"], + "expected_time_window": "past_week", + "notes": "Targets news topic `macro_geopolitics_risk` + `asset_precious_metals_spot`, plus GPR index from macro, plus GLD options chain. Should route through HyDE expansion and surface GLD via impacted_assets." + }, + { + "name": "Macro Regime - FOMC & Yields", + "query": "How did the most recent FOMC decision and 10-year Treasury yields move over the past week, and what does that imply for SPY 30-DTE put protection?", + "expected_sources": ["news", "macro_history", "options"], + "expected_time_window": "past_week", + "notes": "Targets news topic `macro_central_banks` + macro parquet (^TNX, VIX) + SPY options chain. Tests that MasterRetriever widens news time window for weekly-cadence Gold sources while keeping options Silver on a daily anchor." + }, + { + "name": "Cross-Asset Regime - IV vs VIX Divergence", + "query": "Compare QQQ's current ATM implied volatility against VIX over the past month. Is there a divergence, and if so what index-level hedge would you suggest?", + "expected_sources": ["options", "macro_history"], + "expected_time_window": "past_month", + "notes": "Exercises macro + options cross-join. QQQ has options Silver, VIX is macro Silver; no news/SEC expected. Tests IV-regime pinning in AnalystState across revisions." + }, + { + "name": "Options Silver - Single Name Liquidity", + "query": "What is AAPL's today Put/Call Ratio, IV Skew, and which 30-DTE strikes are most liquid today? Based on this, would you recommend selling near-the-money strangles?", + "expected_sources": ["options"], + "expected_time_window": "today", + "notes": "Exercises Silver options dispatcher for PCR + IV Skew + liquidity scan on a fully-covered Nasdaq-100 single-name. Route should resolve to hybrid_both (PCR primary)." + } + ] +} diff --git a/Scripts/tests/test_master_retriever.py b/Scripts/tests/test_master_retriever.py new file mode 100644 index 0000000..2ba64bc --- /dev/null +++ b/Scripts/tests/test_master_retriever.py @@ -0,0 +1,126 @@ +""" +test_master_retriever.py + +Financial RAG architecture - end-to-end test for the MasterRetriever facade. +Scope: multi-scenario concurrent retrieval tests, failure isolation checks, +and daily-rotating audit log output. +""" + +import asyncio +import logging +import sys +from datetime import datetime +from pathlib import Path + +# Dynamic bootstrap: walk up three levels to resolve project root. +project_root = Path(__file__).parent.parent.parent.resolve() +sys.path.append(str(project_root)) + +# Import retrieval components via package exports. +from Scripts.retrieval import QueryTransformer, MasterRetriever, QueryIntent + +# ========================================== +# 1. Production-style test logging setup +# ========================================== +def setup_test_logger(): + """Configure daily partitioned test logs at logs/test/YYYY-MM-DD/.""" + today = datetime.now().strftime("%Y-%m-%d") + log_dir = project_root / "logs" / "test" / today + log_dir.mkdir(parents=True, exist_ok=True) + + timestamp = datetime.now().strftime("%H%M%S") + log_file = log_dir / f"master_retriever_test_{timestamp}.log" + + logger = logging.getLogger("TestAudit") + logger.setLevel(logging.DEBUG) + + # Avoid duplicate handler registration. + if not logger.handlers: + # 1) File sink. + fh = logging.FileHandler(log_file, encoding='utf-8') + fh.setLevel(logging.DEBUG) + + # 2) Console sink. + ch = logging.StreamHandler(sys.stdout) + ch.setLevel(logging.INFO) + + formatter = logging.Formatter('%(asctime)s | %(levelname)s | %(message)s') + fh.setFormatter(formatter) + ch.setFormatter(formatter) + + logger.addHandler(fh) + logger.addHandler(ch) + + return logger, log_file + +# ========================================== +# 2. Concurrent retrieval E2E orchestration +# ========================================== +async def run_tests(): + logger, log_path = setup_test_logger() + logger.info("==================================================") + logger.info("🚀 Starting MasterRetriever E2E test") + logger.info(f"📁 Audit log file: {log_path}") + logger.info("==================================================") + + try: + # API surface check: verify package exports resolve correctly. + _ = QueryTransformer + _ = QueryIntent + + logger.info("⏳ Initializing MasterRetriever...") + master_retriever = MasterRetriever() + master_retriever.gold_timeout = 6.0 + master_retriever.silver_timeout = 10.0 + logger.info("✅ System components initialized.\n") + except Exception as e: + logger.error(f"❌ Startup failed, please check environment: {e}", exc_info=True) + return + + # Three representative financial queries. + test_queries = [ + # Query 1: Quant-heavy options case (primarily stresses Silver). + "What is the current IV Skew and Put/Call Ratio for AAPL?", + + # Query 2: Qualitative macro/geopolitical case (stresses Gold and cross-modal retrieval). + "How did the recent spike in Geopolitical Risk (GPR) index affect SPY's macro trend?", + + # Query 3: Hybrid complex case (tests SEC filtering and liquidity assessment). + "Did AAPL executives' Form 4 insider selling last week negatively impact the options market liquidity?" + ] + + for idx, query in enumerate(test_queries, 1): + logger.info(f"▶️ [TEST {idx}/3] Query: '{query}'") + + try: + # Step 1: Trigger black-box retrieval through MasterRetriever. + # Intent routing and transformation are handled internally by retrieve(). + logger.info(" [1] Triggering MasterRetriever (Gold & Silver concurrency)...") + results = await master_retriever.retrieve(user_query=query) + + # Step 2: Result assertion and reporting. + gold_count = len(results["gold_context"]) + silver_keys = list(results["silver_context"].get("values", {}).keys()) + + logger.info(" [2] Retrieval result summary:") + logger.info(f" - 🥇 Gold (Qdrant): Retrieved {gold_count} text chunks.") + logger.info(f" - 🥈 Silver (SQL): Computed {len(silver_keys)} metrics: {silver_keys}") + + # Print lineage anchors if present. + anchors = results["silver_context"].get("lineage_anchors", []) + if anchors: + logger.info(f" - 🔗 Data lineage: captured {len(anchors)} underlying anchors.") + + except Exception as e: + logger.error(f"❌ Query execution failed: {str(e)}", exc_info=True) + + logger.info("-" * 60 + "\n") + + logger.info("🎉 All tests completed.") + +if __name__ == "__main__": + # Windows-specific asyncio policy optimization. + if sys.platform == "win32": + asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) + + asyncio.run(run_tests()) \ No newline at end of file diff --git a/Scripts/tests/test_router_e2e.py b/Scripts/tests/test_router_e2e.py new file mode 100644 index 0000000..36f98c3 --- /dev/null +++ b/Scripts/tests/test_router_e2e.py @@ -0,0 +1,670 @@ +""" +Output tree (one run): + + logs/router_e2e/ + 2026-04-21/ + 20260421_103015_console.log + 20260421_103015_run_summary.json + 20260421_103015_01_happy_path_trace.jsonl + 20260421_103015_01_happy_path_final_state.json + 20260421_103015_01_happy_path_summary.json + 20260421_103015_02_critic_trap_trace.jsonl + ... +""" + +from __future__ import annotations + +import asyncio +import json +import logging +import os +import re +import sys +import time +import traceback +from datetime import date, datetime +from pathlib import Path +from typing import Any, Dict, List, Optional + +# ----------------------------------------------------------------------------- +# Path bootstrap — this lets the test run standalone (python -m, pytest, or +# `python Scripts/tests/test_router_e2e.py`) without external PYTHONPATH. +# ----------------------------------------------------------------------------- +PROJECT_ROOT = Path(__file__).resolve().parents[2] +if str(PROJECT_ROOT) not in sys.path: + sys.path.insert(0, str(PROJECT_ROOT)) + +from pydantic import BaseModel # noqa: E402 + +from Scripts.agents.router import build_financial_rag_graph # noqa: E402 +from Scripts.agents.state import AgentFeedback # noqa: E402 + + +# ============================================================================= +# 0. Constants & log paths +# ============================================================================= + +_VALID_VERDICTS = {"pass", "fatal", "minor", None} +_VALID_SEVERITIES = {"Fatal", "Minor"} +_REQUIRED_TIMERANGE_KEYS = { + "time_window_label", "window_days", "anchor_date", + "start_date", "end_date", "is_default_window_applied", +} +_REQUIRED_HYDE_KEYS = {"paragraph", "novel_tickers", "whitelisted_tickers"} +_REQUIRED_FINAL_KEYS = {"status", "final_report", "evidence_links", "confidence_score"} +_MIN_DRAFT_LEN = 120 # below this the draft is suspicious + +# Larger than the worst-case path (retrieval + analyst×3 + checker×3 + critic×3 +# + finalizer ≈ 11) so the circuit-breaker fires before the recursion limit. +_RECURSION_LIMIT = 20 + +_DATE_STR = datetime.now().strftime("%Y-%m-%d") +_RUN_TS = datetime.now().strftime("%Y%m%d_%H%M%S") + +LOG_ROOT = PROJECT_ROOT / "logs" / "router_e2e" / _DATE_STR +LOG_ROOT.mkdir(parents=True, exist_ok=True) + + +# ============================================================================= +# 1. Logging — dual sink (console + file) attached to the root logger so every +# agent / retriever INFO line shows up in the audit artefact. +# ============================================================================= + +def _configure_logging() -> Path: + console_log_path = LOG_ROOT / f"{_RUN_TS}_console.log" + fmt = "%(asctime)s | %(levelname)s | %(name)s | %(message)s" + + root = logging.getLogger() + root.setLevel(logging.INFO) + + # Remove any pre-existing handlers (pytest reruns / REPL), then attach ours. + for h in list(root.handlers): + root.removeHandler(h) + + stream_handler = logging.StreamHandler() + stream_handler.setFormatter(logging.Formatter(fmt)) + root.addHandler(stream_handler) + + file_handler = logging.FileHandler(console_log_path, encoding="utf-8") + file_handler.setFormatter(logging.Formatter(fmt)) + root.addHandler(file_handler) + + # Silence over-noisy HTTP stack; we only care about agent/retriever signal. + for noisy in ("httpx", "httpcore", "urllib3"): + logging.getLogger(noisy).setLevel(logging.WARNING) + + return console_log_path + + +logger = logging.getLogger("RouterE2E") + + +# ============================================================================= +# 2. Serialisation helpers (Pydantic-safe) +# ============================================================================= + +def _to_jsonable(obj: Any, max_str: int = 2000) -> Any: + """Recursively convert Pydantic models / dates / sets into JSON-safe data. + + max_str truncates individual string fields to keep trace files readable — + draft_report can be multi-KB and we only need a fingerprint in the trace. + """ + if obj is None or isinstance(obj, (bool, int, float)): + return obj + if isinstance(obj, str): + return obj if len(obj) <= max_str else obj[:max_str] + f"...(+{len(obj) - max_str} chars)" + if isinstance(obj, (datetime, date)): + return obj.isoformat() + if isinstance(obj, BaseModel): + return _to_jsonable(obj.model_dump(), max_str) + if isinstance(obj, dict): + return {str(k): _to_jsonable(v, max_str) for k, v in obj.items()} + if isinstance(obj, (list, tuple, set)): + return [_to_jsonable(x, max_str) for x in obj] + # Fallback: best-effort repr — never raise. + try: + return str(obj)[:max_str] + except Exception: + return f"" + + +def _slugify(text: str, max_len: int = 40) -> str: + """Filesystem-safe slug for the test case name.""" + s = re.sub(r"[^a-zA-Z0-9_-]+", "_", text.strip().lower()) + s = re.sub(r"_+", "_", s).strip("_") + return s[:max_len] or "unnamed" + + +# ============================================================================= +# 3. Per-node audit functions +# ----------------------------------------------------------------------------- +# Each function receives the delta for the node (what LangGraph merged into +# state from THAT node's return) and the cumulative merged state assembled by +# the harness. It returns: +# (audit_dict, assertion_failures) +# where assertion_failures is a list[str] — empty == clean node. +# ============================================================================= + +def _audit_retrieval_master(delta: Dict[str, Any], merged: Dict[str, Any]): + audit: Dict[str, Any] = {} + fails: List[str] = [] + + meta = delta.get("metadata") + tr = delta.get("time_range") or {} + he = delta.get("hyde_anticipation") or {} + silver = delta.get("silver_context") or {} + gold = delta.get("gold_context") or [] + macro = delta.get("macro_context") or "" + + audit["metadata_present"] = meta is not None + audit["gold_chunks"] = len(gold) + audit["silver_values_n"] = len(silver.get("values", {}) or {}) + audit["silver_source_channel"] = silver.get("source_channel") + audit["silver_has_compensation"] = "compensation" in silver + audit["time_range_keys"] = sorted(tr.keys()) + audit["time_range_label"] = tr.get("time_window_label") + audit["time_range_days"] = tr.get("window_days") + audit["time_range_start"] = tr.get("start_date") + audit["time_range_end"] = tr.get("end_date") + audit["default_window_applied"] = tr.get("is_default_window_applied") + audit["hyde_paragraph_len"] = len(he.get("paragraph", "")) if isinstance(he, dict) else 0 + audit["hyde_whitelisted"] = he.get("whitelisted_tickers") if isinstance(he, dict) else None + audit["hyde_novel_tickers"] = he.get("novel_tickers") if isinstance(he, dict) else None + audit["hyde_source_channel"] = he.get("source_channel") if isinstance(he, dict) else None + audit["macro_context_bytes"] = len(macro) + audit["is_fallback"] = bool(delta.get("is_fallback", False)) + audit["revision_count_reset_to_zero"] = delta.get("revision_count") == 0 + + if meta is None: + fails.append("retrieval_master: metadata is None (transformer failed)") + missing_tr = _REQUIRED_TIMERANGE_KEYS - set(tr.keys()) + if missing_tr: + fails.append(f"retrieval_master: time_range missing keys {sorted(missing_tr)}") + if not isinstance(he, dict): + fails.append("retrieval_master: hyde_anticipation is not a dict") + else: + missing_he = _REQUIRED_HYDE_KEYS - set(he.keys()) + if missing_he: + fails.append(f"retrieval_master: hyde_anticipation missing keys {sorted(missing_he)}") + if silver.get("source_channel") not in ("primary", "hyde_expansion", None): + fails.append(f"retrieval_master: unexpected silver source_channel={silver.get('source_channel')}") + if delta.get("revision_count") != 0: + fails.append("retrieval_master: revision_count not initialised to 0") + if delta.get("checker_verdict") is not None: + fails.append("retrieval_master: checker_verdict should be None at graph entry") + if delta.get("critic_verdict") is not None: + fails.append("retrieval_master: critic_verdict should be None at graph entry") + + return audit, fails + + +def _audit_analyst(delta: Dict[str, Any], merged: Dict[str, Any]): + audit: Dict[str, Any] = {} + fails: List[str] = [] + + draft = delta.get("draft_report") or "" + rev = delta.get("revision_count") + + audit["draft_len"] = len(draft) + audit["draft_preview"] = draft[:240] + audit["revision_count_after"] = rev + audit["checker_verdict_reset"] = delta.get("checker_verdict") is None + audit["critic_verdict_reset"] = delta.get("critic_verdict") is None + + if not isinstance(rev, int) or rev < 1: + fails.append(f"analyst: revision_count must be >=1, got {rev!r}") + if len(draft) < _MIN_DRAFT_LEN: + fails.append(f"analyst: draft too short ({len(draft)} chars < {_MIN_DRAFT_LEN})") + if delta.get("checker_verdict") is not None: + fails.append("analyst: must reset checker_verdict to None for the new revision") + if delta.get("critic_verdict") is not None: + fails.append("analyst: must reset critic_verdict to None for the new revision") + + return audit, fails + + +def _audit_checker(delta: Dict[str, Any], merged: Dict[str, Any]): + audit: Dict[str, Any] = {} + fails: List[str] = [] + + verdict = delta.get("checker_verdict") + new_fb = delta.get("critic_feedback", []) or [] + + audit["checker_verdict"] = verdict + audit["new_feedback_items"] = len(new_fb) + audit["silver_context_refreshed"] = "silver_context" in delta + + senders: List[str] = [] + severities: List[str] = [] + rev_indices: List[Any] = [] + for f in new_fb: + if isinstance(f, BaseModel): + d = f.model_dump() + elif isinstance(f, dict): + d = f + else: + fails.append(f"checker: feedback item of unexpected type {type(f).__name__}") + continue + senders.append(d.get("sender")) + severities.append(d.get("error_type")) + rev_indices.append(d.get("revision_index")) + + audit["feedback_senders"] = senders + audit["feedback_severities"] = severities + audit["feedback_revision_indices"] = rev_indices + + if verdict not in _VALID_VERDICTS: + fails.append(f"checker: verdict={verdict!r} not in {_VALID_VERDICTS}") + for sv in severities: + if sv not in _VALID_SEVERITIES: + fails.append(f"checker: feedback severity {sv!r} not in {_VALID_SEVERITIES}") + # Every feedback this node emitted should be stamped by the Checker. + if any(s != "Checker" for s in senders): + fails.append(f"checker: found non-Checker senders in its delta: {senders}") + cur_rev = merged.get("revision_count", 0) + if any(ri is None for ri in rev_indices): + fails.append("checker: at least one feedback item has revision_index=None") + elif any(ri != cur_rev for ri in rev_indices): + fails.append( + f"checker: feedback revision_index {rev_indices} does not match current revision {cur_rev}" + ) + # Sanity: if verdict=="fatal" there MUST be at least one Fatal feedback to + # justify the routing decision. + if verdict == "fatal" and not any(s == "Fatal" for s in severities): + # Fatal verdict without any Fatal entry → router will re-run analyst + # on empty ammo. Architectural smell. + fails.append("checker: verdict=fatal but no Fatal severity in the delta feedback") + + return audit, fails + + +def _audit_critic(delta: Dict[str, Any], merged: Dict[str, Any]): + audit: Dict[str, Any] = {} + fails: List[str] = [] + + verdict = delta.get("critic_verdict") + new_fb = delta.get("critic_feedback", []) or [] + + audit["critic_verdict"] = verdict + audit["new_feedback_items"] = len(new_fb) + + senders: List[str] = [] + severities: List[str] = [] + rev_indices: List[Any] = [] + for f in new_fb: + if isinstance(f, BaseModel): + d = f.model_dump() + elif isinstance(f, dict): + d = f + else: + fails.append(f"critic: feedback item of unexpected type {type(f).__name__}") + continue + senders.append(d.get("sender")) + severities.append(d.get("error_type")) + rev_indices.append(d.get("revision_index")) + + audit["feedback_senders"] = senders + audit["feedback_severities"] = severities + audit["feedback_revision_indices"] = rev_indices + + if verdict not in _VALID_VERDICTS: + fails.append(f"critic: verdict={verdict!r} not in {_VALID_VERDICTS}") + for sv in severities: + if sv not in _VALID_SEVERITIES: + fails.append(f"critic: feedback severity {sv!r} not in {_VALID_SEVERITIES}") + if any(s != "Critic" for s in senders): + fails.append(f"critic: found non-Critic senders in its delta: {senders}") + cur_rev = merged.get("revision_count", 0) + if any(ri is None for ri in rev_indices): + fails.append("critic: at least one feedback item has revision_index=None") + elif any(ri != cur_rev for ri in rev_indices): + fails.append( + f"critic: feedback revision_index {rev_indices} does not match current revision {cur_rev}" + ) + if verdict == "fatal" and not any(s == "Fatal" for s in severities): + fails.append("critic: verdict=fatal but no Fatal severity in the delta feedback") + + return audit, fails + + +def _audit_finalizer(delta: Dict[str, Any], merged: Dict[str, Any]): + audit: Dict[str, Any] = {} + fails: List[str] = [] + + final = delta.get("final_strategy") or {} + audit["final_status"] = final.get("status") + audit["confidence_score"] = final.get("confidence_score") + audit["evidence_links_n"] = len(final.get("evidence_links", []) or []) + audit["has_markdown"] = bool(final.get("markdown")) + audit["final_report_keys"] = sorted((final.get("final_report") or {}).keys()) + + missing = _REQUIRED_FINAL_KEYS - set(final.keys()) + if missing: + fails.append(f"finalizer: final_strategy missing keys {sorted(missing)}") + if final.get("status") not in ("complete", "degraded"): + fails.append(f"finalizer: status={final.get('status')!r} not in {{complete, degraded}}") + cs = final.get("confidence_score") + if not isinstance(cs, (int, float)) or not (0.0 <= float(cs) <= 1.0): + fails.append(f"finalizer: confidence_score={cs!r} out of [0,1]") + return audit, fails + + +NODE_AUDITORS = { + "retrieval_master": _audit_retrieval_master, + "analyst": _audit_analyst, + "checker": _audit_checker, + "critic": _audit_critic, + "finalizer": _audit_finalizer, +} + + +# ============================================================================= +# 4. Merged-state accumulator +# ----------------------------------------------------------------------------- +# LangGraph's stream_mode="updates" yields ONLY the per-node delta. To validate +# assertions that need whole-state context (e.g. revision_count at the moment +# Checker writes its verdict) we maintain our own merged view, honouring the +# AgentState `operator.add` semantics for `critic_feedback`. +# ============================================================================= + +def _merge_delta(merged: Dict[str, Any], delta: Dict[str, Any]) -> None: + for k, v in delta.items(): + if k == "critic_feedback": + prior = merged.get("critic_feedback") or [] + merged["critic_feedback"] = list(prior) + list(v or []) + else: + merged[k] = v + + +# ============================================================================= +# 5. Single-test runner +# ============================================================================= + +async def run_single_test( + graph, + test_idx: int, + test_name: str, + query: str, + case_meta: Optional[Dict[str, Any]] = None, +) -> Dict[str, Any]: + """Execute ONE LangGraph query; write trace/final_state/summary artefacts. + + Returns a compact summary dict that the caller aggregates into the run-level + summary. Exceptions are captured, not re-raised, so a broken test case + cannot abort the rest of the suite. + """ + slug = f"{test_idx:02d}_{_slugify(test_name)}" + trace_path = LOG_ROOT / f"{_RUN_TS}_{slug}_trace.jsonl" + final_state_path = LOG_ROOT / f"{_RUN_TS}_{slug}_final_state.json" + summary_path = LOG_ROOT / f"{_RUN_TS}_{slug}_summary.json" + + banner = f"{'=' * 80}\n🚀 [TEST {test_idx}] {test_name}\n❓ Query: {query}\n{'=' * 80}" + logger.info("\n" + banner) + + t_start = time.time() + merged_state: Dict[str, Any] = {"original_query": query} + node_executions: List[Dict[str, Any]] = [] + step = 0 + total_failures: List[str] = [] + + try: + with open(trace_path, "w", encoding="utf-8") as trace_fp: + # Header line — makes the JSONL self-describing for later replay. + trace_fp.write(json.dumps({ + "_meta": { + "test_idx": test_idx, + "test_name": test_name, + "query": query, + "run_ts": _RUN_TS, + "recursion_limit": _RECURSION_LIMIT, + "started_at": datetime.now().isoformat(), + # Catalogue metadata (expected_sources, expected_time_window, + # notes, …) is propagated verbatim so post-mortem tooling + # can diff actual vs. expected without re-reading the JSON. + "case_meta": case_meta or {}, + }, + }, ensure_ascii=False) + "\n") + trace_fp.flush() + + initial_state = {"original_query": query} + async for output in graph.astream( + initial_state, + config={"recursion_limit": _RECURSION_LIMIT}, + stream_mode="updates", + ): + for node_name, state_update in output.items(): + step += 1 + _merge_delta(merged_state, state_update) + + auditor = NODE_AUDITORS.get(node_name) + if auditor: + audit, fails = auditor(state_update, merged_state) + else: + audit, fails = {"note": "no auditor registered"}, [] + + total_failures.extend(f"[step {step}][{node_name}] {m}" for m in fails) + + # Per-node console line — bounded, no PII leak. + verdict_str = "" + if node_name == "checker": + verdict_str = f" | verdict={audit.get('checker_verdict')}" + elif node_name == "critic": + verdict_str = f" | verdict={audit.get('critic_verdict')}" + elif node_name == "finalizer": + verdict_str = f" | status={audit.get('final_status')}" + elif node_name == "analyst": + verdict_str = f" | rev={audit.get('revision_count_after')}" + elif node_name == "retrieval_master": + verdict_str = ( + f" | gold={audit.get('gold_chunks')}" + f" silver_vals={audit.get('silver_values_n')}" + f" tr={audit.get('time_range_start')}→{audit.get('time_range_end')}" + ) + fail_tag = f" ⚠️ FAILS={len(fails)}" if fails else "" + logger.info( + f"🟢 [Step {step:02d}] Node={node_name.upper()}{verdict_str}{fail_tag}" + ) + if fails: + for m in fails: + logger.warning(f" ↳ {m}") + + record = { + "step": step, + "timestamp": datetime.now().isoformat(), + "elapsed_s": round(time.time() - t_start, 3), + "node": node_name, + "delta_keys": sorted(state_update.keys()), + "audit": _to_jsonable(audit), + "assertion_failures": fails, + "delta_preview": _to_jsonable(state_update), + } + node_executions.append(record) + trace_fp.write(json.dumps(record, ensure_ascii=False) + "\n") + trace_fp.flush() + + elapsed = round(time.time() - t_start, 3) + final_state_json = _to_jsonable(merged_state) + + with open(final_state_path, "w", encoding="utf-8") as fp: + json.dump(final_state_json, fp, ensure_ascii=False, indent=2) + + final_strategy = merged_state.get("final_strategy") or {} + summary = { + "test_idx": test_idx, + "test_name": test_name, + "query": query, + "outcome": "ok", + "steps": step, + "elapsed_s": elapsed, + "revision_count": merged_state.get("revision_count"), + "is_fallback": merged_state.get("is_fallback"), + "final_status": final_strategy.get("status"), + "confidence_score": final_strategy.get("confidence_score"), + "final_report_produced": bool(final_strategy.get("final_report")), + "evidence_links_n": len(final_strategy.get("evidence_links", []) or []), + "total_feedback": len(merged_state.get("critic_feedback", []) or []), + "nodes_executed": [r["node"] for r in node_executions], + "assertion_failures_total": len(total_failures), + "assertion_failures": total_failures, + "artefacts": { + "trace": str(trace_path), + "final_state": str(final_state_path), + }, + } + with open(summary_path, "w", encoding="utf-8") as fp: + json.dump(summary, fp, ensure_ascii=False, indent=2) + + verdict_icon = "✅" if not total_failures and final_strategy.get("final_report") else ( + "⚠️" if final_strategy.get("final_report") else "❌" + ) + logger.info( + f"{verdict_icon} [TEST {test_idx}] Done in {elapsed}s | rev={summary['revision_count']} " + f"| final_status={summary['final_status']} | assertion_fails={len(total_failures)} | " + f"artefacts={summary_path.name}" + ) + return summary + + except Exception as e: + elapsed = round(time.time() - t_start, 3) + tb = traceback.format_exc() + logger.error(f"❌ [TEST {test_idx}] CRASHED after {elapsed}s: {type(e).__name__}: {e}") + crash_summary = { + "test_idx": test_idx, + "test_name": test_name, + "query": query, + "outcome": "crashed", + "steps": step, + "elapsed_s": elapsed, + "error_type": type(e).__name__, + "error_msg": str(e), + "traceback": tb, + "nodes_executed_before_crash": [r["node"] for r in node_executions], + "assertion_failures_before_crash": total_failures, + } + with open(summary_path, "w", encoding="utf-8") as fp: + json.dump(crash_summary, fp, ensure_ascii=False, indent=2) + return crash_summary + + +# ============================================================================= +# 6. Test catalogue & main +# ============================================================================= + +# Default path for the externalised catalogue. Overridable via the +# ROUTER_E2E_QUERIES env var for CI / ad-hoc runs without editing source. +_DEFAULT_QUERY_CATALOGUE = PROJECT_ROOT / "Scripts" / "tests" / "router_e2e_queries.json" + +# Inline fallback — mirrors the externalised file so the harness still +# runs if the JSON is missing or corrupt. Keep this list short; the +# JSON file is the source of truth for day-to-day edits. +_FALLBACK_TEST_CASES: List[Dict[str, str]] = [ + { + "name": "Happy Path - Quant Query", + "query": "What is the current Put/Call Ratio and IV Skew for AAPL?", + }, + { + "name": "Minimal Time Default - Six Months Fallback", + "query": "Show me the options sentiment for SPY.", + }, +] + + +def _load_test_cases(path: Optional[Path] = None) -> List[Dict[str, str]]: + """Load the query catalogue from JSON (source of truth) with a silent + fallback to the inline list. + + Contract expected of the JSON: + {"cases": [{"name": str, "query": str, ...}, ...]} + + Extra metadata (``expected_sources``, ``expected_time_window``, + ``notes``) is passed through untouched so future assertions can key + on it without schema changes here. + """ + path = path or Path(os.environ.get("ROUTER_E2E_QUERIES", _DEFAULT_QUERY_CATALOGUE)) + try: + with open(path, "r", encoding="utf-8") as fp: + payload = json.load(fp) + cases = payload.get("cases") or [] + # Minimal sanity-check — each case must carry at least a name + query. + cleaned = [ + c for c in cases + if isinstance(c, dict) and c.get("name") and c.get("query") + ] + if not cleaned: + logger.warning( + "Catalogue %s parsed but contained no valid cases — " + "falling back to inline defaults.", path, + ) + return _FALLBACK_TEST_CASES + logger.info("📂 Loaded %d query cases from %s", len(cleaned), path) + return cleaned + except FileNotFoundError: + logger.warning("Catalogue %s not found — using inline fallback.", path) + return _FALLBACK_TEST_CASES + except (json.JSONDecodeError, OSError) as exc: + logger.error( + "Catalogue %s is unreadable (%s) — using inline fallback.", + path, exc, + ) + return _FALLBACK_TEST_CASES + + +TEST_CASES: List[Dict[str, str]] = _load_test_cases() + + +async def main(): + console_log = _configure_logging() + logger.info(f"📝 Run log directory: {LOG_ROOT}") + logger.info(f"📝 Console mirror: {console_log}") + logger.info(f"📝 Run timestamp: {_RUN_TS}") + logger.info( + "📂 Query catalogue: %s (%d cases)", + os.environ.get("ROUTER_E2E_QUERIES", str(_DEFAULT_QUERY_CATALOGUE)), + len(TEST_CASES), + ) + + # Build the graph ONCE — singleton agents are already cached inside router. + graph = build_financial_rag_graph() + + run_summaries: List[Dict[str, Any]] = [] + for i, tc in enumerate(TEST_CASES, start=1): + # Strip the two mandatory keys so `case_meta` only carries extras + # (expected_sources, expected_time_window, notes, …) — keeps the + # JSONL trace clean and the diff against the catalogue obvious. + extras = {k: v for k, v in tc.items() if k not in ("name", "query")} + s = await run_single_test( + graph=graph, + test_idx=i, + test_name=tc["name"], + query=tc["query"], + case_meta=extras, + ) + run_summaries.append(s) + + aggregate = { + "run_ts": _RUN_TS, + "date": _DATE_STR, + "n_tests": len(run_summaries), + "n_ok": sum(1 for s in run_summaries if s.get("outcome") == "ok"), + "n_crashed": sum(1 for s in run_summaries if s.get("outcome") == "crashed"), + "n_with_assertion_failures": sum( + 1 for s in run_summaries if s.get("assertion_failures_total", 0) > 0 + ), + "tests": run_summaries, + "log_root": str(LOG_ROOT), + } + aggregate_path = LOG_ROOT / f"{_RUN_TS}_run_summary.json" + with open(aggregate_path, "w", encoding="utf-8") as fp: + json.dump(_to_jsonable(aggregate), fp, ensure_ascii=False, indent=2) + + logger.info("=" * 80) + logger.info( + f"🏁 RUN COMPLETE | ok={aggregate['n_ok']} | crashed={aggregate['n_crashed']} " + f"| with_assertion_failures={aggregate['n_with_assertion_failures']} | " + f"aggregate={aggregate_path.name}" + ) + logger.info("=" * 80) + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/Scripts/tools/SEC_Accession_No_depulicated.py b/Scripts/tools/SEC_Accession_No_depulicated.py new file mode 100644 index 0000000..b90d7e4 --- /dev/null +++ b/Scripts/tools/SEC_Accession_No_depulicated.py @@ -0,0 +1,184 @@ +import json +import logging +from pathlib import Path + +# --- Path resolution: repo root is two levels above Scripts/tools/ --- +PROJECT_ROOT = Path(__file__).resolve().parents[2] + +BRONZE_SEC_JSONL_ROOT = ( + PROJECT_ROOT / "Data" / "1_Bronze_Raw" / "SEC_Parsed_JSON" +) +# Canonical location migrated 2026-04-22: +# config/SEC_Processing/global_processed_registry.json (retired) +# -> config/runtime/sec_processed_registry.json (current) +GLOBAL_PROCESSED_REGISTRY = ( + PROJECT_ROOT / "config" / "runtime" / "sec_processed_registry.json" +) + +TARGET_DATE = "2026-04-08" + +logger = logging.getLogger("DedupeBot") + + +def _log_dir_for_run(target_date: str) -> Path: + """Run audit trail: logs/{YYYY-MM-DD}/ (date-aligned with other daily artifacts).""" + return PROJECT_ROOT / "logs" / target_date + + +def _configure_logging(target_date: str) -> None: + log_dir = _log_dir_for_run(target_date) + log_dir.mkdir(parents=True, exist_ok=True) + log_file = log_dir / f"SEC_bronze_accession_dedupe_{target_date}.log" + + logger.setLevel(logging.INFO) + fmt = logging.Formatter("%(asctime)s [%(levelname)s] %(message)s") + + logger.handlers.clear() + fh = logging.FileHandler(log_file, encoding="utf-8") + fh.setFormatter(fmt) + logger.addHandler(fh) + sh = logging.StreamHandler() + sh.setFormatter(fmt) + logger.addHandler(sh) + logger.propagate = False + + +def _truncate_list(items, limit: int = 80): + if len(items) <= limit: + return list(items), 0 + return list(items[:limit]), len(items) - limit + + +def _load_global_processed_registry(): + if not GLOBAL_PROCESSED_REGISTRY.is_file(): + logger.warning( + f"⚠️ Registry not found: {GLOBAL_PROCESSED_REGISTRY} — " + "treating as empty (only within-file dedupe will apply)." + ) + return set() + with open(GLOBAL_PROCESSED_REGISTRY, "r", encoding="utf-8") as f: + data = json.load(f) + if not isinstance(data, list): + logger.error("❌ global_processed_registry.json must be a JSON array of strings.") + return set() + return set(str(x) for x in data) + + +def _is_ticker_jsonl(path: Path) -> bool: + """Bronze layout: {TICKER}.jsonl (no patched_ prefix, no date suffix).""" + name = path.name + if not name.endswith(".jsonl"): + return False + if name.startswith("patched_") or name.startswith("_"): + return False + if "SUMMARY" in name.upper(): + return False + return True + + +def deduplicate_all_files() -> None: + _configure_logging(TARGET_DATE) + + data_dir = BRONZE_SEC_JSONL_ROOT / TARGET_DATE + if not data_dir.is_dir(): + logger.error(f"❌ Data directory not found: {data_dir}") + return + + global_processed = _load_global_processed_registry() + + candidates = sorted(p for p in data_dir.iterdir() if p.is_file() and _is_ticker_jsonl(p)) + + logger.info( + "=== SEC Bronze accession deduplication run ===\n" + f"target_date: {TARGET_DATE}\n" + f"bronze_dir: {data_dir}\n" + f"registry_file: {GLOBAL_PROCESSED_REGISTRY}\n" + f"registry_accession_count: {len(global_processed)}\n" + f"candidate_jsonl_files: {len(candidates)}" + ) + + if not candidates: + logger.warning( + f"⚠️ No per-ticker *.jsonl files under {data_dir} " + "(expected names like AAPL.jsonl)." + ) + return + + for file_path in candidates: + filename = file_path.name + seen_accessions = set() + records_to_save = [] + + input_lines = 0 + dropped_missing_accession = 0 + dropped_in_registry: list[str] = [] + dropped_duplicate_in_file: list[str] = [] + + logger.info(f"--- Processing: {filename} (in-place rewrite) ---") + + try: + with open(file_path, "r", encoding="utf-8") as f: + for line in f: + if not line.strip(): + continue + input_lines += 1 + record = json.loads(line) + + acc_no = record.get("metadata", {}).get("accession_no") + if not acc_no: + dropped_missing_accession += 1 + continue + if acc_no in global_processed: + dropped_in_registry.append(acc_no) + continue + if acc_no in seen_accessions: + dropped_duplicate_in_file.append(acc_no) + continue + + seen_accessions.add(acc_no) + records_to_save.append(record) + + output_lines = len(records_to_save) + removed_total = input_lines - output_lines + + with open(file_path, "w", encoding="utf-8") as f_out: + for rec in records_to_save: + f_out.write(json.dumps(rec, ensure_ascii=False) + "\n") + + shown_reg, more_reg = _truncate_list(dropped_in_registry) + shown_dup, more_dup = _truncate_list(dropped_duplicate_in_file) + + logger.info( + f"Summary | file={filename}\n" + f" input_lines (non-empty): {input_lines}\n" + f" output_lines (kept): {output_lines}\n" + f" removed_total: {removed_total}\n" + f" dropped_missing_accession: {dropped_missing_accession}\n" + f" dropped_in_global_registry: {len(dropped_in_registry)}\n" + f" dropped_duplicate_within_file: {len(dropped_duplicate_in_file)}" + ) + + if dropped_in_registry: + extra = f" ... ({more_reg} more)" if more_reg else "" + logger.info( + " accessions_removed_as_already_processed (sample):\n " + + "\n ".join(shown_reg) + + extra + ) + + if dropped_duplicate_in_file: + extra = f" ... ({more_dup} more)" if more_dup else "" + logger.info( + " accessions_removed_as_in_file_duplicates (sample):\n " + + "\n ".join(shown_dup) + + extra + ) + + logger.info(f"✅ Wrote {output_lines} rows -> {file_path}") + + except Exception as e: + logger.error(f"❌ Error while processing {filename}: {e}") + + +if __name__ == "__main__": + deduplicate_all_files() diff --git a/Scripts/tools/SEC_generate_cik_map.py b/Scripts/tools/SEC_generate_cik_map.py new file mode 100644 index 0000000..0ff0365 --- /dev/null +++ b/Scripts/tools/SEC_generate_cik_map.py @@ -0,0 +1,92 @@ +"""Generate the static ticker -> CIK map from SEC EDGAR. + +Output: ``config/reference/ticker_to_cik.json`` — this is the canonical +location read by ``Scripts.core.universe.UniverseLoader.cik_map()`` and by +``Scripts/data_collection/scrapers/sec_ingestion.py``. + +The curated filer universe (``config/universe/equity_single_name.json``) is +read here only to emit a sanity warning if it is missing. +""" + +import json +import logging +import sys +from pathlib import Path + +import requests + +# --- Path resolution: repo root is two levels above Scripts/tools/ --- +PROJECT_ROOT = Path(__file__).resolve().parents[2] + +# Make Scripts.core.universe importable whether this file is run directly or +# via `python -m Scripts.tools.SEC_generate_cik_map`. +if str(PROJECT_ROOT) not in sys.path: + sys.path.insert(0, str(PROJECT_ROOT)) + +# Canonical output location (was config/SEC_Ingestion/ — now retired). +REFERENCE_DIR = PROJECT_ROOT / "config" / "reference" +OUTPUT_CIK_MAP = REFERENCE_DIR / "ticker_to_cik.json" + +REFERENCE_DIR.mkdir(parents=True, exist_ok=True) + +logging.basicConfig( + level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s" +) +logger = logging.getLogger("CIK_Generator") + +# Replace with a contact email per SEC fair-access guidelines. +SEC_HEADERS = { + "User-Agent": "DataEngineer (bot@example.com)", + "Accept-Encoding": "gzip, deflate", +} + + +def generate_local_cik_map() -> None: + logger.info("📡 Downloading latest SEC ticker -> CIK mapping...") + url = "https://www.sec.gov/files/company_tickers.json" + + try: + response = requests.get(url, headers=SEC_HEADERS, timeout=15) + response.raise_for_status() + data = response.json() + + mapping = {} + for entry in data.values(): + ticker = entry["ticker"] + # SEC convention: 10-digit CIK string, zero-padded on the left + cik = str(entry["cik_str"]).zfill(10) + mapping[ticker] = cik + + with open(OUTPUT_CIK_MAP, "w", encoding="utf-8") as f: + json.dump(mapping, f, indent=4) + + logger.info(f"✅ Extracted {len(mapping)} tickers.") + logger.info(f"💾 Wrote CIK map to: {OUTPUT_CIK_MAP}") + + # Sanity check: the curated filer universe should exist and every + # ticker in it should resolve to a CIK (else sec_ingestion will skip). + try: + from Scripts.core.universe import universe as _universe + filers = _universe.get("sec.filers") + missing = [t for t in filers if t.upper() not in mapping] + if missing: + logger.warning( + f"⚠️ {len(missing)} filer tickers have no CIK in the freshly " + f"downloaded map (sample: {missing[:8]}). sec_ingestion will " + "skip these until they appear in SEC EDGAR." + ) + else: + logger.info( + f" (Filer universe OK: all {len(filers)} tickers mapped.)" + ) + except Exception as e: + logger.warning( + f"Could not cross-check filer universe via UniverseLoader: {e}" + ) + + except Exception as e: + logger.error(f"❌ Download or parse failed: {e}") + + +if __name__ == "__main__": + generate_local_cik_map() diff --git a/Scripts/tools/SEC_parsed_form4_8-k.py b/Scripts/tools/SEC_parsed_form4_8-k.py new file mode 100644 index 0000000..d78f94a --- /dev/null +++ b/Scripts/tools/SEC_parsed_form4_8-k.py @@ -0,0 +1,191 @@ +""" +Bronze SEC JSONL patch utility (Form 4 XML + 8-K HTML). + +Purpose +------- +Ingestion writes per-ticker JSONL under ``Data/1_Bronze_Raw/SEC_Parsed_JSON/{date}/``. +Some rows may still lack structured ``parsed_data`` (e.g. Form 4 needs EDGAR XML; +8-K benefits from HTML cleanup and item chunking). This script re-opens those +source files, fetches the filing URL content, runs the same parsers used in +``sec_ingestion`` (XML for Form 4, HTML→markdown chunks for 8-K), and writes +parallel outputs ``patched_{TICKER}.jsonl`` in the same date folder. It does +not change the original files. + +Logging +------- +Patch runs log to ``logs/{target_date}/SEC_Ingestion/`` (same date partition and +SEC subtree as ``sec_ingestion`` / ``sec_processor``), in a dedicated file +``patch_form4_8k_{target_date}.log`` so ingestion progress logs stay separate. +""" + +import glob +import json +import logging +import os +import sys +from pathlib import Path + +# --- Path resolution: repo root is two levels above Scripts/tools/ --- +PROJECT_ROOT = Path(__file__).resolve().parents[2] +# Bronze SEC JSONL layout (matches sec_ingestion.RAW_FOLDER) +DATA_REL_PARTS = ("Data", "1_Bronze_Raw", "SEC_Parsed_JSON") + +if str(PROJECT_ROOT) not in sys.path: + sys.path.insert(0, str(PROJECT_ROOT)) + +from Scripts.data_collection.scrapers.sec_ingestion import ( + fetch_and_parse_form4_xml, + fetch_and_parse_8k_html, +) + +logger = logging.getLogger("PatchBot") + + +def _patch_log_dir(target_date: str) -> Path: + """Daily SEC logs: logs/YYYY-MM-DD/SEC_Ingestion/ (shared with ingestion pipeline).""" + return PROJECT_ROOT / "logs" / target_date / "SEC_Ingestion" + + +def _configure_logging(target_date: str) -> None: + log_dir = _patch_log_dir(target_date) + log_dir.mkdir(parents=True, exist_ok=True) + log_file = log_dir / f"patch_form4_8k_{target_date}.log" + + logger.setLevel(logging.INFO) + fmt = logging.Formatter("%(asctime)s [%(levelname)s] %(message)s") + + logger.handlers.clear() + fh = logging.FileHandler(log_file, encoding="utf-8") + fh.setFormatter(fmt) + logger.addHandler(fh) + sh = logging.StreamHandler() + sh.setFormatter(fmt) + logger.addHandler(sh) + logger.propagate = False + + +def _is_source_bronze_jsonl(path: Path) -> bool: + """Per-ticker bronze files: {TICKER}.jsonl — skip patched outputs and summaries.""" + name = path.name + if not name.endswith(".jsonl"): + return False + if name.startswith("patched_") or name.startswith("_"): + return False + if "SUMMARY" in name.upper(): + return False + return True + + +def run_patch(target_date: str) -> None: + _configure_logging(target_date) + + target_folder = PROJECT_ROOT.joinpath(*DATA_REL_PARTS, target_date) + + if not target_folder.is_dir(): + logger.error(f"❌ Path does not exist: {target_folder}") + logger.info(f"💡 Verify PROJECT_ROOT is correct: {PROJECT_ROOT}") + return + + search_pattern = str(target_folder / "*.jsonl") + all_files = glob.glob(search_pattern) + target_files = [ + f + for f in all_files + if _is_source_bronze_jsonl(Path(f)) + ] + + if not target_files: + logger.warning(f"⚠️ No source *.jsonl files to process under {target_folder}.") + return + + logger.info( + f"🚀 Starting patch run | target_date={target_date} | files={len(target_files)} | " + f"log_dir={_patch_log_dir(target_date)}" + ) + + for file_path in target_files: + filename = os.path.basename(file_path) + patched_file_path = target_folder / f"patched_{filename}" + + if patched_file_path.is_file(): + logger.info(f"⏭️ Skipping; output already exists: {patched_file_path}") + continue + + logger.info(f"📝 Processing: {filename}") + + rows_processed = 0 + form4_patched = 0 + form8k_patched = 0 + + try: + with open(file_path, "r", encoding="utf-8") as f_in, open( + patched_file_path, "w", encoding="utf-8" + ) as f_out: + + for line_num, line in enumerate(f_in, 1): + line = line.strip() + if not line: + continue + + try: + record = json.loads(line) + metadata = record.get("metadata", {}) + form_type = str(metadata.get("form_type", "")) + url = metadata.get("url", "") + + # --- Form 4: fetch EDGAR XML and parse into structured fields --- + if form_type == "4" and url: + if not record.get("parsed_data"): + logger.info( + f" -> Fetch Form 4: {metadata.get('ticker')} (line {line_num})" + ) + parsed_xml = fetch_and_parse_form4_xml(url) + + if parsed_xml: + record["parsed_data"] = parsed_xml + record["raw_text"] = "XML_PARSED_SUCCESSFULLY" + form4_patched += 1 + else: + logger.error(f" ❌ Form 4 parse failed: {url}") + record["parsed_data"] = {} + + # --- 8-K: fetch HTML, strip noise, split into item markdown chunks --- + elif form_type == "8-K" and url: + if not record.get("parsed_data") or record.get( + "raw_text" + ) != "8K_PARSED_INTO_MARKDOWN_CHUNKS": + logger.info( + f" -> Fetch 8-K: {metadata.get('ticker')} (line {line_num})" + ) + parsed_8k = fetch_and_parse_8k_html(url) + + if parsed_8k: + record["parsed_data"] = parsed_8k + record["raw_text"] = "8K_PARSED_INTO_MARKDOWN_CHUNKS" + form8k_patched += 1 + else: + logger.error(f" ❌ 8-K parse failed: {url}") + record["parsed_data"] = {} + + if "parsed_data" not in record: + record["parsed_data"] = {} + + f_out.write(json.dumps(record, ensure_ascii=False) + "\n") + rows_processed += 1 + + except Exception as e: + logger.error(f" ❌ Parse error on line {line_num}: {e}") + + logger.info( + f"✅ Finished {filename}: rows={rows_processed} | Form 4 patches={form4_patched} | 8-K patches={form8k_patched}" + ) + + except Exception as e: + logger.error(f"❌ File processing aborted for {filename}: {e}") + if patched_file_path.is_file(): + patched_file_path.unlink() + + +if __name__ == "__main__": + DATE_TO_FIX = "2026-04-04" + run_patch(DATE_TO_FIX) diff --git a/Scripts/tools/check_Qdrant.py b/Scripts/tools/check_Qdrant.py new file mode 100644 index 0000000..f4c6f8c --- /dev/null +++ b/Scripts/tools/check_Qdrant.py @@ -0,0 +1,50 @@ +import sys +from pathlib import Path + +# dynamically resolve path issues +project_root = str(Path(__file__).resolve().parents[2]) +if project_root not in sys.path: + sys.path.insert(0, project_root) + +from Scripts.vector_store.connection import get_qdrant_client + +def run_health_check(): + client = get_qdrant_client() + collection_name = "financial_rag_gold" + + print("="*50) + print("🏥 Qdrant Database Health Check") + print("="*50) + + # 1. check if the collection exists and its count + try: + count_result = client.count(collection_name=collection_name) + print(f"✅ Collection found: '{collection_name}'") + print(f"📊 Total Documents in DB: {count_result.count}") + except Exception as e: + print(f"❌ Collection missing or error: {e}") + return + + # 2. sample one latest SEC document to verify Payload and Hybrid Vectors + print("\n🔍 Sampling 1 SEC document to verify Payload and Hybrid Vectors...") + scroll_results, _ = client.scroll( + collection_name=collection_name, + scroll_filter={"must": [{"key": "source_type", "match": {"value": "sec"}}]}, + limit=1, + with_payload=True, + with_vectors=True # force pull the vectors to see what's inside + ) + + if scroll_results: + doc = scroll_results[0] + print(f"\n[Document ID]: {doc.id}") + print(f"[Vector Types Found]: {list(doc.vector.keys())}") # should print out ['dense', 'sparse'] + print(f"[Text Preview]: {doc.payload.get('text')[:100]}...") + print(f"[Ticker]: {doc.payload.get('ticker')}") + print(f"[Unified Timestamp]: {doc.payload.get('unified_timestamp')}") + print(f"[Has Bronze Evidence?]: {doc.payload.get('has_bronze_evidence')}") + else: + print("⚠️ No SEC documents found.") + +if __name__ == "__main__": + run_health_check() \ No newline at end of file diff --git a/Scripts/vector_store/__init__.py b/Scripts/vector_store/__init__.py new file mode 100644 index 0000000..8d980ca --- /dev/null +++ b/Scripts/vector_store/__init__.py @@ -0,0 +1,8 @@ +from .connection import get_qdrant_client, get_embedding_model +from .ingestion import QdrantHybridIngestor + +__all__ = [ + "get_qdrant_client", + "get_embedding_model", + "QdrantHybridIngestor" +] \ No newline at end of file diff --git a/Scripts/vector_store/connection.py b/Scripts/vector_store/connection.py new file mode 100644 index 0000000..a7c36a2 --- /dev/null +++ b/Scripts/vector_store/connection.py @@ -0,0 +1,157 @@ +""" +Connection Management Layer for Vector Store (Cloud Native Version). +Implements Factory Pattern for Embedding Models (HuggingFace CPU-Bound / Ollama). +Manages secure RESTful connections to Qdrant Cloud. +""" + +import os +import time +import logging +from datetime import datetime +from pathlib import Path +from functools import lru_cache +from dotenv import load_dotenv + +from qdrant_client import QdrantClient +from langchain_core.embeddings import Embeddings +from langchain_huggingface import HuggingFaceEmbeddings +from langchain_ollama import OllamaEmbeddings + +# ========================================== +# 0. Dynamic logging (daily log isolation) +# ========================================== +def setup_logger(): + project_root = Path(__file__).resolve().parents[2] + today_str = datetime.now().strftime("%Y-%m-%d") + log_dir = project_root / "logs" / today_str + log_dir.mkdir(parents=True, exist_ok=True) + + log_file = log_dir / "connection.log" + + logger = logging.getLogger("VectorStoreConnection") + if not logger.handlers: + logger.setLevel(logging.INFO) + formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') + + file_handler = logging.FileHandler(log_file, encoding='utf-8') + file_handler.setFormatter(formatter) + logger.addHandler(file_handler) + + stream_handler = logging.StreamHandler() + stream_handler.setFormatter(formatter) + logger.addHandler(stream_handler) + + return logger + +logger = setup_logger() + +# Resolve project root and load .env +project_root = Path(__file__).resolve().parents[2] +load_dotenv(project_root / ".env", override=True) + +# ========================================== +# 1. Factory: embedding model (device controlled via env) +# ========================================== +@lru_cache(maxsize=1) +def get_embedding_model() -> Embeddings: + """ + Factory with explicit device control via environment variables. + Returns a cached LangChain Embeddings implementation (one per process). + """ + provider = os.getenv("EMBEDDING_PROVIDER", "huggingface").lower() + model_name = os.getenv("EMBEDDING_MODEL_NAME", "BAAI/bge-large-en-v1.5") + + # Guardrail: device comes from .env; default cpu + device = os.getenv("EMBEDDING_DEVICE", "cpu").lower() + + logger.info(f"Initialize Embedding Engine -> Provider: [{provider.upper()}], Model: [{model_name}], Device: [{device.upper()}]") + + try: + if provider == "ollama": + # Warning: Ollama embeddings can contend with a local LLM in production + ollama_host = os.getenv("OLLAMA_HOST", "http://localhost:11434") + logger.warning("Using Ollama for embeddings. This may cause OOM if a large LLM is concurrently active.") + return OllamaEmbeddings( + model=model_name, + base_url=ollama_host + ) + + elif provider == "huggingface": + # Recommended: HuggingFace local; device from EMBEDDING_DEVICE (default cpu) + model_kwargs = {'device': device} + encode_kwargs = {'normalize_embeddings': True} # Normalize for cosine similarity in Qdrant + + emb_model = HuggingFaceEmbeddings( + model_name=model_name, + model_kwargs=model_kwargs, + encode_kwargs=encode_kwargs + ) + logger.info("✅ HuggingFace Embedding Model loaded successfully.") + return emb_model + + else: + raise ValueError(f"Unsupported EMBEDDING_PROVIDER: {provider}") + + except Exception as e: + logger.error(f"❌ Failed to load Embedding Model: {e}") + raise + +# ========================================== +# 2. Qdrant Cloud connection +# ========================================== +@lru_cache(maxsize=1) +def get_qdrant_client() -> QdrantClient: + """ + Return cached Qdrant Cloud client singleton. + """ + qdrant_url = os.getenv("QDRANT_HOST") + qdrant_api_key = os.getenv("QDRANT_API_KEY") + + if not qdrant_url or not qdrant_api_key: + logger.error("QDRANT_HOST or QDRANT_API_KEY is missing in .env") + raise ValueError("Database credentials missing.") + + max_retries = 3 + delay_seconds = 2 + + for attempt in range(1, max_retries + 1): + try: + logger.info(f"Connecting to Qdrant Cloud [{qdrant_url[:12]}...] (Attempt {attempt}/{max_retries})...") + + client = QdrantClient( + url=qdrant_url, + api_key=qdrant_api_key, + timeout=15.0, + prefer_grpc=False # HTTP/HTTPS only; avoids many firewall/grpc blocks + ) + + client.get_collections() + logger.info("✅ Connected to Qdrant Cloud successfully.") + return client + + except Exception as e: + logger.warning(f"⚠️ Connection to Cloud failed on attempt {attempt}: {e}") + if attempt < max_retries: + time.sleep(delay_seconds) + else: + logger.error("❌ Max retries reached. Could not connect to Qdrant Cloud.") + raise ConnectionError(f"Failed to connect to Qdrant Cloud.") from e + +# ========================================== +# 3. Health check +# ========================================== +if __name__ == "__main__": + logger.info("=== Starting System Component Health Check ===") + try: + db_client = get_qdrant_client() + collections = db_client.get_collections() + logger.info(f"📊 Current Collections in Cloud: {[c.name for c in collections.collections]}") + + emb_model = get_embedding_model() + + # Smoke-test embedding pipeline + test_vec = emb_model.embed_query("Apple Inc. financial results.") + logger.info(f"✅ Embedding test passed. Vector dimension: {len(test_vec)}") + logger.info("🎉 Health Check Passed: Cloud DB and CPU Embedding Model are fully operational.") + except Exception as e: + logger.error(f"❌ Health Check Failed: {e}", exc_info=True) \ No newline at end of file diff --git a/Scripts/vector_store/ingestion.py b/Scripts/vector_store/ingestion.py new file mode 100644 index 0000000..8906e78 --- /dev/null +++ b/Scripts/vector_store/ingestion.py @@ -0,0 +1,386 @@ +""" +Institutional-Grade Vector Store Ingestion Layer. +Implements: +1. Dual-Track Idempotent Ingestion (UUIDv5 for SEC, Native IDs for News/GPR). +2. Hybrid Search Initialization (Dense + Sparse/BM25 vectors). +3. Payload Indexing (Strict categorization: Keyword, Array, Datetime). +4. Bronze Evidence Linking (Tracking SEC accession_no). +""" + +import os +import json +import uuid +import logging +from datetime import datetime +from pathlib import Path +from tqdm import tqdm +from dotenv import load_dotenv + +# import Qdrant native objects +from qdrant_client.http import models +from qdrant_client.models import PointStruct, VectorParams, SparseVectorParams, Distance + +# import FastEmbed for sparse vector generation +from fastembed import SparseTextEmbedding + +import sys +from pathlib import Path + + +project_root = str(Path(__file__).resolve().parents[2]) +if project_root not in sys.path: + sys.path.insert(0, project_root) + +from Scripts.vector_store.connection import get_qdrant_client, get_embedding_model + +load_dotenv(override=True) + +SYSTEM_NAMESPACE = uuid.UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8') + +def setup_ingestion_logger(): + project_root = Path(__file__).resolve().parents[2] + today_str = datetime.now().strftime("%Y-%m-%d") + log_dir = project_root / "logs" / today_str + log_dir.mkdir(parents=True, exist_ok=True) + + log_file = log_dir / "ingestion.log" + logger = logging.getLogger("HybridIngestion") + + if not logger.handlers: + logger.setLevel(logging.INFO) + formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') + + file_handler = logging.FileHandler(log_file, encoding='utf-8') + file_handler.setFormatter(formatter) + logger.addHandler(file_handler) + + stream_handler = logging.StreamHandler() + stream_handler.setFormatter(formatter) + logger.addHandler(stream_handler) + + return logger + +logger = setup_ingestion_logger() + +class QdrantHybridIngestor: + def __init__(self, collection_name: str = "financial_rag_gold"): + self.collection_name = collection_name + self.project_root = Path(__file__).resolve().parents[2] + self.gold_layer_dir = self.project_root / "Data" / "3_Gold_Semantic" + self.batch_size = 100 + + logger.info("Initializing Connections & AI Models...") + self.client = get_qdrant_client() + self.dense_model = get_embedding_model() + self.sparse_model = SparseTextEmbedding(model_name="prithivida/Splade_PP_en_v1") + + # dynamically detect dimension + dummy_vector = self.dense_model.embed_query("dummy_test") + self.dense_dimension = len(dummy_vector) + logger.info(f"Dense Vector Dimension detected as: {self.dense_dimension}") + + def _get_uuid_v5(self, accession_no: str) -> str: + return str(uuid.uuid5(SYSTEM_NAMESPACE, accession_no)) + + def _to_unix_timestamp(self, date_str: str) -> int: + if not date_str: return 0 + try: + return int(datetime.strptime(date_str[:10], "%Y-%m-%d").timestamp()) + except Exception: + return 0 + + # ====================================================================== + # Canonical payload-index schema (single source of truth). + # + # Every key the retriever filters on MUST appear here. Qdrant rejects a + # Range filter with `400 Bad Request: Index required but not found for …` + # if the payload key is not indexed as `integer`/`float`, so missing a + # key here is NOT a silent perf regression — it's a hard pipeline break. + # + # Production audit 2026-04-22 caught exactly this: the Gold retriever + # filters on `unified_timestamp` OR `publish_timestamp` (nested should), + # but only `unified_timestamp` was indexed → every query 400'd whenever + # source_type picked up a payload without `unified_timestamp`. + # ====================================================================== + _REQUIRED_INDEXES: list = [ + # -- Keyword filters (exact match / array contains) -- + ("ticker", models.PayloadSchemaType.KEYWORD), + ("form_type", models.PayloadSchemaType.KEYWORD), + ("action_direction", models.PayloadSchemaType.KEYWORD), + ("source_type", models.PayloadSchemaType.KEYWORD), + ("topic", models.PayloadSchemaType.KEYWORD), + ("topics", models.PayloadSchemaType.KEYWORD), + ("impacted_assets", models.PayloadSchemaType.KEYWORD), + ("entities", models.PayloadSchemaType.KEYWORD), + # -- Numeric range filters (Gold time barrier) -- + # BOTH keys must be indexed because the retriever uses nested + # `should=[unified_timestamp, publish_timestamp]` to heal legacy + # payloads that only carry one of the two. + ("unified_timestamp", models.PayloadSchemaType.INTEGER), + ("publish_timestamp", models.PayloadSchemaType.INTEGER), + # -- Optional numeric auxiliary filters (News tone ranges) -- + ("tone_score", models.PayloadSchemaType.INTEGER), + ("llm_tone_score", models.PayloadSchemaType.INTEGER), + ] + + def _ensure_payload_indexes(self) -> None: + """Idempotently create every index in `_REQUIRED_INDEXES`. + + Safe to call on both fresh and existing collections: + - Fresh collection → creates all indexes. + - Existing collection missing one index → creates only the missing + ones (the "already exists" branch raises a benign 400 that we + swallow and log at INFO). + - Existing collection already fully indexed → every call is a + no-op; no drop, no re-vectorise, no downtime. + + This is the auto-heal path that saved the 2026-04-22 outage: the + collection had been created back when only `unified_timestamp` was + in the schema, and the retriever's `publish_timestamp` Range filter + was 400-ing until this method was promoted out of the "if not + exists" branch. + """ + for field, schema in self._REQUIRED_INDEXES: + try: + self.client.create_payload_index( + self.collection_name, field_name=field, field_schema=schema, + ) + logger.info(f"✅ Payload Index ensured: {field} ({schema})") + except Exception as e: + # Qdrant returns 400/409 for "index already exists" — treat + # as success but keep the message so operators can confirm + # the index is there. Any *other* error surfaces loudly. + msg = str(e).lower() + if "already exists" in msg or "conflict" in msg or "409" in msg: + logger.info(f"ℹ️ Payload Index already present: {field}") + else: + logger.error(f"❌ Failed to ensure index for {field}: {e}") + raise + + def init_collection_with_indexes(self): + """Create the collection if missing, then always reconcile indexes. + + Index reconciliation runs on EVERY call (not just at collection- + create time) so schema additions in `_REQUIRED_INDEXES` propagate to + existing production collections on the next ingest run — no manual + drop-and-recreate required. + """ + if not self.client.collection_exists(self.collection_name): + logger.info(f"🚀 Creating new Hybrid Collection: {self.collection_name}") + self.client.create_collection( + collection_name=self.collection_name, + vectors_config={ + "dense": VectorParams(size=self.dense_dimension, distance=Distance.COSINE) + }, + sparse_vectors_config={ + "sparse": SparseVectorParams() + } + ) + else: + logger.info(f"✅ Collection '{self.collection_name}' already exists. Reconciling payload indexes…") + + # Always ensure indexes — auto-heals collections that predate a + # schema addition (e.g. `publish_timestamp` in 2026-04-22). + self._ensure_payload_indexes() + + def process_and_upsert_file(self, file_path: Path, source_type: str) -> int: + points = [] + success_count = 0 + + try: + with open(file_path, 'r', encoding='utf-8') as f: + lines = f.readlines() + except Exception as e: + logger.error(f"❌ Could not read {file_path.name}: {e}") + return 0 + + logger.info(f"📦 Processing {len(lines)} records from {file_path.name} (Type: {source_type.upper()})...") + + for line in tqdm(lines, desc=f"Embedding {source_type}"): + if not line.strip(): continue + try: + data = json.loads(line) + text = data.get("text", "") + metadata = data.get("metadata", {}) + + # 1. ID 处理 + acc_no = metadata.get("accession_no") + if source_type == "sec" and acc_no: + point_id = self._get_uuid_v5(acc_no) + has_bronze_evidence = True + else: + point_id = data.get("id", str(uuid.uuid4())) + has_bronze_evidence = False + + # 2. unified timestamp + raw_date = metadata.get("publish_timestamp") # News takes precedence over this + if not raw_date: + raw_date = metadata.get("publish_date") or metadata.get("filed_at") or metadata.get("transaction_date") + + # if the date is already an integer timestamp (News/GPR), use it; otherwise convert to timestamp + if isinstance(raw_date, int): + unified_ts = raw_date + else: + unified_ts = self._to_unix_timestamp(str(raw_date)) + + # 3. defensive metadata construction to prevent data loss + payload = { + "text": text, + "source_type": source_type, + "has_bronze_evidence": has_bronze_evidence, + "unified_timestamp": unified_ts, + + # provide default values to prevent empty values from being filtered out + "ticker": metadata.get("ticker", "NONE"), + "form_type": metadata.get("form_type", "NONE"), + "action_direction": metadata.get("action_direction", "NONE"), + "topics": metadata.get("topics") or [metadata.get("topic", "NONE")], + "entities": metadata.get("entities", []), + + **metadata + } + + # 4. Hybrid Embedding + dense_vec = self.dense_model.embed_query(text) + sparse_gen = list(self.sparse_model.embed([text]))[0] + sparse_vec = models.SparseVector( + indices=sparse_gen.indices.tolist(), + values=sparse_gen.values.tolist() + ) + + # 5. 构建与 Upsert + points.append(PointStruct( + id=point_id, + vector={ + "dense": dense_vec, + "sparse": sparse_vec + }, + payload=payload + )) + + if len(points) >= self.batch_size: + self.client.upsert(collection_name=self.collection_name, points=points) + success_count += len(points) + points = [] + + except Exception as e: + logger.error(f"⚠️ Error processing record in {file_path.name}: {e}") + + if points: + try: + self.client.upsert(collection_name=self.collection_name, points=points) + success_count += len(points) + except Exception as e: + logger.error(f"❌ Error during final batch upsert in {file_path.name}: {e}") + + logger.info(f"✅ Completed {file_path.name}: Upserted {success_count} documents.") + return success_count + + def _get_run_states(self) -> dict: + """ + read the state file to get the last run keys + """ + state_file = self.project_root / "config" / "runtime" / "collect_data_state.json" + states = {} + + # default fallback mechanism: if the state file is not found, default to the current date + today = datetime.now().strftime("%Y-%m-%d") + current_month = datetime.now().strftime("%Y-%m") + + if state_file.exists(): + try: + with open(state_file, 'r', encoding='utf-8') as f: + data = json.load(f) + last_run_keys = data.get("last_run_keys", {}) + + # map the job key to the ingestion source type + states = { + "news": last_run_keys.get("news_daily", today), + "gpr": last_run_keys.get("gpr_monthly", current_month), + "sec": last_run_keys.get("sec_daily", today) + } + logger.info(f"📄 Successfully loaded upstream states: {states}") + return states + except Exception as e: + logger.error(f"⚠️ Failed to parse state file: {e}. Falling back to current date.") + + # Fallback + return {"news": today, "gpr": current_month, "sec": today} + + def run_pipeline(self, full_refresh: bool = True): + """ + :param full_refresh: if True, full refresh the pipeline + """ + logger.info("="*50) + logger.info(f"🚀 Starting Hybrid Search Data Ingestion Pipeline (Full Refresh: {full_refresh})") + logger.info("="*50) + + if not self.gold_layer_dir.exists(): + logger.error(f"❌ Data directory not found: {self.gold_layer_dir}") + return + + self.init_collection_with_indexes() + + # get the upstream watermark + target_states = self._get_run_states() + + total_upserted = 0 + file_mappings = [ + ("sec", "qdrant_ready.jsonl"), + ("news", "qdrant_asset_precious_metals_spot_processed.jsonl"), + ("news", "qdrant_macro_inflation_employment_processed.jsonl"), + ("news", "qdrant_macro_central_banks_processed.jsonl"), + ("news", "qdrant_macro_yields_dollar_processed.jsonl"), + ("news", "qdrant_asset_metals_derivatives_processed.jsonl"), + ("gpr", "qdrant_gpr_input.jsonl") + ] + + for source_type, filename in file_mappings: + found_files = list(self.gold_layer_dir.rglob(filename)) + + # get the date identifier for this data source + target_date_str = target_states.get(source_type, "") + + for f_path in found_files: + # core logic: if full refresh is enabled, or the file path contains the target date, then process + if full_refresh or (target_date_str and target_date_str in str(f_path)): + count = self.process_and_upsert_file(f_path, source_type) + total_upserted += count + else: + # not the target date history file, skip (silent, no logging) + pass + + logger.info("="*50) + logger.info(f"🎉 Pipeline Complete! Documents Upserted this run: {total_upserted}") + logger.info("="*50) + +if __name__ == "__main__": + import argparse + parser = argparse.ArgumentParser( + description="Qdrant Hybrid Ingestor (init + upsert pipeline)." + ) + parser.add_argument( + "--indexes-only", + action="store_true", + help=( + "Only reconcile payload indexes on the existing collection — " + "no embedding, no upsert. Use this to auto-heal a collection " + "that predates a new index (e.g. publish_timestamp added " + "2026-04-22) without re-vectorising data." + ), + ) + parser.add_argument( + "--no-full-refresh", + action="store_true", + help="Only process files matching the upstream watermark (default is full refresh).", + ) + args = parser.parse_args() + + ingestor = QdrantHybridIngestor() + if args.indexes_only: + # Fast path for the 400 "Index required but not found" auto-heal. + # Completes in ~1s regardless of collection size. + ingestor.init_collection_with_indexes() + logger.info("🔧 Index-only reconciliation complete.") + else: + ingestor.run_pipeline(full_refresh=not args.no_full_refresh) \ No newline at end of file diff --git a/config/Config_docs.md b/config/Config_docs.md new file mode 100644 index 0000000..b00d173 --- /dev/null +++ b/config/Config_docs.md @@ -0,0 +1,169 @@ +# `config/` — Configuration single source of truth + +This tree is intentionally **semantic-layered**, not pipeline-layered: files live next to *what they describe* (the asset universe, reference maps, per-pipeline parameters), not next to the script that happens to consume them. All access goes through **`Scripts/core/universe.py`** — callers should never `open()` files in this tree directly. + +## Layout + +``` +config/ +├── universe/ # WHAT we track +│ ├── _manifest.json # schema + role metadata (owner, coverage, flags) +│ ├── equity_single_name.json # 48 Nasdaq-100 single-names +│ ├── etf_broad_market.json # ["SPY", "QQQ", "IWM"] +│ └── etf_commodity.json # ["GLD", "SLV"] +│ +├── reference/ # STATIC lookup tables (derived from external sources) +│ └── ticker_to_cik.json # ticker -> SEC CIK (~10K entries; written by SEC_generate_cik_map.py) +│ +├── pipeline/ # PER-PIPELINE parameters (no business logic) +│ └── options_history.json # yfinance options scraper: universe_role, storage strategy, … +│ +└── runtime/ # MUTABLE runtime state + ├── collect_data_state.json # data-collection checkpoint + └── sec_processed_registry.json # SEC accession de-dup ledger (moved from SEC_Processing/ on 2026-04-22) +``` + +> Retired on **2026-04-22**: ``config/SEC_Ingestion/`` and ``config/SEC_Processing/``. +> All of their content now lives under ``universe/``, ``reference/``, or ``runtime/`` and is reached through ``Scripts.core.universe`` — **never** by opening a hard-coded path. + +## Why semantic layering + +| Old pipeline-layered layout | New semantic layout | +|------------------------------------------------------|---------------------------------------------| +| `config/SEC_Ingestion/SEC_tickers.json` | `config/universe/equity_single_name.json` | +| `config/Option_chain/target_symbols.json` (proposed) | `config/universe/etf_broad_market.json` | +| Duplicated ticker lists across pipelines | **One list per role**, unioned via manifest | + +The universe knows nothing about SEC or yfinance; it just declares *which tickers are equities, which are broad-market ETFs, which are commodity ETFs*. Pipelines then **ask for a role** (`sec.filers`, `options.scrape`) and the manifest resolves the union. + +## Access pattern + +```python +from Scripts.core.universe import universe, pipelines, paths + +universe.get("sec.filers") # ['AAPL', 'ADBE', …] +universe.get("options.scrape") # 53 tickers = single_names ∪ ETFs +universe.cik_map() # {'AAPL': '0000320193', …} +universe.asset_class_of("SPY") # 'etf' + +pipelines.load("options_history") # dict with scrape / storage / … + +paths.options_parquet_path("SPY", "2026-04-22") +# legacy -> Data/2_Silver_Processed/Options_Market_Data/2026-04-22/SPY_options_2026-04-22.parquet +# hive_v1 -> Data/2_Silver_Processed/Options_Market_Data/snapshot_date=2026-04-22/asset_class=etf/SPY.parquet +# monthly_rollup +# -> Data/2_Silver_Processed/Options_Market_Data/raw/snapshot_date=2026-04-22/SPY.parquet +``` + +The active strategy is `storage.strategy` in `pipeline/options_history.json`. +**Default is `legacy`**, which produces paths byte-identical to the pre-migration code so `Scripts/retrieval/sql_tools.py` read-side globs keep working unchanged. + +--- + +## Storage scaling — the 13K-files-per-year problem + +With the universe now at **53 tickers** (`options.scrape` role), the scraper writes **53 parquet / day → ~13,356 parquet / year**. The tree below is the recommended migration path. None of it requires touching the scraper's business logic. + +### Phase 0 — today (`storage.strategy = legacy`) ✅ default + +``` +Data/2_Silver_Processed/Options_Market_Data/ +└── 2026-04-22/ + ├── SPY_options_2026-04-22.parquet + ├── QQQ_options_2026-04-22.parquet + └── … +``` + +* Pros: zero-risk drop-in for the existing `*/*.parquet` glob in `sql_tools.py:183`. +* Cons: No partition pruning metadata on disk; just a flat date folder. +* Verdict: **fine up to ~5K–10K files**. DuckDB will still happily glob that many parquets; the real cost is only in S3-backed setups with per-object latency. + +### Phase 1 — Hive partitioning (`storage.strategy = hive_v1`) + +``` +Data/2_Silver_Processed/Options_Market_Data/ +├── snapshot_date=2026-04-22/ +│ ├── asset_class=etf/ +│ │ ├── SPY.parquet +│ │ ├── QQQ.parquet +│ │ └── … +│ └── asset_class=equity/ +│ ├── AAPL.parquet +│ ├── MSFT.parquet +│ └── … +``` + +* DuckDB reads with partition pushdown: + ```sql + SELECT * FROM read_parquet( + '.../Options_Market_Data/**/*.parquet', hive_partitioning=1 + ) + WHERE snapshot_date = '2026-04-22' AND asset_class = 'etf' + ``` + → only touches the 5 ETF files, not all 53. +* **Still ~13K files/year** — but with cheap column-free filtering. +* Migration cost: (a) update `options_glob` to `**/*.parquet` and add `hive_partitioning=1`; (b) optional one-off backfill script to copy legacy files into the new tree; (c) flip `storage.strategy` to `hive_v1`. + +### Phase 2 — Monthly roll-up compaction (`storage.strategy = monthly_rollup`) + +``` +Data/2_Silver_Processed/Options_Market_Data/ +├── raw/ # hot tier: last N days only +│ └── snapshot_date=2026-04-22/ +│ ├── SPY.parquet +│ └── … +└── rollup/ # cold tier: 1 compacted file / month + ├── snapshot_month=2026-03/ + │ └── options_chain.parquet # ALL tickers × ALL days of March + └── snapshot_month=2026-04/ + └── options_chain.parquet +``` + +* Writer side is unchanged — it keeps dropping per-ticker-per-day files into `raw/`. A **separate compaction job** (e.g. monthly cron, not included in this PR) runs: + ```python + df = duckdb.sql(f""" + SELECT *, snapshot_date + FROM read_parquet('.../raw/snapshot_date=2026-03-*/*.parquet', + hive_partitioning=1) + """).to_df() + df.to_parquet('.../rollup/snapshot_month=2026-03/options_chain.parquet', + partition_cols=None, compression='zstd', row_group_size=100_000) + # After rollup is verified, the raw/ tier is pruned for that month. + ``` +* **File count collapses from ~1100/month to 1/month** → 12 rollup files + ~30–60 days of raw hot files = well under 100 files/year on disk. +* Silver SQL then reads: `rollup/**/*.parquet UNION ALL raw/**/*.parquet` with a date-range filter — DuckDB merges the views. + +### When to escalate + +| Universe size | Recommendation | +|---------------|--------------------------------------| +| ≤ 20 tickers | `legacy` is fine. Don't over-engineer. | +| 20–80 tickers | Move to `hive_v1` when convenient. | +| 80+ tickers, multi-year horizon | Implement Phase 2 rollup; prune `raw/` after compaction. | + +--- + +## Adding a new ticker + +1. Append the ticker to the right leaf file under `universe/` (e.g. + `universe/equity_single_name.json`). +2. If it requires SEC filings, run + `python Scripts/tools/SEC_generate_cik_map.py` to refresh + `config/reference/ticker_to_cik.json`. +3. No code change. Both `sec_ingestion.py` and `yfinance_options_history.py` + pick up the new ticker on the next run via `universe.get(role)`. + +## Migration log (2026-04-22) + +| Retired location | New location | +|------------------------------------------------------|----------------------------------------------------| +| `config/SEC_Ingestion/SEC_tickers.json` | `config/universe/equity_single_name.json` (role `sec.filers`) | +| `config/SEC_Ingestion/ticker_to_cik.json` | `config/reference/ticker_to_cik.json` | +| `config/SEC_Processing/global_processed_registry.json` | `config/runtime/sec_processed_registry.json` | + +Callers updated in the same commit: +`Scripts/retrieval/query_transform.py`, `Scripts/tools/SEC_generate_cik_map.py`, +`Scripts/tools/SEC_Accession_No_depulicated.py`, +`Scripts/data_collection/scrapers/sec_ingestion.py`, +`Scripts/data_collection/processors/sec_processor.py`, +`Scripts/core/universe.py`. diff --git a/config/pipeline/options_history.json b/config/pipeline/options_history.json new file mode 100644 index 0000000..dcca0f9 --- /dev/null +++ b/config/pipeline/options_history.json @@ -0,0 +1,49 @@ +{ + "schema_version": "1.0", + "description": "Parameters for Scripts/data_collection/scrapers/yfinance_options_history.py. Business logic (derived metrics, is_liquid flag) is NOT governed here and stays in code.", + + "universe_role": "options.scrape", + + "scrape": { + "request_delay_sec": 1.0, + "inter_symbol_delay_sec": 2.0, + "near_term_expirations": 10 + }, + + "storage": { + "strategy": "legacy", + "comment": "Active strategy is `legacy`. Keep this value until Silver read-side (Scripts/retrieval/sql_tools.py:options_glob) is migrated to Hive-partitioned glob. Supported strategies:", + "strategies": { + "legacy": { + "path_template": "{data_root}/2_Silver_Processed/Options_Market_Data/{snapshot_date}/{symbol}_options_{snapshot_date}.parquet", + "description": "Current layout. 1 file per (ticker, day). Preserves backward compatibility with sql_tools.py's `*/*.parquet` glob.", + "files_per_year_at_53_tickers": 13356 + }, + "hive_v1": { + "path_template": "{data_root}/2_Silver_Processed/Options_Market_Data/snapshot_date={snapshot_date}/asset_class={asset_class}/{symbol}.parquet", + "description": "Hive-partitioned by (snapshot_date, asset_class). Enables DuckDB partition pruning via hive_partitioning=1. Requires read-side glob update to `**/*.parquet`.", + "files_per_year_at_53_tickers": 13356, + "migration_checklist": [ + "1. Update Scripts/retrieval/sql_tools.py:options_glob to use hive_partitioning=1.", + "2. Backfill: re-run snapshot or one-off migration copying legacy files into new tree.", + "3. Flip storage.strategy to `hive_v1` here.", + "4. Update docs/Data_source_docs/options_historial_data.md path example." + ] + }, + "monthly_rollup": { + "path_template_raw": "{data_root}/2_Silver_Processed/Options_Market_Data/raw/snapshot_date={snapshot_date}/{symbol}.parquet", + "path_template_rollup": "{data_root}/2_Silver_Processed/Options_Market_Data/rollup/snapshot_month={yyyy_mm}/options_chain.parquet", + "description": "Dual-tier: hot raw (last N days) + monthly compacted roll-up. Single rollup file per month instead of ~1100 per month. Requires a compaction job (see docs/storage_migration.md).", + "target_files_per_year": 12, + "notes": "Recommended final state once universe grows beyond 50 tickers. Not yet implemented." + } + } + }, + + "liquidity_thresholds_by_role": { + "_comment": "Reference values only — NOT read by yfinance_options_history.py today. The scraper still applies its hard-coded global thresholds (volume>=50 & open_interest>=100 & bid>0). Promote these to code only after per-role tuning is validated.", + "etf.broad_market": {"volume": 50, "open_interest": 100}, + "etf.commodity": {"volume": 30, "open_interest": 50}, + "equity.single_name": {"volume": 20, "open_interest": 50} + } +} diff --git a/config/reference/ticker_to_cik.json b/config/reference/ticker_to_cik.json new file mode 100644 index 0000000..c32143d --- /dev/null +++ b/config/reference/ticker_to_cik.json @@ -0,0 +1,10411 @@ +{ + "NVDA": "0001045810", + "AAPL": "0000320193", + "GOOGL": "0001652044", + "MSFT": "0000789019", + "AMZN": "0001018724", + "AVGO": "0001730168", + "META": "0001326801", + "TSLA": "0001318605", + "BRK-B": "0001067983", + "WMT": "0000104169", + "LLY": "0000059478", + "JPM": "0000019617", + "XOM": "0000034088", + "SPY": "0000884394", + "JNJ": "0000200406", + "V": "0001403161", + "ASML": "0000937966", + "COST": "0000909832", + "MA": "0001141391", + "ORCL": "0001341439", + "NFLX": "0001065280", + "MU": "0000723125", + "CVX": "0000093410", + "ABBV": "0001551152", + "CYATY": "0002070829", + "PLTR": "0001321655", + "AMD": "0000002488", + "BAC": "0000070858", + "CAT": "0000018230", + "PG": "0000080424", + "KO": "0000021344", + "HD": "0000354950", + "AZN": "0000901832", + "CSCO": "0000858877", + "MRK": "0000310158", + "NVS": "0001114448", + "GE": "0000040545", + "BABA": "0001577552", + "HSBC": "0001089113", + "AMAT": "0000006951", + "LRCX": "0000707549", + "TM": "0001094517", + "RTX": "0000101829", + "MS": "0000895421", + "SHEL": "0001306965", + "GS": "0000886982", + "INTC": "0000050863", + "UNH": "0000731766", + "WFC": "0000072971", + "PM": "0001413329", + "GEV": "0001996810", + "LIN": "0001707925", + "IBM": "0000051143", + "QQQ": "0001067839", + "RY": "0001000275", + "TMUS": "0001283699", + "MCD": "0000063908", + "PEP": "0000077476", + "VZ": "0000732712", + "AXP": "0000004962", + "SAP": "0001000184", + "C": "0000831001", + "KLAC": "0000319201", + "T": "0000732717", + "TTE": "0000879764", + "MUFG": "0000067088", + "RTNTF": "0000887028", + "NEE": "0000753308", + "AMGN": "0000318154", + "BHP": "0000811809", + "TMO": "0000097745", + "TJX": "0000109198", + "DTEGY": "0000946770", + "ABT": "0000001800", + "TXN": "0000097476", + "CRM": "0001108524", + "GILD": "0000882095", + "DIS": "0001744489", + "SCHW": "0000316709", + "SAN": "0000891478", + "NVO": "0000353278", + "BA": "0000012927", + "PFE": "0000078003", + "ISRG": "0001035267", + "TD": "0000947263", + "COP": "0001163165", + "ANET": "0001596532", + "ARM": "0001973239", + "APH": "0000820313", + "DE": "0000315189", + "ADI": "0000006281", + "SHOP": "0001594805", + "RIO": "0000863064", + "BLK": "0002012383", + "UBER": "0001543151", + "SCCO": "0001001838", + "HON": "0000773840", + "UNP": "0000100885", + "LMT": "0000936468", + "PDD": "0001737806", + "WELL": "0000766704", + "ETN": "0001551182", + "BUD": "0001668717", + "BX": "0001393818", + "QCOM": "0000804328", + "DHR": "0000313616", + "BKNG": "0001075531", + "HTHIY": "0000047710", + "PANW": "0001327567", + "PBR": "0001119639", + "APP": "0001751008", + "SPGI": "0000064040", + "UTX": "0002046954", + "SMFG": "0001022837", + "LOW": "0000060667", + "CB": "0000896159", + "HDB": "0001144967", + "GLW": "0000024741", + "SYK": "0000310764", + "BTI": "0001303523", + "SONY": "0000313838", + "PLD": "0001045609", + "UBS": "0001610520", + "BBVA": "0000842180", + "NEM": "0001164727", + "ACN": "0001467373", + "BP": "0000313807", + "BMY": "0000014272", + "UL": "0000217410", + "ENB": "0000895728", + "INTU": "0000896878", + "SNY": "0001121404", + "DELL": "0001571996", + "IBKR": "0001381197", + "PH": "0000076334", + "PGR": "0000080661", + "GSK": "0001131399", + "COF": "0000927628", + "GLD": "0001222333", + "VRTX": "0000875320", + "MDT": "0001613103", + "CME": "0001156375", + "MO": "0000764180", + "MCK": "0000927653", + "SO": "0000092122", + "NOW": "0001373715", + "HCA": "0000860730", + "AEM": "0000002809", + "EQNR": "0001140625", + "SNDK": "0002023554", + "SBUX": "0000829224", + "DUK": "0001326160", + "CMCSA": "0001166691", + "CRWD": "0001535527", + "WDC": "0000106040", + "SPOT": "0001639920", + "NOC": "0001133421", + "VRT": "0001674101", + "MFG": "0001335730", + "CNQ": "0001017413", + "ADBE": "0000796343", + "CEG": "0001868275", + "ATEYY": "0001158838", + "EQIX": "0001101239", + "BMO": "0000927971", + "STX": "0001137789", + "WM": "0000823768", + "TT": "0001466258", + "GD": "0000040533", + "MRVL": "0001835632", + "HWM": "0000004281", + "CVS": "0000064803", + "BSX": "0000885725", + "IBN": "0001103838", + "ICE": "0001571949", + "BN": "0001001085", + "ITUB": "0001132597", + "BAESY": "0000895564", + "CM": "0001045520", + "FCX": "0000831259", + "WMB": "0000107263", + "MAR": "0001048286", + "NGG": "0001004315", + "MELI": "0001099590", + "BNS": "0000009631", + "FDX": "0001048911", + "PNC": "0000713676", + "MRSH": "0000062709", + "IAU": "0001278680", + "BK": "0001390777", + "MGCLY": "0002039784", + "KKR": "0001404912", + "E": "0001002242", + "PWR": "0001050915", + "UPS": "0001090727", + "ADP": "0000008670", + "USB": "0000036104", + "JCI": "0000833444", + "AMT": "0001053507", + "EPD": "0001061219", + "REGN": "0000872589", + "SHW": "0000089800", + "SU": "0000311337", + "MCO": "0001059556", + "ING": "0001039765", + "AMX": "0001129137", + "CDNS": "0000813672", + "CSX": "0000277948", + "ORLY": "0000898173", + "EOG": "0000821189", + "LYG": "0001160106", + "MMM": "0000066740", + "CMI": "0000026172", + "SNPS": "0000883241", + "KXIAY": "0002053383", + "ABNB": "0001559720", + "BCS": "0000312069", + "ECL": "0000031462", + "RCL": "0000884887", + "NET": "0001477333", + "ITW": "0000049826", + "MDLZ": "0001103982", + "SLB": "0000087347", + "EMR": "0000032604", + "KMI": "0001506307", + "MSI": "0000068505", + "VLO": "0001035002", + "BAM": "0001937926", + "NTES": "0001110646", + "CI": "0001739940", + "AEP": "0000004904", + "MPC": "0001510295", + "ROST": "0000745732", + "HLT": "0001585689", + "CP": "0000016875", + "MNST": "0000865752", + "PSX": "0001534701", + "B": "0000756894", + "CRH": "0000849395", + "VALE": "0000917851", + "CTAS": "0000723254", + "AON": "0000315293", + "CVNA": "0001690820", + "RSG": "0001060391", + "NU": "0001691493", + "WBD": "0001437107", + "CL": "0000021665", + "DASH": "0001792789", + "GM": "0001467858", + "LHX": "0000202058", + "ELV": "0001156039", + "TRP": "0001232384", + "TDG": "0001260221", + "TRV": "0000086312", + "NKE": "0000320187", + "APD": "0000002969", + "ET": "0001276187", + "IMO": "0000049938", + "SRE": "0001032208", + "NSC": "0000702165", + "CNI": "0000016868", + "DLR": "0001297996", + "CIEN": "0000936395", + "COR": "0001140859", + "PCAR": "0000075362", + "APO": "0001858681", + "HOOD": "0001783879", + "WPM": "0001323404", + "FTNT": "0001262039", + "TEL": "0001385157", + "SPG": "0001063761", + "NWG": "0000844150", + "RACE": "0001648416", + "LSEGY": "0001842726", + "LNG": "0000003570", + "TFC": "0000092230", + "RELX": "0000929869", + "BKR": "0001701605", + "EONGY": "0001136808", + "TAK": "0001395064", + "LITE": "0001633978", + "IFNNY": "0001107457", + "MFC": "0001086888", + "O": "0000726728", + "AFL": "0000004977", + "DB": "0001159508", + "CTVA": "0001755672", + "MPLX": "0001552000", + "AZO": "0000866787", + "INFY": "0001067491", + "BDX": "0000010795", + "AJG": "0000354190", + "BMWKY": "0001446250", + "OKE": "0001039684", + "D": "0000715957", + "MPWR": "0001280452", + "FANG": "0001539838", + "TGT": "0000027419", + "ALL": "0000899051", + "FAST": "0000815556", + "GWW": "0000277135", + "ETR": "0000065984", + "TRGP": "0001389170", + "SNOW": "0001640147", + "AED": "0002057673", + "ZTS": "0001555280", + "VST": "0001692819", + "AU": "0001973832", + "EA": "0000712515", + "UI": "0001511737", + "EXC": "0001109357", + "ADSK": "0000769397", + "XEL": "0000072903", + "CAH": "0000721371", + "CVE": "0001475260", + "AME": "0001037868", + "FIX": "0001035983", + "KEYS": "0001601046", + "FNV": "0001456346", + "NDAQ": "0001120193", + "NOK": "0000924613", + "PSA": "0001393311", + "NXPI": "0001413447", + "CCJ": "0001009001", + "ASX": "0001122411", + "SE": "0001703399", + "TER": "0000097210", + "COHR": "0000820318", + "FER": "0001468522", + "FERG": "0002011641", + "EW": "0001099800", + "CSLLY": "0001274152", + "MET": "0001099219", + "CARR": "0001783180", + "F": "0000037996", + "ARGX": "0001697862", + "COIN": "0001679788", + "GALDY": "0002021390", + "URI": "0001067701", + "WDS": "0000844551", + "ABEV": "0001565025", + "GRMN": "0001121788", + "IDXX": "0000874716", + "BSBR": "0001471055", + "KR": "0000056873", + "HLN": "0001900304", + "CMG": "0001058090", + "DAL": "0000027904", + "SCMWY": "0001069336", + "WAB": "0000943452", + "YUM": "0001041061", + "CRWV": "0001769628", + "GWLIF": "0000850918", + "FITB": "0000035527", + "RBLX": "0001315098", + "DDOG": "0001561550", + "GFI": "0001172724", + "EBAY": "0001065088", + "WCN": "0001318220", + "PYPL": "0001633917", + "ALNY": "0001178670", + "RKT": "0001805284", + "HSY": "0000047111", + "ED": "0001047862", + "MSTR": "0001050446", + "ODFL": "0000878927", + "ESLT": "0001027664", + "CCEP": "0001650107", + "JD": "0001549802", + "ROK": "0001024478", + "PEG": "0000788784", + "DEO": "0000835403", + "AIG": "0000005272", + "DHI": "0000882184", + "CBRE": "0001138118", + "MT": "0001243429", + "TYHOY": "0002018139", + "AMP": "0000820027", + "TRI": "0001075124", + "MSCI": "0001408198", + "KBGGY": "0001535759", + "FMX": "0001061736", + "VTR": "0000740260", + "NUE": "0000073309", + "ERIC": "0000717826", + "PCG": "0001004980", + "BBD": "0001160330", + "RKLB": "0001819994", + "PTCAY": "0001547873", + "ROP": "0000882835", + "WEC": "0000783325", + "BE": "0001664703", + "HIG": "0000874766", + "HEI": "0000046619", + "KGC": "0000701818", + "DIA": "0001041130", + "BIDU": "0001329099", + "EQT": "0000033213", + "ALC": "0001167379", + "SATS": "0001415404", + "TTWO": "0000946581", + "CCI": "0001051470", + "LVS": "0001300514", + "LYV": "0001335258", + "VMC": "0001396009", + "NTR": "0001725964", + "PUK": "0001116578", + "FRFHF": "0000915191", + "XYZ": "0001512673", + "GBTC": "0001588489", + "MLM": "0000916076", + "STT": "0000093751", + "VG": "0002007855", + "MDLN": "0002046386", + "KB": "0001445930", + "ONC": "0001651308", + "ADM": "0000007084", + "CCL": "0000815097", + "MCHP": "0000827054", + "CUK": "0001125259", + "ASTS": "0001780312", + "SLF": "0001097362", + "VOD": "0000839923", + "TEVA": "0000818686", + "INSM": "0001104506", + "QSR": "0001618756", + "WDAY": "0001327811", + "CPNG": "0001834584", + "MDY": "0000936958", + "ACGL": "0000947484", + "KDP": "0001418135", + "DLMAY": "0002073893", + "SYY": "0000096021", + "CLS": "0001030894", + "PRU": "0001137774", + "ARES": "0001176948", + "EME": "0000105634", + "VIK": "0001745201", + "AXON": "0001069183", + "CHT": "0001132924", + "TCOM": "0001269238", + "IX": "0001070304", + "PAYX": "0000723531", + "KVUE": "0001944048", + "GELHY": "0001474968", + "RMD": "0000943819", + "HPE": "0001645590", + "A": "0001090872", + "EC": "0001444406", + "NRG": "0001013871", + "CPRT": "0000900075", + "HBAN": "0000049196", + "SYM": "0001837240", + "HAL": "0000045012", + "GEHC": "0001932393", + "KMB": "0000055785", + "HMC": "0000715153", + "CQP": "0001383650", + "MTB": "0000036270", + "ATO": "0000731802", + "CHLSY": "0001885110", + "SHG": "0001263043", + "AEE": "0001002910", + "DTE": "0000936340", + "IR": "0001699150", + "DVN": "0001090012", + "IRM": "0001020569", + "RYAAY": "0001038683", + "TPL": "0001811074", + "STM": "0000932787", + "CBOE": "0001374310", + "OTIS": "0001781335", + "FISV": "0000798354", + "CTSH": "0001058290", + "AMRZ": "0002035989", + "UAL": "0000100517", + "WAT": "0001000697", + "DOW": "0001751788", + "EXR": "0001289490", + "FE": "0001031296", + "VICI": "0001705696", + "XYL": "0001524472", + "NTRA": "0001604821", + "IQV": "0001478242", + "TS": "0001190723", + "PPL": "0000922224", + "FTS": "0001666175", + "TPR": "0001116132", + "TDY": "0001094285", + "JBL": "0000898293", + "CKHGF": "0001469059", + "VEEV": "0001393052", + "CNP": "0001130310", + "FTI": "0001681459", + "FSNUY": "0000904868", + "EIX": "0000827052", + "RPRX": "0001802768", + "RJF": "0000720005", + "CHTR": "0001091667", + "DOV": "0000029905", + "EXPE": "0001324424", + "CASY": "0000726958", + "NBIS": "0001513845", + "WTW": "0001140536", + "BAP": "0001001290", + "KHC": "0001637459", + "AWK": "0001410636", + "NTRS": "0000073124", + "TW": "0001758730", + "BMDPF": "0001002788", + "MTZ": "0000015615", + "DG": "0000029534", + "STZ": "0000016918", + "HUBB": "0000048898", + "CTRA": "0000858470", + "CFG": "0000759944", + "ES": "0000072741", + "STLD": "0001022671", + "SUNB": "0002083785", + "BIIB": "0000875045", + "ROL": "0000084839", + "PHG": "0000313216", + "RDDT": "0001713445", + "RSHGY": "0001447391", + "PBA": "0001546066", + "VIV": "0001066119", + "AXIA": "0001439124", + "TECK": "0000886986", + "FICO": "0000814547", + "VRSK": "0001442145", + "CW": "0000026324", + "LYB": "0001489393", + "MTD": "0001037646", + "FLEX": "0000866374", + "WRB": "0000011544", + "BG": "0001996862", + "ON": "0001097864", + "EL": "0001001250", + "EXE": "0000895126", + "FOXA": "0001754301", + "FTAI": "0001590364", + "UTHR": "0001082554", + "CINF": "0000020286", + "SYF": "0001601712", + "Q": "0002058873", + "ZM": "0001585521", + "DXCM": "0001093557", + "CMS": "0000811156", + "VRSN": "0001014473", + "GFS": "0001709048", + "FIS": "0001136893", + "CRCL": "0001876042", + "MKL": "0001096343", + "ULTA": "0001403568", + "SQM": "0000909037", + "TELNY": "0001126113", + "AER": "0001378789", + "EQR": "0000906107", + "NMR": "0001163653", + "XPO": "0001166003", + "PAAS": "0000771992", + "LPLA": "0001397911", + "AVB": "0000915912", + "OMC": "0000029989", + "PPG": "0000079879", + "TSCO": "0000916365", + "BNTX": "0001776985", + "BCE": "0000718940", + "RF": "0001281761", + "TSN": "0000100493", + "NI": "0001111711", + "LH": "0000920148", + "WIT": "0001123799", + "DRI": "0000940944", + "FCNCA": "0000798941", + "PHM": "0000822416", + "EDPFY": "0001039610", + "SLV": "0001330568", + "BRO": "0000079282", + "SBS": "0001170858", + "WWD": "0000108312", + "KEY": "0000091576", + "ZS": "0001713683", + "RGLD": "0000085535", + "L": "0000060086", + "TSEM": "0000928876", + "DGX": "0001022079", + "UMC": "0001033767", + "EFX": "0000033185", + "CHD": "0000313927", + "FWONA": "0001560385", + "STLA": "0001605484", + "VLTO": "0001967680", + "BEP": "0001533232", + "DLTR": "0000935703", + "SBAC": "0001034054", + "STE": "0001757898", + "HUM": "0000049071", + "WSM": "0000719955", + "LEN": "0000920760", + "RL": "0001037038", + "ALB": "0000915913", + "FSLR": "0001274494", + "KOF": "0000910631", + "PSTG": "0001474432", + "BURL": "0001579298", + "MDB": "0001441816", + "SW": "0002005951", + "CPAY": "0001175454", + "HKHHY": "0001142231", + "NTAP": "0001002047", + "JBHT": "0000728535", + "ROIV": "0001635088", + "SOFI": "0001818874", + "ATI": "0001018963", + "TU": "0000868675", + "LDOS": "0001336920", + "USFD": "0001665918", + "ASBHY": "0002055337", + "FN": "0001408710", + "IHG": "0000858446", + "CF": "0001324404", + "GIS": "0000040704", + "ALAB": "0001736297", + "CHRW": "0001043277", + "TWLO": "0001447669", + "PFG": "0001126328", + "CDE": "0000215466", + "BWXT": "0001486957", + "TROW": "0001113169", + "RVMD": "0001628171", + "FUTU": "0001754581", + "MRNA": "0001682852", + "CRS": "0000017843", + "ILMN": "0001110803", + "EXPD": "0000746515", + "AS": "0001988894", + "LI": "0001791706", + "AGI": "0001178819", + "DIDIY": "0001764757", + "RIVN": "0001874178", + "INCY": "0000879169", + "NVT": "0001720635", + "EVRG": "0001711269", + "DD": "0001666700", + "SNA": "0000091440", + "JBS": "0001791942", + "ZTO": "0001677250", + "RCI": "0000733099", + "AA": "0001675149", + "LNT": "0000352541", + "BR": "0001383312", + "CIB": "0002058897", + "IOT": "0001642896", + "CRDO": "0001807794", + "YPF": "0000904851", + "NVR": "0000906163", + "TLK": "0001001807", + "FLUT": "0001635327", + "IFF": "0000051253", + "LUV": "0000092380", + "AMCR": "0001748790", + "IP": "0000051434", + "BCH": "0001161125", + "WST": "0000105770", + "RBA": "0001046102", + "LULU": "0001397187", + "PKG": "0000075677", + "KEP": "0000887225", + "APG": "0001796209", + "ZBH": "0001136869", + "TEAM": "0001650372", + "TRMOY": "0002071881", + "PR": "0001658566", + "GPN": "0001123360", + "HPQ": "0000047217", + "MTSI": "0001493594", + "FTV": "0001659166", + "ENTG": "0001101302", + "WY": "0000106535", + "PKX": "0000889132", + "VNOM": "0002074176", + "BJGPY": "0002098425", + "ITT": "0000216228", + "RBC": "0001324948", + "YUMC": "0001673358", + "CNC": "0001071739", + "DKS": "0001089063", + "FFIV": "0001048695", + "WTKWY": "0000861967", + "ESS": "0000920522", + "AKAM": "0001086222", + "ULS": "0001901440", + "NXT": "0001852131", + "PHYS": "0001477049", + "BIP": "0001406234", + "GMAB": "0001434265", + "PTC": "0000857005", + "CSGP": "0001057352", + "SOAGY": "0001715801", + "XPEV": "0001810997", + "HOLX": "0000859737", + "RTO": "0000930157", + "CG": "0001527166", + "BEKE": "0001809587", + "WES": "0001423902", + "OVV": "0001792580", + "SSNC": "0001402436", + "THC": "0000070318", + "SUI": "0000912593", + "USO": "0001327068", + "CX": "0001076378", + "WF": "0001264136", + "TKO": "0001973266", + "HTHT": "0001483994", + "GFL": "0001780232", + "RS": "0000861884", + "BALL": "0000009389", + "EMA": "0001127248", + "LII": "0001069202", + "NIO": "0001736541", + "CHKP": "0001015922", + "GIB": "0001061574", + "CDW": "0001402057", + "CLH": "0000822818", + "NPXYY": "0002019040", + "MKSI": "0001049502", + "INVH": "0001687229", + "BSAC": "0001027552", + "PAA": "0001070423", + "HII": "0001501585", + "TOST": "0001650164", + "TRMB": "0000864749", + "VTRS": "0001792044", + "TME": "0001744676", + "AFRM": "0001820953", + "WPC": "0001025378", + "PUGBY": "0002029472", + "MGA": "0000749098", + "NLY": "0001043219", + "TXT": "0000217346", + "SGI": "0001206264", + "APTV": "0001521332", + "WLK": "0001262823", + "KIM": "0000879101", + "RGC": "0001829667", + "LPGCY": "0002068440", + "J": "0000052988", + "WSO": "0000105016", + "PSLV": "0001494728", + "SMMT": "0001599298", + "EWBC": "0001069157", + "MAA": "0000912595", + "TLN": "0001622536", + "YARIY": "0001279956", + "SNX": "0001177394", + "APA": "0001841666", + "GRAB": "0001855612", + "TPG": "0001880661", + "SN": "0001957132", + "NDSN": "0000072331", + "ARNNY": "0001719117", + "TYL": "0000860731", + "JLL": "0001037976", + "LTM": "0001047716", + "ROKU": "0001428439", + "GPC": "0000040987", + "REG": "0000910606", + "PODD": "0001145197", + "DECK": "0000910521", + "OKTA": "0001660134", + "BBIO": "0001743881", + "IEX": "0000832101", + "KSPI": "0001985487", + "MEDP": "0001668397", + "ASND": "0001612042", + "NVMI": "0001109345", + "PAYP": "0002080845", + "NWSA": "0001564708", + "GGG": "0000042888", + "PNR": "0000077360", + "SMCI": "0001375365", + "NYT": "0000071691", + "QXO": "0001236275", + "SNN": "0000845982", + "COO": "0000711404", + "DTM": "0001842022", + "OHI": "0000888491", + "WMG": "0001319161", + "LOGI": "0001032975", + "H": "0001468174", + "CSL": "0000790051", + "BBY": "0000764478", + "WCC": "0000929008", + "RGA": "0000898174", + "TRU": "0001552033", + "CRRFY": "0001078642", + "OWL": "0001823945", + "LECO": "0000059527", + "TIGO": "0000912958", + "HST": "0001070750", + "CNH": "0001567094", + "EG": "0001095073", + "NBIX": "0000914475", + "PFGC": "0001618673", + "AVY": "0000008818", + "PNFP": "0002082866", + "MKC": "0000063754", + "DSEEY": "0001481045", + "RNR": "0000913144", + "ERIE": "0000922621", + "UDR": "0000074208", + "LSCC": "0000855658", + "FIVE": "0001177609", + "ARCC": "0001287750", + "PEN": "0001321732", + "COKE": "0000317540", + "LAMR": "0001090425", + "FMS": "0001333141", + "HUBS": "0001404655", + "TOL": "0000794170", + "HL": "0000719413", + "BJ": "0001531152", + "ELS": "0000895417", + "GWRE": "0001528396", + "STRL": "0000874238", + "PAC": "0001347557", + "CACI": "0000016058", + "HAS": "0000046080", + "AEIS": "0000927003", + "TIMB": "0001826168", + "GLPI": "0001575965", + "KTOS": "0001069258", + "RPM": "0000110621", + "MDGL": "0001157601", + "CNA": "0000021175", + "AR": "0001433270", + "DPZ": "0001286681", + "BF-A": "0000014693", + "PL": "0001836833", + "PNW": "0000764622", + "UNM": "0000005513", + "FNF": "0001331875", + "IONS": "0000874015", + "UUGRY": "0001440130", + "CLX": "0000021076", + "DRS": "0001833756", + "ALLY": "0000040729", + "GH": "0001576280", + "MLI": "0000089439", + "LYTHF": "0001816319", + "RRX": "0000082811", + "ALGN": "0001097149", + "BEN": "0000038777", + "SUN": "0001552275", + "SUZ": "0000909327", + "HRL": "0000048465", + "ALLE": "0001579241", + "SOLS": "0002064953", + "PINS": "0001506293", + "EVR": "0001360901", + "AMH": "0001562401", + "SCI": "0000089089", + "MAS": "0000062996", + "VARRY": "0001919275", + "GMED": "0001237831", + "EXEL": "0000939767", + "CONE": "0002103884", + "GEN": "0000849399", + "WTRG": "0000078128", + "CCK": "0001219601", + "CRBG": "0001889539", + "MOD": "0000067347", + "AMKR": "0001047127", + "IREN": "0001878848", + "BNT": "0001837429", + "EQX": "0001756607", + "JAZZ": "0001232524", + "DOC": "0000765880", + "DKNG": "0001883685", + "ELAN": "0001739104", + "SF": "0000720672", + "ENSG": "0001125376", + "AGNC": "0001423689", + "JKHY": "0000779152", + "SKM": "0001015650", + "GNRC": "0001474735", + "IT": "0000749251", + "DT": "0001773383", + "KRMN": "0002040127", + "IAG": "0001203464", + "WBS": "0000801337", + "GL": "0000320335", + "FHN": "0000036966", + "CHWY": "0001766502", + "ARMK": "0001584509", + "EMBJ": "0001355444", + "SFD": "0000091388", + "AEG": "0000769218", + "DINO": "0001915657", + "RDY": "0001135951", + "NTNX": "0001618732", + "FIG": "0001579878", + "GDDY": "0001609711", + "SOLV": "0001964738", + "ACM": "0000868857", + "BWA": "0000908255", + "ONON": "0001858985", + "AIZ": "0001267238", + "AM": "0001623925", + "AFG": "0001042046", + "UHS": "0000352915", + "TXRH": "0001289460", + "JHX": "0001159152", + "IONQ": "0001824920", + "AG": "0001308648", + "KAIKY": "0001447126", + "WMS": "0001604028", + "ONTO": "0000704532", + "IVZ": "0000914208", + "OBICY": "0002077146", + "BMRN": "0001048477", + "SWK": "0000093556", + "WYNN": "0001174922", + "EQH": "0001333986", + "VFS": "0001913510", + "PSKY": "0002041610", + "BPYPP": "0001545772", + "CPT": "0000906345", + "BSY": "0001031308", + "TTD": "0001671933", + "ASR": "0001123452", + "GME": "0001326380", + "DLAKY": "0001049724", + "DY": "0000067215", + "RBRK": "0001943896", + "KT": "0000892450", + "RRC": "0000315852", + "ZBRA": "0000877212", + "DAR": "0000916540", + "BAH": "0001443646", + "AES": "0000874761", + "SJM": "0000091419", + "CART": "0001579091", + "HMY": "0001023514", + "TTMI": "0001116942", + "GIL": "0001061894", + "AIT": "0000109563", + "RMBS": "0000917273", + "OGE": "0001021635", + "EGP": "0000049600", + "BLD": "0001633931", + "MGM": "0000789570", + "GSAT": "0001366868", + "CNM": "0001856525", + "RVTY": "0000031791", + "STN": "0001131383", + "U": "0001810806", + "VIRT": "0001592386", + "ORI": "0000074260", + "GTLS": "0000892553", + "DCI": "0000029644", + "HLI": "0001302215", + "SPXC": "0000088205", + "ZG": "0001617640", + "PAG": "0001019849", + "EHC": "0000785161", + "ENLT": "0001922641", + "BILI": "0001723690", + "DVA": "0000927066", + "ALSN": "0001411207", + "CR": "0001944013", + "BZLFY": "0001072397", + "WTS": "0000795403", + "XP": "0001787425", + "IESC": "0001048268", + "MASI": "0000937556", + "ACI": "0001646972", + "FLS": "0000030625", + "KNX": "0001492691", + "W": "0001616707", + "SAIA": "0001177702", + "SSB": "0000764038", + "SEIC": "0000350894", + "EDU": "0001372920", + "DOCU": "0001261333", + "WTFC": "0001015328", + "ABVX": "0001956827", + "DOCN": "0001582961", + "AVAV": "0001368622", + "MUSA": "0001573516", + "FRT": "0000034903", + "FRHC": "0000924805", + "CAVA": "0001639438", + "BVN": "0001013131", + "OSK": "0000775158", + "ADC": "0000917251", + "TFII": "0001588823", + "MOG-A": "0000067887", + "ELPC": "0001041792", + "FPS": "0002080126", + "BXP": "0001037540", + "GAP": "0000039911", + "SITM": "0001451809", + "SNROY": "0001584273", + "CEF": "0001726122", + "NCLTY": "0001801729", + "AHR": "0001632970", + "SBSW": "0001786909", + "TTC": "0000737758", + "PCOR": "0001611052", + "UHAL": "0000004457", + "NFG": "0000070145", + "DDS": "0000028917", + "LKNCY": "0001767582", + "BPOP": "0000763901", + "AOS": "0000091142", + "ICLR": "0001060955", + "PPC": "0000802481", + "BRX": "0001581068", + "LLYVA": "0002078416", + "BMNR": "0001829311", + "RYAN": "0001849253", + "MP": "0001801368", + "MICC": "0002071668", + "FCFS": "0000840489", + "PMDIY": "0002013003", + "CELH": "0001341766", + "UMBF": "0000101382", + "CFR": "0000039263", + "BLDR": "0001316835", + "SARO": "0002025410", + "LFUS": "0000889331", + "HSIC": "0001000228", + "OC": "0001370946", + "ONB": "0000707179", + "PRAX": "0001689548", + "NCLH": "0001513761", + "AXSM": "0001579428", + "BAX": "0000010456", + "ZION": "0000109380", + "HBM": "0001322422", + "YMM": "0001838413", + "EMN": "0000915389", + "CRL": "0001100682", + "CTRE": "0001590717", + "ARWR": "0000879407", + "SPIIY": "0002083221", + "VIAV": "0000912093", + "CUBE": "0001298675", + "FDS": "0001013237", + "JEF": "0000096223", + "CAE": "0001173382", + "GWKSY": "0002062522", + "PCVX": "0001649094", + "TEM": "0001717115", + "QGEN": "0001015820", + "SOTGY": "0001601992", + "OKLO": "0001849056", + "JOBY": "0001819848", + "TECH": "0000842023", + "MOS": "0001285785", + "ESI": "0001590714", + "SWKS": "0000004127", + "AGCO": "0000880266", + "TAP": "0000024545", + "NUVL": "0001861560", + "BROS": "0001866581", + "CWEN": "0001567683", + "BTSG": "0001865782", + "CYTK": "0001061983", + "CGNX": "0000851205", + "LINE": "0001868159", + "COLB": "0000887343", + "PSO": "0000938323", + "FRO": "0000913290", + "NNN": "0000751364", + "R": "0000085961", + "ATR": "0000896622", + "MANH": "0001056696", + "TTEK": "0000831641", + "AUR": "0001828108", + "HESM": "0001789832", + "AYI": "0001144215", + "CHRD": "0001486159", + "AAOI": "0001158114", + "IDCC": "0001405495", + "FORM": "0001039399", + "PRI": "0001475922", + "KNSL": "0001669162", + "AGX": "0000100591", + "FR": "0000921825", + "PRIM": "0001361538", + "SIRI": "0000908937", + "GDS": "0001526125", + "FNMA": "0000310522", + "NE": "0001895262", + "JHG": "0001274173", + "WAL": "0001212545", + "SSL": "0000314590", + "IDA": "0001057877", + "UGI": "0000884614", + "REXR": "0001571283", + "ALV": "0001034670", + "VMI": "0000102729", + "AXS": "0001214816", + "SNAP": "0001564408", + "CIG": "0001157557", + "TX": "0001342874", + "MTDR": "0001520006", + "BOKF": "0000875357", + "MSGS": "0001636519", + "NXE": "0001698535", + "GGAL": "0001114700", + "SMTC": "0000088941", + "HALO": "0001159036", + "KRYS": "0001711279", + "EPAM": "0001352010", + "PDI": "0001510599", + "OR": "0001627272", + "VIST": "0001762506", + "ESE": "0000866706", + "BIO": "0000012208", + "SFM": "0001575515", + "ZWS": "0001439288", + "IBRX": "0001326110", + "CAG": "0000023217", + "CRUS": "0000772406", + "ARE": "0001035443", + "GGB": "0001073404", + "AMG": "0001004434", + "FIGR": "0002064124", + "POOL": "0000945841", + "ARW": "0000007536", + "BEPC": "0001791863", + "TFPM": "0001829726", + "MTCH": "0000891103", + "VIPS": "0001529192", + "CHYM": "0001795586", + "LEVI": "0000094845", + "CBSH": "0000022356", + "LBRDA": "0001611983", + "CAMT": "0001109138", + "AUGO": "0001468642", + "SAIL": "0002030781", + "JXN": "0001822993", + "SM": "0000893538", + "QRVO": "0001604778", + "VSAT": "0000797721", + "KEX": "0000056047", + "AL": "0001487712", + "RIG": "0001451505", + "MOH": "0001179929", + "IBP": "0001580905", + "HQY": "0001428336", + "PEGA": "0001013857", + "LKQ": "0001065696", + "DOX": "0001062579", + "CE": "0001306830", + "LUMN": "0000018926", + "INGR": "0001046257", + "AAL": "0000006201", + "STAG": "0001479094", + "AWI": "0000007431", + "CWAN": "0001866368", + "SANM": "0000897723", + "EGO": "0000918608", + "SHMXY": "0001648512", + "VICR": "0000751978", + "RCWLY": "0001969729", + "KYMR": "0001815442", + "SOBO": "0002019061", + "MINBY": "0001034983", + "ORA": "0001296445", + "VLY": "0000714310", + "YOU": "0001856314", + "FLR": "0001124198", + "TKR": "0000098362", + "SLAB": "0001038074", + "GLXY": "0001859392", + "SSD": "0000920371", + "NICE": "0001003935", + "LOTMY": "0002041918", + "APLD": "0001144879", + "AN": "0000350698", + "CMC": "0000022444", + "NOV": "0001021860", + "MORN": "0001289419", + "WFRD": "0001603923", + "QMMM": "0001971542", + "TAL": "0001499620", + "PB": "0001068851", + "PRMB": "0002042694", + "VAL": "0000314808", + "PAYC": "0001590955", + "GRFS": "0001438569", + "ICL": "0000941221", + "CAR": "0000723612", + "ACLX": "0001786205", + "BLTE": "0001889109", + "TEX": "0000097216", + "MIDD": "0000769520", + "FSS": "0000277509", + "UEC": "0001334933", + "CMS-PB": "0000201533", + "POWL": "0000080420", + "AAON": "0000824142", + "SNEX": "0000913760", + "LGN": "0002052568", + "RGEN": "0000730272", + "LNC": "0000059558", + "PTGX": "0001377121", + "TRNO": "0001476150", + "VFC": "0000103379", + "AMTM": "0002011286", + "CPB": "0000016732", + "GKOS": "0001192448", + "STWD": "0001465128", + "ENS": "0001289308", + "TKMTY": "0002044863", + "BZ": "0001842827", + "JBTM": "0001433660", + "EPRT": "0001728951", + "SSRM": "0000921638", + "SWX": "0001692115", + "EAT": "0000703351", + "FSV": "0001637810", + "RYN": "0000052827", + "G": "0001398659", + "TXNM": "0001108426", + "MSA": "0000066570", + "VOYA": "0001535929", + "MKTX": "0001278021", + "BIRK": "0001977102", + "OMF": "0001584207", + "UELMO": "0000100826", + "BTG": "0001429937", + "ECG": "0002015845", + "BYD": "0000906553", + "WULF": "0001083301", + "LEA": "0000842162", + "HXL": "0000717605", + "APGE": "0001974640", + "JAN": "0002100805", + "MBLY": "0001910139", + "POR": "0000784977", + "CHDN": "0000020212", + "SEE": "0001012100", + "THG": "0000944695", + "CENX": "0000949157", + "HR": "0001360604", + "GATX": "0000040211", + "WH": "0001722684", + "DSGX": "0001050140", + "CNTA": "0001847903", + "SFGYY": "0002084022", + "GXO": "0001852244", + "TERN": "0001831363", + "AROC": "0001389050", + "KMX": "0001170010", + "FROG": "0001800667", + "ALGM": "0000866291", + "PSN": "0000275880", + "EXP": "0000918646", + "FNB": "0000037808", + "MWH": "0002065636", + "LTH": "0001869198", + "PATH": "0001734722", + "CRC": "0001609253", + "UGP": "0001094972", + "TTAN": "0001638826", + "ESAB": "0001877322", + "ROAD": "0001718227", + "MHK": "0000851968", + "NEU": "0001282637", + "UWMC": "0001783398", + "FAF": "0001472787", + "MGY": "0001698990", + "GBCI": "0000868671", + "DLB": "0001308547", + "RYTM": "0001649904", + "MUR": "0000717423", + "MBRFY": "0001496919", + "LAD": "0001023128", + "STEP": "0001796022", + "PLNT": "0001637207", + "DBX": "0001467623", + "BLCO": "0001860742", + "RHP": "0001040829", + "ACT": "0001823529", + "OLLI": "0001639300", + "UBSI": "0000729986", + "KVYO": "0001835830", + "INGM": "0001897762", + "ALKS": "0001520262", + "ORLA": "0001680056", + "URBN": "0000912615", + "CBC": "0002065601", + "PCTY": "0001591698", + "NSA": "0001618563", + "MTG": "0000876437", + "SRRK": "0001727196", + "CRK": "0000023194", + "OTEX": "0001002638", + "AXTA": "0001616862", + "COGT": "0001622229", + "CGON": "0001991792", + "GTES": "0001718512", + "MIRM": "0001759425", + "FCN": "0000887936", + "RRR": "0001653653", + "SEB": "0000088121", + "APPF": "0001433195", + "ENIC": "0001659939", + "NJR": "0000356309", + "SITE": "0001650729", + "OMAB": "0001378239", + "GLNG": "0001207179", + "PTCT": "0001070081", + "FLG": "0000910073", + "PAGP": "0001581990", + "BRKR": "0001109354", + "ESNT": "0001448893", + "TMHC": "0001562476", + "IFS": "0001615903", + "OGS": "0001587732", + "PJT": "0001626115", + "LSTR": "0000853816", + "PLXS": "0000785786", + "OBDC": "0001655888", + "PIPR": "0001230245", + "CWST": "0000911177", + "ERAS": "0001761918", + "PNDRY": "0001505880", + "BXSL": "0001736035", + "BCPC": "0000009326", + "CNX": "0001070412", + "LB": "0001995807", + "GOLF": "0001672013", + "CIGI": "0000913353", + "HOMB": "0001331520", + "SR": "0001126956", + "TGS": "0000931427", + "NXST": "0001142417", + "LW": "0001679273", + "BLSH": "0001872195", + "KRG": "0001286043", + "CAI": "0002019410", + "CELC": "0001603454", + "ADT": "0001703056", + "XENE": "0001582313", + "CZR": "0001590895", + "VSNT": "0002067876", + "SON": "0000091767", + "EQPT": "0001693736", + "AVTR": "0001722482", + "BKH": "0001130464", + "WTM": "0000776867", + "OTF": "0001747777", + "SGHC": "0001878057", + "CHE": "0000019584", + "NPO": "0001164863", + "ABCB": "0000351569", + "TGTX": "0001001316", + "RITM": "0001556593", + "DOO": "0001748797", + "RLI": "0000084246", + "LOAR": "0002000178", + "ESTC": "0001707753", + "HUT": "0001964789", + "PBF": "0001534504", + "LYFT": "0001759509", + "CNR": "0001710366", + "WEX": "0001309108", + "GVA": "0000861459", + "QBTS": "0001907982", + "GLBE": "0001835963", + "VNO": "0000899689", + "ACA": "0001739445", + "RSI": "0001793659", + "FLY": "0001860160", + "MAC": "0000912242", + "HLNE": "0001433642", + "HWC": "0000750577", + "COMP": "0001563190", + "TKC": "0001071321", + "REZI": "0001740332", + "POST": "0001530950", + "TFX": "0000096943", + "PECO": "0001476204", + "SEI": "0001697500", + "CIFR": "0001819989", + "VSEC": "0000102752", + "AVAL": "0001504764", + "MATX": "0000003453", + "OZK": "0001569650", + "APLS": "0001492422", + "AUB": "0000883948", + "UFPI": "0000912767", + "VNT": "0001786842", + "FND": "0001507079", + "CORZ": "0001839341", + "KGS": "0001767042", + "WFG": "0001402388", + "TDS": "0001051512", + "ETSY": "0001370637", + "FSLY": "0001517413", + "AVT": "0000008858", + "TEO": "0000932470", + "RUSHA": "0001012019", + "PACS": "0002001184", + "ST": "0001477294", + "ATAT": "0001853717", + "MSM": "0001003078", + "KLAR": "0002003292", + "GPGI": "0001823144", + "SRAD": "0001836470", + "HCC": "0001691303", + "SBRA": "0001492298", + "MNSO": "0001815846", + "IMVT": "0001764013", + "EMAT": "0001866226", + "LNTH": "0001521036", + "BMA": "0001347426", + "LPX": "0000060519", + "BTDPY": "0001516324", + "IEP": "0000813762", + "BIPC": "0001788348", + "EXLS": "0001297989", + "ASB": "0000007789", + "PAM": "0001469395", + "MCY": "0000064996", + "RIOT": "0001167419", + "AX": "0001299709", + "SIM": "0000887153", + "KBR": "0001357615", + "AQN": "0001174169", + "SLFPY": "0001370418", + "IPGP": "0001111928", + "CHH": "0001046311", + "LOPE": "0001434588", + "CLF": "0000764065", + "LAUR": "0000912766", + "WIX": "0001576789", + "BC": "0000014930", + "OUT": "0001579877", + "MIR": "0001809987", + "HASI": "0001561894", + "HAPVY": "0001869666", + "CRSP": "0001674416", + "MAIN": "0001396440", + "BFAM": "0001437578", + "SNDR": "0001692063", + "RAL": "0002041385", + "BGC": "0001094831", + "CPA": "0001345105", + "RGTI": "0001838359", + "GNTX": "0000355811", + "ATMU": "0001921963", + "PFSI": "0001745916", + "M": "0000794367", + "PSMT": "0001041803", + "LMND": "0001691421", + "MTN": "0000812011", + "NNI": "0001258602", + "UNF": "0000717954", + "MEOH": "0000886977", + "GHC": "0000104889", + "ONDS": "0001646188", + "SIGI": "0000230557", + "CACC": "0000885550", + "MRP": "0002017206", + "RDN": "0000890926", + "PHI": "0000078150", + "ENPH": "0001463101", + "BMI": "0000009092", + "LBRT": "0001694028", + "DNTH": "0001690585", + "OSIS": "0001039065", + "WAY": "0001990354", + "OPEN": "0001801169", + "S": "0001583708", + "FOLD": "0001178879", + "DUOL": "0001562088", + "BDC": "0000913142", + "CORT": "0001088856", + "SAIC": "0001571123", + "SPHR": "0001795250", + "ADOOY": "0001489079", + "FBIN": "0001519751", + "EBC": "0001810546", + "MAT": "0000063276", + "REYN": "0001786431", + "MRCY": "0001049521", + "KEN": "0001611005", + "TNL": "0001361658", + "MYRG": "0000700923", + "CRGY": "0001866175", + "CSW": "0001624794", + "NWSGY": "0001449664", + "FHI": "0001056288", + "MTH": "0000833079", + "FOUR": "0001794669", + "AIR": "0000001750", + "HIMS": "0001773751", + "OPCH": "0001014739", + "MDU": "0000067716", + "CROX": "0001334036", + "ALH": "0001317685", + "ALM": "0001670061", + "AKO-A": "0000925261", + "MWA": "0001350593", + "FFIN": "0000036029", + "UUUU": "0001385849", + "SLM": "0001032033", + "DOCS": "0001516513", + "CVSA": "0000730464", + "ALK": "0000766421", + "OLED": "0001005284", + "ACIW": "0000935036", + "SHC": "0001822479", + "BCO": "0000078890", + "RDNT": "0000790526", + "NVST": "0001757073", + "VVV": "0001674910", + "TCBI": "0001077428", + "WING": "0001636222", + "MAUTF": "0001830918", + "ANF": "0001018840", + "VISN": "0001517228", + "IBOC": "0000315709", + "CAAP": "0001717393", + "KNF": "0001955520", + "TDW": "0000098222", + "NOVT": "0001076930", + "TBBB": "0001978954", + "MC": "0001596967", + "SLGN": "0000849869", + "GPI": "0001031203", + "NWE": "0001993004", + "AD": "0000821130", + "SKY": "0000090896", + "IFHLY": "0002035057", + "BOOT": "0001610250", + "FELE": "0000038725", + "NGXXF": "0002044153", + "LBTYA": "0001570585", + "CSAN": "0001430162", + "BTU": "0001064728", + "THO": "0000730263", + "TPC": "0000077543", + "HRB": "0000012659", + "ACHR": "0001824502", + "KC": "0001795589", + "ERELY": "0001454144", + "VCTR": "0001570827", + "NHI": "0000877860", + "PTEN": "0000889900", + "MMSI": "0000856982", + "VKTX": "0001607678", + "TFSL": "0001381668", + "LPL": "0001290109", + "USAC": "0001522727", + "TAC": "0001144800", + "HAFN": "0001815779", + "GPOR": "0000874499", + "PONY": "0001969302", + "SFBS": "0001430723", + "ARIS": "0001964504", + "AMRX": "0001723128", + "NG": "0001173420", + "TPH": "0001561680", + "LGND": "0000886163", + "CBT": "0000016040", + "SKT": "0000899715", + "STNG": "0001483934", + "FULT": "0000700564", + "LAZ": "0001311370", + "MMED": "0002062583", + "LRN": "0001157408", + "ITRI": "0000780571", + "SXT": "0000310142", + "AAUC": "0001993344", + "FMCC": "0001026214", + "EPR": "0001045450", + "CRNX": "0001658247", + "QS": "0001811414", + "MZTI": "0000057515", + "NEXHY": "0001985406", + "USLM": "0000082020", + "ZETA": "0001851003", + "CNO": "0001224608", + "DNP": "0000806628", + "SIMO": "0001329394", + "BILL": "0001786352", + "EBOSY": "0001533082", + "FTDR": "0001727263", + "GTLB": "0001653482", + "UCB": "0000857855", + "CCC": "0001818201", + "KTB": "0001760965", + "ALHC": "0001832466", + "ASO": "0001817358", + "PRM": "0001880319", + "LUNR": "0001844452", + "GEF": "0000043920", + "SHAK": "0001620533", + "BRC": "0000746598", + "INDV": "0001625297", + "PATK": "0000076605", + "CSTM": "0001563411", + "BBWI": "0000701985", + "AZZ": "0000008947", + "NAMS": "0001936258", + "DLO": "0001846832", + "MMYT": "0001495153", + "GPCR": "0001888886", + "ACAD": "0001070494", + "IRTC": "0001388658", + "CUZ": "0000025232", + "SKE": "0001713748", + "JOE": "0000745308", + "INDB": "0000776901", + "HGTY": "0001840776", + "ABG": "0001144980", + "STVN": "0001849853", + "NMRK": "0001690680", + "HHH": "0001981792", + "CVCO": "0000278166", + "CMBT": "0001604481", + "SYRE": "0001636282", + "KNSA": "0001730430", + "EE": "0001888447", + "INSW": "0001679049", + "MIAX": "0001438472", + "BNL": "0001424182", + "CALM": "0000016160", + "OTTR": "0001466593", + "MDA": "0001857047", + "PVH": "0000078239", + "SMG": "0000825542", + "VSCO": "0001856437", + "SKYW": "0000793733", + "TREX": "0001069878", + "BETA": "0001784570", + "IRT": "0001466085", + "PPTA": "0001526243", + "DAN": "0000026780", + "BANF": "0000760498", + "CGAU": "0001854640", + "BLLN": "0002070849", + "ELF": "0001600033", + "AGO": "0001273813", + "UTG": "0001263994", + "SII": "0001512920", + "NTSK": "0002063196", + "WSFS": "0000828944", + "ARLP": "0001086600", + "CDP": "0000860546", + "LEU": "0001065059", + "GTX": "0001735707", + "YSS": "0002086587", + "EWTX": "0001710072", + "WHR": "0000106640", + "AB": "0000825313", + "OSCR": "0001568651", + "OII": "0000073756", + "LEGN": "0001801198", + "FG": "0001934850", + "TCGL": "0002047190", + "CVLT": "0001169561", + "MNDY": "0001845338", + "HPHTY": "0001600928", + "CLBT": "0001854587", + "LIVN": "0001639691", + "RNST": "0000715072", + "STNE": "0001745431", + "USAR": "0001970622", + "HP": "0000046765", + "NP": "0002067129", + "INTR": "0001864163", + "BGSI": "0002091467", + "TMDX": "0001756262", + "SIG": "0000832988", + "IRDM": "0001418819", + "WPP": "0000806968", + "CATY": "0000861842", + "BOX": "0001372612", + "CNK": "0001385280", + "ENVA": "0001529864", + "BKU": "0001504008", + "BHF": "0001685040", + "WK": "0001445305", + "BBAR": "0000913059", + "KRC": "0001025996", + "FBP": "0001057706", + "MMS": "0001032220", + "AVA": "0000104918", + "NEA": "0001195737", + "NIQ": "0002054696", + "FIBK": "0000860413", + "KAI": "0000886346", + "RELY": "0001782170", + "PLUG": "0001093691", + "LASR": "0001124796", + "KLIC": "0000056978", + "GNW": "0001276520", + "GBDC": "0001476765", + "WSBC": "0000203596", + "PS": "0002026053", + "BFH": "0001101215", + "GFF": "0000050725", + "EXPO": "0000851520", + "LQDA": "0001819576", + "BKD": "0001332349", + "MARA": "0001507605", + "KFY": "0000056679", + "MCHB": "0001518715", + "DNN": "0001063259", + "FUL": "0000039368", + "HGV": "0001674168", + "WHD": "0001699136", + "ANDG": "0002065708", + "FRMI": "0002071778", + "VEON": "0001468091", + "COLD": "0001455863", + "HYMC": "0001718405", + "DNLI": "0001714899", + "DBC": "0001328237", + "BTE": "0001279495", + "LCID": "0001811210", + "OLN": "0000074303", + "LIF": "0001581760", + "HSAI": "0001861737", + "SA": "0001231346", + "RNG": "0001384905", + "CC": "0001627223", + "SMR": "0001822966", + "NATL": "0001974138", + "PLBL": "0002035697", + "CNS": "0001284812", + "AVNT": "0001122976", + "PARR": "0000821483", + "PLMR": "0001761312", + "TR": "0000098677", + "KBH": "0000795266", + "CVI": "0001376139", + "NIC": "0001174850", + "CARG": "0001494259", + "DIOD": "0000029002", + "MHO": "0000799292", + "PAY": "0001841156", + "ZIM": "0001654126", + "QLYS": "0001107843", + "HWKN": "0000046250", + "RUN": "0001469367", + "WSC": "0001647088", + "FSM": "0001341335", + "FIZZ": "0000069891", + "BXMT": "0001061630", + "MRX": "0001997464", + "OPLN": "0001395942", + "SUNC": "0002089661", + "PTXKY": "0001545057", + "CBU": "0000723188", + "SXI": "0000310354", + "AAP": "0001158449", + "BSM": "0001621434", + "BATRA": "0001958140", + "DYN": "0001818794", + "CPK": "0000019745", + "MTRN": "0001104657", + "TLX": "0002007191", + "HYPMY": "0001486749", + "TNGX": "0001819133", + "DORM": "0000868780", + "IAC": "0001800227", + "TWST": "0001581280", + "FHB": "0000036377", + "HNGE": "0001673743", + "PII": "0000931015", + "ICUI": "0000883984", + "ITGR": "0001114483", + "CLMT": "0002013745", + "CALX": "0001406666", + "HRI": "0001364479", + "PI": "0001114995", + "KD": "0001867072", + "CPRX": "0001369568", + "AWR": "0001056903", + "BKV": "0001838406", + "COPR": "0001263364", + "DBRG": "0001679688", + "HG": "0001593275", + "KNTK": "0001692787", + "CTRI": "0001981599", + "DHT": "0001331284", + "NAVN": "0001639723", + "TRMD": "0001655891", + "SBCF": "0000730708", + "TARS": "0001819790", + "JOYY": "0001530238", + "LCII": "0000763744", + "QTWO": "0001410384", + "ARX": "0001997350", + "PRK": "0000805676", + "ALMS": "0001847367", + "BOH": "0000046195", + "MANU": "0001549107", + "NOG": "0001104485", + "FSK": "0001422183", + "SEDG": "0001419612", + "FFBC": "0000708955", + "AXTI": "0001051627", + "COLM": "0001050797", + "ARQT": "0001787306", + "ERO": "0001853860", + "ACLS": "0001113232", + "UTF": "0001275617", + "VERA": "0001831828", + "FRPT": "0001611647", + "GBTG": "0001820872", + "POWI": "0000833640", + "SUPN": "0001356576", + "HAYW": "0001834622", + "IPAR": "0000822663", + "CWK": "0001628369", + "SYNA": "0000817720", + "PAGS": "0001712807", + "MGEE": "0001161728", + "RCUS": "0001724521", + "VTMX": "0001969373", + "IDYA": "0001676725", + "UCTT": "0001275014", + "SOUN": "0001840856", + "GPK": "0001408075", + "NMIH": "0001547903", + "FBK": "0001649749", + "TXG": "0001770787", + "MSGE": "0001952073", + "UE": "0001611547", + "SDRL": "0001737706", + "GRBK": "0001373670", + "JPC": "0001216583", + "ZGN": "0001877787", + "WRD": "0001867729", + "SFNC": "0000090498", + "EXK": "0001277866", + "TVTX": "0001438533", + "AEO": "0000919012", + "CSQ": "0001275214", + "LION": "0002052959", + "CRVL": "0000874866", + "WDFC": "0000105132", + "MPT": "0001287865", + "HCM": "0001648257", + "RLX": "0001828365", + "PFS": "0001178970", + "TTAM": "0002035304", + "IHS": "0001876183", + "ADEA": "0001803696", + "DBD": "0000028823", + "SBLK": "0001386716", + "WU": "0001365135", + "CURB": "0002027317", + "ATS": "0001394832", + "CWT": "0001035201", + "CAKE": "0000887596", + "COCO": "0001482981", + "YETI": "0001670592", + "AKR": "0000899629", + "ADX": "0000002230", + "DRD": "0001023512", + "KMT": "0000055242", + "SLG": "0001040971", + "HTGC": "0001280784", + "UNFI": "0001020859", + "APLE": "0001418121", + "LXP": "0000910108", + "BANC": "0001169770", + "NAD": "0001083839", + "EXG": "0001379438", + "EEFT": "0001029199", + "DK": "0001694426", + "AMR": "0001704715", + "DKL": "0001552797", + "CON": "0002014596", + "BRZE": "0001676238", + "CVBF": "0000354647", + "NVG": "0001090116", + "BWLP": "0001649313", + "TNK": "0001419945", + "ACMR": "0001680062", + "TALO": "0001724965", + "HAE": "0000313143", + "VRNS": "0001361113", + "MGRC": "0000752714", + "TRN": "0000099780", + "ORKA": "0000907654", + "HE": "0000354707", + "PHIN": "0001968915", + "SHTPY": "0002018852", + "SMSEY": "0001560968", + "CEPU": "0001717161", + "BCC": "0001328581", + "PRVA": "0001759655", + "MH": "0001951070", + "AAPG": "0002023311", + "FCPT": "0001650132", + "DX": "0000826675", + "SPNT": "0001576018", + "WOR": "0000108516", + "PTY": "0001190935", + "APAM": "0001517302", + "RHI": "0000315213", + "SAM": "0000949870", + "BKE": "0000885245", + "VCYT": "0001384101", + "CALY": "0000837465", + "DJT": "0001849635", + "BBT": "0001108134", + "NHC": "0001047335", + "PBH": "0001295947", + "VSH": "0000103730", + "BULL": "0001866364", + "BEAM": "0001745999", + "DRSHF": "0001671541", + "NGVT": "0001653477", + "UPST": "0001647639", + "TRMK": "0000036146", + "HPP": "0001482512", + "ETOR": "0001493318", + "ANDE": "0000821026", + "FRME": "0000712534", + "TMC": "0001798562", + "PTRN": "0001811935", + "BMRRY": "0001671235", + "VC": "0001111335", + "ATRO": "0000008063", + "ASH": "0001674862", + "IRON": "0001816736", + "WRBY": "0001504776", + "KOD": "0001468748", + "SHOO": "0000913241", + "HTO": "0000766829", + "GEO": "0000923796", + "LMAT": "0001158895", + "IMNM": "0001472012", + "UNIT": "0002020795", + "HOG": "0000793952", + "SMA": "0001585389", + "RXO": "0001929561", + "EFXT": "0001904856", + "FLNC": "0001868941", + "AMBP": "0001845097", + "GRDN": "0001802255", + "TBBK": "0001295401", + "TSCFY": "0001555815", + "FIGS": "0001846576", + "SRPT": "0000873303", + "TGB": "0000878518", + "WAFD": "0000936528", + "SVM": "0001340677", + "GDV": "0001260729", + "LFST": "0001845257", + "PRDO": "0001046568", + "BBUC": "0001654795", + "CUBI": "0001488813", + "PLAB": "0000810136", + "TDC": "0000816761", + "HIW": "0000921082", + "AYR": "0001362988", + "OSW": "0001758488", + "UAA": "0001336917", + "NZF": "0001137887", + "IVT": "0001307748", + "BELFA": "0000729580", + "GOF": "0001380936", + "MNR": "0001980088", + "FRSH": "0001544522", + "KYIV": "0002062440", + "BRSL": "0001619762", + "CHEF": "0001517175", + "HNI": "0000048287", + "KYN": "0001293613", + "FMCXF": "0001105122", + "NTCT": "0001078075", + "AEBZY": "0001174511", + "XRAY": "0000818479", + "ELVN": "0001672619", + "CDLR": "0001978867", + "FBNC": "0000811589", + "VRRM": "0001682745", + "VAC": "0001524358", + "MLCO": "0001381640", + "CXT": "0000025445", + "ZLAB": "0001704292", + "TMTNY": "0002072098", + "STUB": "0001337634", + "DAVE": "0001841408", + "MCW": "0001853513", + "INFQ": "0002007825", + "CSGS": "0001005757", + "NESR": "0001698514", + "ADPT": "0001478320", + "NWN": "0001733998", + "BTDR": "0001899123", + "ABM": "0000771497", + "SOC": "0001831481", + "ARCB": "0000894405", + "BCRX": "0000882796", + "GRAL": "0001699031", + "NBTB": "0000790359", + "MANE": "0001827635", + "DNOW": "0001599617", + "PAHC": "0001069899", + "GRND": "0001820144", + "CLSK": "0000827876", + "DXPE": "0001020710", + "HUN": "0001307954", + "NN": "0001865631", + "RLAY": "0001812364", + "SLDE": "0001886428", + "HUBG": "0000940942", + "CENT": "0000887733", + "HLIO": "0001024795", + "MLYS": "0001933414", + "FMC": "0000037785", + "SNDX": "0001395937", + "CECO": "0000003197", + "ETY": "0001340736", + "DAWN": "0001845337", + "AMBA": "0001280263", + "KN": "0001587523", + "ACHC": "0001520697", + "NKTR": "0000906709", + "BUSE": "0000314489", + "RARE": "0001515673", + "DXC": "0001688568", + "HTH": "0001265131", + "VNET": "0001508475", + "NTB": "0001653242", + "XMTR": "0001657573", + "AMPX": "0001899287", + "ADMA": "0001368514", + "CLM": "0000814083", + "VVX": "0001601548", + "ALRM": "0001459200", + "SAH": "0001043509", + "SEZL": "0001662991", + "FLOC": "0002035149", + "CCU": "0000888746", + "AGRO": "0001499505", + "IMAX": "0000921582", + "BWIN": "0001781755", + "BL": "0001666134", + "FXCNY": "0001164009", + "HURN": "0001289848", + "MTX": "0000891014", + "GEL": "0001022321", + "AVPT": "0001777921", + "WB": "0001595761", + "CPRI": "0001530721", + "XXI": "0002070457", + "NYAX": "0001901279", + "TYRA": "0001863127", + "KALU": "0000811596", + "RH": "0001528849", + "HTFL": "0001464521", + "BW": "0001630805", + "SLNO": "0001484565", + "NTST": "0001798100", + "SPSC": "0001092699", + "GLOB": "0001557860", + "ARR": "0001428205", + "DAC": "0001369241", + "BANR": "0000946673", + "EVCM": "0001853145", + "AEGXF": "0001309167", + "TENB": "0001660280", + "WTTR": "0001693256", + "PK": "0001617406", + "GSG": "0001332174", + "KWR": "0000081362", + "AERO": "0001561861", + "CMRE": "0001503584", + "NEXT": "0001612720", + "NSIT": "0000932696", + "ATKR": "0001666138", + "AUPH": "0001600620", + "VECO": "0000103145", + "RVT": "0000804116", + "CLDX": "0000744218", + "GNL": "0001526113", + "ATHM": "0001527636", + "AGIO": "0001439222", + "EXTR": "0001078271", + "DFTX": "0001813814", + "NEOG": "0000711377", + "ALG": "0000897077", + "WT": "0000880631", + "TSAT": "0001845840", + "ECO": "0001964954", + "MBIN": "0001629019", + "BB": "0001070235", + "VET": "0001293135", + "PLUS": "0001022408", + "TGLS": "0001534675", + "NVTS": "0001821769", + "INTA": "0001565687", + "DRVN": "0001804745", + "CXW": "0001070985", + "SEM": "0001320414", + "EFSC": "0001025835", + "PAX": "0001825570", + "BHE": "0000863436", + "UTI": "0001261654", + "BLBD": "0001589526", + "CASH": "0000907471", + "NMM": "0001415921", + "WLY": "0000107140", + "AGYS": "0000078749", + "VGNT": "0002078008", + "HCI": "0001400810", + "BHC": "0000885590", + "SYBT": "0000835324", + "NCNO": "0001902733", + "GLPG": "0001421876", + "AAMI": "0001748824", + "PENN": "0000921738", + "FDP": "0001047340", + "BRBR": "0001772016", + "FA": "0001210677", + "SKWD": "0001519449", + "PTON": "0001639825", + "BLX": "0000890541", + "GTY": "0001052752", + "VRE": "0000924901", + "WGS": "0001818331", + "MESO": "0001345099", + "DRH": "0001298946", + "STOK": "0001623526", + "VRDN": "0001590750", + "VERX": "0001806837", + "IE": "0001879016", + "ZYME": "0001937653", + "FORTY": "0001045986", + "GT": "0000042582", + "DCO": "0000030305", + "STRA": "0001013934", + "AHG": "0001702318", + "XPRO": "0001575828", + "NWBI": "0001471265", + "DEI": "0001364250", + "NUV": "0000812801", + "PDO": "0001798618", + "EYUBY": "0001562294", + "EYE": "0001710155", + "ROG": "0000084748", + "DGII": "0000854775", + "CHA": "0002013649", + "CURLF": "0001756770", + "EPAC": "0000006955", + "AVVSY": "0002082141", + "RDW": "0001819810", + "LTC": "0000887905", + "STEL": "0001473844", + "LNXSY": "0001311307", + "OSSUY": "0001437545", + "PHVS": "0001830487", + "OCUL": "0001393434", + "MAAS": "0001750264", + "STC": "0000094344", + "CAPR": "0001133869", + "CLBK": "0001723596", + "SMNR": "0001913577", + "IOSP": "0001054905", + "PRKS": "0001564902", + "CMPR": "0001262976", + "FCF": "0000712537", + "EVT": "0001253327", + "PSNY": "0001884082", + "WERN": "0000793074", + "SION": "0002036042", + "HBNB": "0002054507", + "BLKB": "0001280058", + "TNET": "0000937098", + "GCMG": "0001819796", + "SEMR": "0001831840", + "APPN": "0001441683", + "COTY": "0001024305", + "KMPR": "0000860748", + "NAC": "0001074952", + "EVTC": "0001559865", + "BORR": "0001715497", + "OFG": "0001030469", + "AXGN": "0000805928", + "NBHC": "0001475841", + "GTM": "0001794515", + "USAS": "0001286973", + "PVLA": "0001583648", + "LU": "0001816007", + "MD": "0000893949", + "ARCO": "0001508478", + "HMN": "0000850141", + "ALKT": "0001529274", + "PAYO": "0001845815", + "GENB": "0002100782", + "CHCO": "0000726854", + "MQ": "0001522540", + "FLO": "0001128928", + "TSLX": "0001508655", + "WMK": "0000105418", + "VCEL": "0000887359", + "KOS": "0001509991", + "IMKTA": "0000050493", + "RNW": "0001848763", + "BRAI": "0002076975", + "MCRI": "0000907242", + "RAMP": "0000733269", + "SRCE": "0000034782", + "ATEN": "0001580808", + "FSUN": "0001709442", + "MGNI": "0001595974", + "SPB": "0000109177", + "INVA": "0001080014", + "THR": "0001489096", + "QFIN": "0001741530", + "TY": "0000099614", + "ESTA": "0001688757", + "FUN": "0001999001", + "SHO": "0001295810", + "ADUS": "0001468328", + "BBAI": "0001836981", + "PUMP": "0001680247", + "AILIH": "0000018654", + "SXGCF": "0001622629", + "RUM": "0001830081", + "SLVM": "0001856485", + "EOSE": "0001805077", + "CNL": "0001953575", + "EZPW": "0000876523", + "INVX": "0001042893", + "USA": "0000799195", + "SID": "0001049659", + "DHC": "0001075415", + "JBLU": "0001158463", + "LILA": "0001712184", + "GAB": "0000794685", + "ASGN": "0000890564", + "ICHR": "0001652535", + "ANIP": "0001023024", + "STEW": "0000102426", + "GCT": "0001857816", + "CNXC": "0001803599", + "ANAB": "0001370053", + "RQI": "0001157842", + "OGN": "0001821825", + "CCS": "0001576940", + "FIHL": "0001636639", + "AMLX": "0001658551", + "LC": "0001409970", + "PBI": "0000078814", + "FLNG": "0001772253", + "BVC": "0001785680", + "GBX": "0000923120", + "GRC": "0000042682", + "RXRX": "0001601830", + "SONO": "0001314727", + "ATEC": "0001350653", + "MDCOY": "0002094100", + "AORT": "0000784199", + "AHCO": "0001725255", + "ZD": "0001084048", + "AGM": "0000845877", + "NRP": "0001171486", + "CLVT": "0001764046", + "NVRI": "0000045876", + "PWP": "0001777835", + "ADNT": "0001670541", + "KRP": "0001657788", + "DV": "0001819928", + "RAPP": "0002012593", + "HRMY": "0001802665", + "NRIX": "0001549595", + "GABC": "0000714395", + "SGML": "0001848309", + "ETV": "0001322436", + "GTBIF": "0001795139", + "HTZ": "0001657853", + "STGW": "0000876883", + "OI": "0000812074", + "RVLV": "0001746618", + "ABR": "0001253986", + "ECPG": "0001084961", + "HLMN": "0001822492", + "VOYG": "0001788060", + "INSP": "0001609550", + "SGRY": "0001638833", + "MXL": "0001288469", + "TV": "0000912892", + "RCAT": "0000748268", + "MBX": "0001776111", + "ETG": "0001270523", + "PLSE": "0001625101", + "TCBK": "0000356171", + "NGL": "0001504461", + "IMCR": "0001671927", + "STBA": "0000719220", + "PSIX": "0001137091", + "GSHD": "0001726978", + "BDJ": "0001332283", + "OMCL": "0000926326", + "NTLA": "0001652130", + "YELP": "0001345016", + "OCS": "0001953530", + "LOB": "0001462120", + "QUBT": "0001758009", + "WINA": "0000908315", + "TIC": "0002032966", + "BSTZ": "0001768666", + "KARO": "0001828102", + "BFC": "0001746109", + "TRVI": "0001563880", + "NUVB": "0001811063", + "ESRT": "0001541401", + "RES": "0000742278", + "ALGT": "0001362468", + "AMSC": "0000880807", + "SNDA": "0001043000", + "GLP": "0001323468", + "CBZ": "0000944148", + "AESI": "0001984060", + "ASAN": "0001477720", + "LKFN": "0000721994", + "WD": "0001497770", + "DMRA": "0001800315", + "WS": "0001968487", + "CXM": "0001569345", + "COHU": "0000021535", + "JJSF": "0000785956", + "KW": "0001408100", + "NBTX": "0001760854", + "CNXN": "0001050377", + "DCOM": "0000846617", + "EFC": "0001411342", + "BCAT": "0001809541", + "ARLO": "0001736946", + "AIN": "0000819793", + "APC": "0002080921", + "REX": "0000744187", + "PRGO": "0001585364", + "CTOS": "0001709682", + "BTT": "0001528437", + "HOPE": "0001128361", + "XHR": "0001616000", + "ECVT": "0001708035", + "TILE": "0000715787", + "ARI": "0001467760", + "PLPC": "0000080035", + "UFPT": "0000914156", + "LPG": "0001596993", + "CYD": "0000932695", + "CET": "0000018748", + "BHVN": "0001935979", + "SLSR": "0002019103", + "QCRH": "0000906465", + "NEXA": "0001713930", + "TROX": "0001530804", + "BY": "0001702750", + "BOBS": "0002085187", + "GLIBA": "0002057463", + "ARDX": "0001437402", + "PEB": "0001474098", + "SFL": "0001289877", + "TUYA": "0001829118", + "TRS": "0000842633", + "AAT": "0001500217", + "ATRC": "0001323885", + "VIR": "0001706431", + "DCH": "0001062231", + "WLTH": "0001524566", + "NWL": "0000814453", + "FLYW": "0001580560", + "KSS": "0000885639", + "BAK": "0001071438", + "HLF": "0001180262", + "EDN": "0001395213", + "UPWK": "0001627475", + "MAZE": "0001842295", + "TFIN": "0001539638", + "NSSC": "0000069633", + "GAM": "0000040417", + "PRCT": "0001588978", + "MNSKY": "0001584297", + "DQ": "0001477641", + "HLX": "0000866829", + "IOVA": "0001425205", + "IAUX": "0001853962", + "IIPR": "0001677576", + "RBCAA": "0000921557", + "BCAX": "0002023658", + "NOMD": "0001651717", + "CTS": "0000026058", + "LAC": "0001966983", + "TPB": "0001290677", + "PGEN": "0001356090", + "ASTH": "0001083446", + "TH": "0001712189", + "CDRE": "0001860543", + "IMTX": "0001809196", + "AVAH": "0001832332", + "DOLE": "0001857475", + "PDFS": "0001120914", + "HIMX": "0001342338", + "HYT": "0001222401", + "GSL": "0001430725", + "SKYT": "0001819974", + "VTOL": "0001525221", + "ORC": "0001518621", + "ECAT": "0001864843", + "ESBA": "0001553079", + "ATAI": "0001840904", + "PRLB": "0001443669", + "WVE": "0001631574", + "GLUE": "0001826457", + "IRS": "0000933267", + "SFDMY": "0001493507", + "MAN": "0000871763", + "OLPX": "0001868726", + "PGNY": "0001551306", + "CNOB": "0000712771", + "AEHR": "0001040470", + "AFYA": "0001771007", + "DMLP": "0001172358", + "QQQX": "0001608741", + "CSWC": "0000017313", + "SMPL": "0001702744", + "KDK": "0001853138", + "IQ": "0001722608", + "EBCRY": "0001969796", + "ZBIO": "0001953926", + "UAN": "0001425292", + "LINC": "0001286613", + "LOMA": "0001711375", + "OPRA": "0001737450", + "AZULQ": "0001432364", + "LEG": "0000058492", + "HROW": "0001360214", + "ABXXF": "0001971975", + "OLMA": "0001750284", + "RHLD": "0002039497", + "SILA": "0001567925", + "UVV": "0000102037", + "WEN": "0000030697", + "CRI": "0001060822", + "WWW": "0000110471", + "SBH": "0001368458", + "DFH": "0001825088", + "LZB": "0000057131", + "WKC": "0000789460", + "NAT": "0001000177", + "WBTN": "0001997859", + "SPH": "0001005210", + "AMRC": "0001488139", + "NVGS": "0001581804", + "PAEXY": "0002073620", + "XZO": "0001873951", + "ENOV": "0001420800", + "OBK": "0001516912", + "HCSG": "0000731012", + "BST": "0001616678", + "RSRBF": "0001974551", + "JKS": "0001481513", + "FINV": "0001691445", + "VIA": "0001603015", + "IMOS": "0001123134", + "MUX": "0000314203", + "RKGRY": "0002093907", + "TNDM": "0001438133", + "PSEC": "0001287032", + "TRIP": "0001526520", + "DFIN": "0001669811", + "PRA": "0001127703", + "DLX": "0000027996", + "WABC": "0000311094", + "ASTE": "0000792987", + "TNC": "0000097134", + "TSHA": "0001806310", + "AI": "0001577526", + "NVAX": "0001000694", + "INOD": "0000903651", + "FOR": "0001406587", + "NXRT": "0001620393", + "CBL": "0000910612", + "DBVT": "0001613780", + "TRIN": "0001786108", + "UAMY": "0000101538", + "LADR": "0001577670", + "MLTX": "0001821586", + "UMH": "0000752642", + "RZLV": "0001920294", + "ARDT": "0001756655", + "PDS": "0001013605", + "ICFI": "0001362004", + "DEC": "0001922446", + "CRVS": "0001626971", + "GILT": "0000897322", + "ELE": "0002086771", + "DSGR": "0000703604", + "IRMD": "0001325618", + "MSDL": "0001782524", + "DSL": "0001566388", + "OUST": "0001816581", + "LAR": "0001440972", + "LSPD": "0001823306", + "SBET": "0001981535", + "XPEL": "0001767258", + "NPKI": "0000071829", + "IDT": "0001005731", + "NMZ": "0001266585", + "TEN": "0001166663", + "GIC": "0000945114", + "NFJ": "0001260563", + "PEBO": "0000318300", + "NVCR": "0001645113", + "LUCK": "0001840572", + "WLFC": "0001018164", + "WBI": "0002064947", + "WLDN": "0001370450", + "ASA": "0001230869", + "CCO": "0001334978", + "GPRE": "0001309402", + "RDWR": "0001094366", + "GIII": "0000821002", + "CCB": "0001437958", + "JFR": "0001276533", + "AMAL": "0001823608", + "ALX": "0000003499", + "QDEL": "0001906324", + "FIVN": "0001288847", + "NBR": "0001163739", + "GENI": "0001834489", + "SVV": "0001883313", + "TTI": "0000844965", + "TWO": "0001465740", + "TCNNF": "0001754195", + "GOLD": "0001591588", + "TMP": "0001005817", + "KMTS": "0001877184", + "PHAR": "0001828316", + "PZZA": "0000901491", + "ROCK": "0000912562", + "AGBK": "0002081206", + "SHLS": "0001831651", + "RYZ": "0001481582", + "CRF": "0000033934", + "BFS": "0000907254", + "DEA": "0001622194", + "LWLG": "0001325964", + "BKSY": "0001753539", + "VZLA": "0001796073", + "TIGR": "0001756699", + "SVRA": "0001160308", + "ALVO": "0001898416", + "IVA": "0001756594", + "NNNN": "0001982708", + "SCL": "0000094049", + "TE": "0001992243", + "SEPN": "0001984086", + "PRG": "0001808834", + "ENR": "0001632790", + "DAO": "0001781753", + "MRTN": "0000799167", + "RLJ": "0001511337", + "ARRY": "0001820721", + "USPH": "0000885978", + "PXED": "0001600222", + "CTBI": "0000350852", + "BH-A": "0001726173", + "EYPT": "0001314102", + "TRUP": "0001371285", + "NNE": "0001923891", + "LIND": "0001512499", + "RUPRF": "0001010000", + "PFBC": "0001492165", + "FMBH": "0000700565", + "CCEC": "0001392326", + "NSP": "0001000753", + "EOS": "0001308335", + "TK": "0000911971", + "BV": "0001734713", + "ASM": "0000316888", + "AVBP": "0001868279", + "ACDC": "0001881487", + "ENVX": "0001828318", + "KODK": "0000031235", + "OSBC": "0000357173", + "LNN": "0000836157", + "CMRF": "0001498547", + "IGIC": "0001794338", + "SAFT": "0001172052", + "EVV": "0001222922", + "SBR": "0000710752", + "PENG": "0001616533", + "REAL": "0001573221", + "MRVI": "0001823239", + "CRAI": "0001053706", + "PRGS": "0000876167", + "EVLV": "0001805385", + "FPF": "0001567569", + "CNMD": "0000816956", + "JCAP": "0002046042", + "GUYGF": "0001526491", + "HFWA": "0001046025", + "QURE": "0001590560", + "LXU": "0000060714", + "CIM": "0001409493", + "LUXE": "0001831907", + "PRSU": "0000884219", + "ELVR": "0001739016", + "ABCL": "0001703057", + "MFIC": "0001278752", + "GERN": "0000886744", + "CSR": "0000798359", + "CRML": "0001951089", + "APEI": "0001201792", + "SVMB": "0001647822", + "VMET": "0002080073", + "GNK": "0001326200", + "OCFC": "0001004702", + "BFLY": "0001804176", + "LTGHY": "0001569963", + "METC": "0001687187", + "TDAY": "0001579684", + "PTA": "0001793882", + "AZTA": "0000933974", + "XERS": "0001867096", + "PMT": "0001464423", + "ADTN": "0000926282", + "PLTK": "0001828016", + "NEO": "0001077183", + "NBXG": "0001843181", + "MCB": "0001476034", + "LZ": "0001286139", + "VSTS": "0001967649", + "INNV": "0001834376", + "HLIT": "0000851310", + "GSBD": "0001572694", + "ALNT": "0000046129", + "PNTG": "0001766400", + "COLL": "0001267565", + "FSCO": "0001568194", + "GOOS": "0001690511", + "AVO": "0001802974", + "EMO": "0001517518", + "MBC": "0001941365", + "RIOFF": "0001743235", + "KALV": "0001348911", + "UPBD": "0000933036", + "ITRN": "0001337117", + "NPK": "0000080172", + "YALA": "0001794350", + "HQH": "0000805267", + "MTAL": "0002107724", + "MMI": "0001578732", + "OCSL": "0001414932", + "XIFR": "0001603145", + "SSII": "0001676163", + "STAA": "0000718937", + "COUR": "0001651562", + "HBT": "0000775215", + "PBT": "0000319654", + "SCHL": "0000866729", + "UVSP": "0000102212", + "MSEX": "0000066004", + "ORIC": "0001796280", + "HSLV": "0002013223", + "SIFY": "0001094324", + "IPX": "0001898601", + "BBN": "0001493683", + "MFA": "0001055160", + "TBN": "0001997652", + "MLKN": "0000066382", + "AOD": "0001379400", + "MUC": "0001051004", + "CTMX": "0001501989", + "NBBK": "0001979330", + "ODV": "0001431852", + "TYG": "0001268533", + "BTGO": "0001740604", + "CMPX": "0001738021", + "RERE": "0001838957", + "EPC": "0001096752", + "PCT": "0001830033", + "ODC": "0000074046", + "HEPS": "0001850235", + "PCRX": "0001396814", + "OPY": "0000791963", + "CRON": "0001656472", + "PGY": "0001883085", + "ETW": "0001322435", + "SAFE": "0001095651", + "SATL": "0001874315", + "PLOW": "0001287213", + "UTL": "0000755001", + "RNP": "0001224450", + "LQDT": "0001235468", + "AMTB": "0001734342", + "ABTC": "0001755953", + "OXLC": "0001495222", + "MPLT": "0001770069", + "JBSS": "0000880117", + "UFCS": "0000101199", + "DAKT": "0000915779", + "AKTS": "0002035832", + "ASIC": "0002040491", + "CFFN": "0001490906", + "CCOI": "0001158324", + "EXPI": "0001495932", + "CMP": "0001227654", + "EAI": "0000007323", + "CRTO": "0001576427", + "EQBK": "0001227500", + "MOMO": "0001610601", + "PDX": "0001756908", + "SENEB": "0000088948", + "BLFS": "0000834365", + "CDNA": "0001217234", + "ESQ": "0001531031", + "TDOC": "0001477449", + "BTZ": "0001379384", + "AMPH": "0001297184", + "BHRB": "0001964333", + "XNCR": "0001326732", + "LMB": "0001606163", + "SBSI": "0000705432", + "BCX": "0001506289", + "UVE": "0000891166", + "POET": "0001437424", + "KBDC": "0001747172", + "SBGI": "0001971213", + "TBLA": "0001840502", + "INBX": "0002007919", + "EVO": "0001412558", + "FUEMF": "0002001201", + "CPAC": "0001221029", + "EVEX": "0001823652", + "URGN": "0001668243", + "NABL": "0001834488", + "AMPL": "0001866692", + "BUR": "0001714174", + "XRN": "0001533615", + "NRK": "0001195739", + "GHRS": "0001855129", + "BFST": "0001624322", + "JANX": "0001817713", + "CHY": "0001222719", + "CLOV": "0001801170", + "ACEL": "0001698991", + "ARHS": "0001875444", + "GHM": "0000716314", + "LMRI": "0002071288", + "EEX": "0001579214", + "BMEZ": "0001785971", + "SNCY": "0001743907", + "CSIQ": "0001375877", + "PHAT": "0001783183", + "CII": "0001278895", + "CHI": "0001171471", + "CRESY": "0001034957", + "MBWM": "0001042729", + "PCN": "0001160990", + "FTRE": "0001965040", + "ANNX": "0001528115", + "HTD": "0001260041", + "LGIH": "0001580670", + "VOR": "0001817229", + "KRNGY": "0001494191", + "JBGS": "0001689796", + "BBDC": "0001379785", + "ABUS": "0001447028", + "OPK": "0000944809", + "INMD": "0001742692", + "YB": "0001995520", + "CGEM": "0001789972", + "HPK": "0001792849", + "CCNE": "0000736772", + "TALK": "0001803901", + "SUPV": "0001517399", + "AWF": "0000906013", + "WSR": "0001175535", + "CERT": "0001827090", + "CPF": "0000701347", + "VRTS": "0000883237", + "HBNC": "0000706129", + "WGO": "0000107687", + "CPPKF": "0001691710", + "VYX": "0000070866", + "SDGR": "0001490978", + "EVMN": "0002044725", + "SANA": "0001770121", + "JMIA": "0001756708", + "GROY": "0001834026", + "THRM": "0000903129", + "CRCT": "0001828962", + "MCBS": "0001747068", + "WOLF": "0000895419", + "GGN": "0001313510", + "PHK": "0001219360", + "RJET": "0000810332", + "HDL": "0001995306", + "SHEN": "0000354963", + "AEVA": "0001789029", + "HMH": "0002021880", + "AIP": "0001667011", + "ULCC": "0001670076", + "SLI": "0001537137", + "KRUS": "0001772177", + "TBPH": "0001583107", + "MEG": "0001643615", + "NAK": "0001164771", + "SPRY": "0001671858", + "HTLD": "0000799233", + "SWMR": "0002092574", + "PDM": "0001042776", + "FSBC": "0001275168", + "EIG": "0001379041", + "MPB": "0000879635", + "CAC": "0000750686", + "BCSF": "0001655050", + "PFLT": "0001504619", + "FCBC": "0000859070", + "HRTG": "0001598665", + "REPX": "0001001614", + "TRST": "0000357301", + "NOAH": "0001499543", + "NX": "0001423221", + "SCSC": "0000918965", + "NMFC": "0001496099", + "VLRS": "0001520504", + "CGBD": "0001544206", + "OILSF": "0001868917", + "NEGG": "0001474627", + "PRCH": "0001784535", + "SLRC": "0001418076", + "ODD": "0001907085", + "FMCB": "0001085913", + "MQY": "0000890196", + "CAPL": "0001538849", + "CTLP": "0000896429", + "HAFC": "0001109242", + "FMNB": "0000709337", + "CAZGF": "0002074220", + "ABX": "0001814287", + "GFR": "0001966287", + "MATW": "0000063296", + "NEWP": "0001369085", + "NAVI": "0001593538", + "MYE": "0000069488", + "SMP": "0000093389", + "BRELY": "0002018463", + "LDI": "0001831631", + "BTX": "0001836057", + "EOI": "0001300391", + "HTBK": "0001053352", + "RPC": "0001841968", + "IBTA": "0001538379", + "WLKP": "0001604665", + "PKST": "0001600626", + "BIOA": "0001709941", + "EGBN": "0001050441", + "OMER": "0001285819", + "MNKD": "0000899460", + "STKL": "0000351834", + "LOT": "0001962746", + "MEGI": "0001855066", + "NWPX": "0001001385", + "JBIO": "0001798749", + "HUYA": "0001728190", + "WOOF": "0001826470", + "TLRY": "0001731348", + "GSM": "0001639877", + "KURA": "0001422143", + "THFF": "0000714562", + "BJRI": "0001013488", + "ACVA": "0001637873", + "SKYH": "0001823587", + "CCBG": "0000726601", + "BBSI": "0000902791", + "ATEX": "0001304492", + "NRDS": "0001625278", + "GRNT": "0001928446", + "FFC": "0001174164", + "CLB": "0001958086", + "HTB": "0001538263", + "SGP": "0001778922", + "AIO": "0001778114", + "DBA": "0001383082", + "MGTX": "0001735438", + "CMPS": "0001816590", + "BLDP": "0001453015", + "LIFE": "0001788451", + "EH": "0001759783", + "HNRG": "0000788965", + "IART": "0000917520", + "SVC": "0000945394", + "AEBI": "0002048519", + "SLS": "0001390478", + "OMDA": "0001611115", + "CSTL": "0001447362", + "CSV": "0001016281", + "SLDB": "0001707502", + "LBRX": "0001691082", + "HBIA": "0000732417", + "NXP": "0000883618", + "BOW": "0002002473", + "NMAX": "0002026478", + "RLMD": "0001553643", + "KRO": "0001257640", + "KOP": "0001315257", + "GMTL": "0002039972", + "PEO": "0000216851", + "BRSP": "0001717547", + "ASGI": "0001793855", + "YDDL": "0002034723", + "SMBC": "0000916907", + "FPH": "0001574197", + "STRW": "0001782430", + "VTS": "0001944558", + "APOG": "0000006845", + "GSBC": "0000854560", + "GLASF": "0001848731", + "RYAM": "0001597672", + "VEL": "0001692376", + "ORRF": "0000826154", + "SCZM": "0001548536", + "BIT": "0001562818", + "GDEN": "0001071255", + "NUTX": "0001479681", + "DJCO": "0000783412", + "BBOT": "0001869105", + "TRNS": "0000099302", + "THQ": "0001604522", + "EHAB": "0001803737", + "GO": "0001771515", + "MYI": "0000883412", + "RA": "0001655099", + "RWT": "0000930236", + "BTO": "0000925683", + "CVLG": "0000928658", + "WRLD": "0000108385", + "IVR": "0001437071", + "AMN": "0001142750", + "FOXF": "0001424929", + "GDRX": "0001809519", + "IIIV": "0001728688", + "VTEX": "0001793663", + "DRUG": "0001827401", + "JQC": "0001227476", + "CBLL": "0001861107", + "DC": "0001852353", + "MRLN": "0002028707", + "ARVN": "0001655759", + "DSP": "0001828791", + "WDI": "0001819559", + "AXG": "0001959224", + "MALG": "0001309251", + "REPL": "0001737953", + "PRAA": "0001185348", + "RBTK": "0001594204", + "DSGN": "0001807120", + "ANRO": "0001999480", + "IBCP": "0000039311", + "TXO": "0001559432", + "VINP": "0001826286", + "QNST": "0001117297", + "FBRT": "0001562528", + "STK": "0001471420", + "PSNL": "0001527753", + "SSYS": "0001517396", + "SPFI": "0001163668", + "GYRE": "0001124105", + "KRNT": "0001625791", + "SPPP": "0001539190", + "JBI": "0001839839", + "ETON": "0001710340", + "UTZ": "0001739566", + "UDMY": "0001607939", + "ASIX": "0001673985", + "PAXS": "0001886878", + "LYTS": "0000763532", + "AOSL": "0001387467", + "SMBK": "0001038773", + "MTUS": "0001598428", + "OIS": "0001121484", + "SB": "0001434754", + "ASST": "0001920406", + "FDUS": "0001513363", + "LXRX": "0001062822", + "PFN": "0001296250", + "HSHP": "0001959455", + "NFGC": "0001840616", + "ROOT": "0001788882", + "HIPO": "0001828105", + "IGR": "0001268884", + "ESPR": "0001434868", + "ADAM": "0001273685", + "GAU": "0001377757", + "FET": "0001401257", + "DLY": "0001788399", + "NTGR": "0001122904", + "VIVK": "0001450704", + "SWBI": "0001092796", + "MNTN": "0001891027", + "RSKD": "0001851112", + "IMSR": "0002019804", + "NB": "0001512228", + "TBLD": "0001820378", + "BHK": "0001160864", + "HOV": "0000357294", + "FWRG": "0001789940", + "TMQ": "0001543418", + "IIIN": "0000764401", + "PSTL": "0001759774", + "DMII": "0002040475", + "RGR": "0000095029", + "NIE": "0001383441", + "AMC": "0001411579", + "EGY": "0000894627", + "UMAC": "0001956955", + "PDT": "0000855886", + "OPFI": "0001818502", + "AVNS": "0001606498", + "FISI": "0000862831", + "SLDP": "0001844862", + "INDI": "0001841925", + "CINT": "0001868995", + "NCDL": "0001737924", + "ADSE": "0001879248", + "CODI": "0001345126", + "BUI": "0001528988", + "CBRL": "0001067294", + "ALSAF": "0001865111", + "CDNL": "0002079999", + "TRON": "0001956744", + "ALPIB": "0000872716", + "ASC": "0001577437", + "SVA": "0001084201", + "OFRM": "0001696556", + "VMO": "0000884152", + "ISOU": "0001997377", + "WASH": "0000737468", + "PGC": "0001050743", + "SG": "0001477815", + "SERV": "0001832483", + "DGICA": "0000800457", + "ACP": "0001503290", + "MTA": "0001722606", + "VLGEA": "0000103595", + "TCBX": "0001781730", + "TIPT": "0001393726", + "RSVR": "0001824403", + "LPTH": "0000889971", + "BWMX": "0001788257", + "SHBI": "0001035092", + "MITK": "0000807863", + "ARKO": "0001823794", + "CWBC": "0001127371", + "TASK": "0001829864", + "NKX": "0001195738", + "DXYZ": "0001843974", + "EVOH": "0001700844", + "AMSF": "0001018979", + "CCD": "0001602584", + "OBE": "0001334388", + "BOE": "0001320375", + "RMT": "0000912147", + "BETR": "0001835856", + "CNNE": "0001704720", + "THM": "0001134115", + "UXIN": "0001729173", + "GDOT": "0001386278", + "MUJ": "0001053988", + "TRTX": "0001630472", + "HKHC": "0000088000", + "MAX": "0001818383", + "PURR": "0002078856", + "CGNT": "0001824814", + "NDMO": "0001793129", + "CTO": "0000023795", + "GLRE": "0001385613", + "AMRQF": "0002076631", + "DRTS": "0001871321", + "SWIM": "0001833197", + "HSTM": "0001095565", + "AMBQ": "0001500412", + "MAMA": "0001520358", + "ALRS": "0000903419", + "DSU": "0001051003", + "ALLO": "0001737287", + "BVS": "0001665988", + "URG": "0001375205", + "QDMI": "0001094032", + "NPB": "0001336706", + "NGVC": "0001547459", + "RRBI": "0001071236", + "CRSR": "0001743759", + "PRME": "0001894562", + "HZO": "0001057060", + "CTGO": "0001502377", + "FIP": "0001899883", + "VPG": "0001487952", + "WDH": "0001823986", + "LDP": "0001548717", + "MFI": "0001940941", + "BMBL": "0001830043", + "CBIO": "0001253689", + "KE": "0001606757", + "FAX": "0000790500", + "NMCO": "0001774342", + "EVAC": "0002042902", + "MHD": "0001034665", + "AHRT": "0001569187", + "SSTK": "0001549346", + "PD": "0001568100", + "IPI": "0001421461", + "OCGN": "0001372299", + "BZH": "0000915840", + "ITRG": "0001722387", + "DNUT": "0001857154", + "OXM": "0000075288", + "AIV": "0000922864", + "MDXG": "0001376339", + "CTKB": "0001831915", + "CASS": "0000708781", + "HY": "0001173514", + "THSGF": "0001832803", + "CEPF": "0002034267", + "FTK": "0000928054", + "SIBN": "0001459839", + "MSIF": "0001535778", + "IRWD": "0001446847", + "WRN": "0001364125", + "BCAL": "0001795815", + "EMD": "0001227862", + "TECX": "0001681087", + "SABR": "0001597033", + "NML": "0001562051", + "GAIN": "0001321741", + "PROK": "0001850270", + "ZURA": "0001855644", + "GOOD": "0001234006", + "SD": "0001349436", + "CCXI": "0002074973", + "IIM": "0000885601", + "BAND": "0001514416", + "ETD": "0000896156", + "UHT": "0000798783", + "NFBK": "0001493225", + "ULH": "0001308208", + "MOVE": "0001734750", + "TREE": "0001434621", + "VITL": "0001579733", + "ALTI": "0001838615", + "AROW": "0000717538", + "PKE": "0000076267", + "DDL": "0001854545", + "PAR": "0000708821", + "TCMD": "0001027838", + "KRT": "0001758021", + "MMU": "0000886043", + "MAKO": "0001784930", + "AMWD": "0000794619", + "CRMD": "0001410098", + "GEVO": "0001392380", + "IDR": "0001030192", + "MSC": "0001713334", + "EBF": "0000033002", + "DBO": "0001383058", + "SXC": "0001514705", + "GOGO": "0001537054", + "BHB": "0000743367", + "NRGV": "0001828536", + "NXDR": "0001846069", + "ZVRA": "0001434647", + "ALOY": "0001567900", + "MCS": "0000062234", + "FWRD": "0000912728", + "CABO": "0001632127", + "EVER": "0001640428", + "KFRC": "0000930420", + "CLNE": "0001368265", + "PFIS": "0001056943", + "FBYD": "0001937987", + "CEVA": "0001173489", + "ETJ": "0001395325", + "BWAY": "0001505065", + "CWCO": "0000928340", + "LAES": "0001951222", + "AEXA": "0002079173", + "UROY": "0001711570", + "ERII": "0001421517", + "DPG": "0001515671", + "VGM": "0000880892", + "REAX": "0001862461", + "ASPI": "0001921865", + "KYTX": "0001994702", + "FULC": "0001680581", + "EVGO": "0001821159", + "ACIC": "0001401521", + "GUT": "0001080720", + "AVR": "0002011514", + "EIKN": "0001861123", + "SPIR": "0001816017", + "SWRD": "0001795851", + "VKQ": "0000877463", + "UNTY": "0000920427", + "PRTA": "0001559053", + "VALN": "0001836564", + "HKD": "0001809691", + "FFIC": "0000923139", + "AGMB": "0002020932", + "MOV": "0000072573", + "FLGT": "0001674930", + "BMM": "0001732379", + "ECC": "0001604174", + "NRIM": "0001163370", + "EMBC": "0001872789", + "YDES": "0002011674", + "MLR": "0000924822", + "PIII": "0001832511", + "TATT": "0000808439", + "BLND": "0001855747", + "CARE": "0001829576", + "TRC": "0000096869", + "WIW": "0001267902", + "UPB": "0002022626", + "BCSS": "0002064355", + "OWLS": "0002025416", + "GTN": "0000043196", + "MRRDF": "0001839886", + "AVK": "0001219120", + "ACRS": "0001557746", + "RIGL": "0001034842", + "NXJ": "0001087786", + "PHR": "0001412408", + "BWMN": "0001847590", + "FPI": "0001591670", + "ANGX": "0001865200", + "GUG": "0001864208", + "FFMGF": "0001641229", + "CPS": "0001320461", + "GEMI": "0002055592", + "MCTA": "0002035992", + "AQST": "0001398733", + "IQI": "0000885125", + "RHNO": "0001785493", + "TRDA": "0001689375", + "MLAB": "0000724004", + "CATX": "0000728387", + "CTNM": "0001855175", + "BWB": "0001341317", + "BME": "0001314966", + "CBNK": "0001419536", + "RDVT": "0001720116", + "VCV": "0000895531", + "BBW": "0001113809", + "QNC": "0002106613", + "FMAC": "0002099232", + "NWAX": "0002074878", + "ACNB": "0000715579", + "HQL": "0000884121", + "LRMR": "0001374690", + "REEMF": "0001419806", + "ZKH": "0001862044", + "CRD-A": "0000025475", + "FGOVF": "0001064052", + "CARS": "0001683606", + "BGB": "0001546429", + "VSTM": "0001526119", + "LYEL": "0001806952", + "PML": "0001170299", + "PHDWY": "0001765812", + "MSBI": "0001466026", + "NPCE": "0001528287", + "EIM": "0001176984", + "BGY": "0001393299", + "GDYN": "0001743725", + "KMDA": "0001567529", + "UURAF": "0001495651", + "LEGH": "0001436208", + "BLW": "0001233681", + "FTHY": "0001810523", + "TRX": "0001173643", + "NLST": "0001282631", + "GDLC": "0001729997", + "JOUT": "0000788329", + "HIVE": "0001720424", + "FEIM": "0000039020", + "FTW": "0002083125", + "FDMT": "0001650648", + "KRNY": "0001617242", + "MG": "0001436126", + "ACTG": "0000934549", + "MVST": "0001760689", + "NGS": "0001084991", + "HBCP": "0001436425", + "OLP": "0000712770", + "ANL": "0001944552", + "ADCT": "0001771910", + "CVGW": "0001133470", + "TWI": "0000899751", + "MNRO": "0000876427", + "THW": "0001635977", + "CHW": "0001396277", + "CIVB": "0000944745", + "HQ": "0002088256", + "PHCI": "0001620749", + "IMXI": "0001683695", + "PANL": "0001606909", + "INN": "0001497645", + "MEVO": "0002087361", + "GHY": "0001554697", + "ESEA": "0001341170", + "IHRT": "0001400891", + "KRSP": "0002074872", + "IMMX": "0001873835", + "VVR": "0001059386", + "GIW": "0002080019", + "MBUU": "0001590976", + "GRPN": "0001490281", + "ANSC": "0001854149", + "WTI": "0001288403", + "BALY": "0001747079", + "ABSI": "0001672688", + "BLMN": "0001546417", + "GOTU": "0001768259", + "VBNK": "0001690639", + "DHIL": "0000909108", + "MATV": "0001000623", + "SGLA": "0001433551", + "CRAN": "0002081358", + "SFIX": "0001576942", + "YEXT": "0001614178", + "IFN": "0000917100", + "HPS": "0001215913", + "OFIX": "0000884624", + "NBB": "0001478888", + "KOPN": "0000771266", + "RR": "0001963685", + "FBIZ": "0001521951", + "GTEN": "0001986817", + "ASMB": "0001426800", + "ORN": "0001402829", + "STTK": "0001680367", + "CHCT": "0001631569", + "AVIR": "0001593899", + "SBC": "0001930313", + "BSRR": "0001130144", + "APXT": "0002079253", + "GPRK": "0001464591", + "SEAH": "0002075786", + "SOHU": "0001734107", + "CMCL": "0000766011", + "CCAP": "0001633336", + "CCSI": "0001866633", + "SFST": "0001090009", + "ELA": "0000701719", + "EACO": "0000784539", + "YORW": "0000108985", + "HTT": "0001692705", + "CGC": "0001737927", + "ENGN": "0001980845", + "BDN": "0000790816", + "BTBT": "0001710350", + "CLYM": "0001768446", + "NPFD": "0001865389", + "ETO": "0001281926", + "WYFI": "0002042022", + "MYGN": "0000899923", + "KIO": "0001515940", + "DCBO": "0001829959", + "IGD": "0001285890", + "DVLT": "0001682149", + "KBON": "0002088749", + "NQP": "0000870780", + "EPRX": "0001581178", + "BBNX": "0001674632", + "RGNX": "0001590877", + "VREX": "0001681622", + "DDI": "0001799567", + "SCVL": "0000895447", + "CYRX": "0001124524", + "GRVY": "0001313310", + "SHAZ": "0002068385", + "ASTL": "0001860805", + "ISD": "0001534880", + "VRNO": "0001848416", + "VREOF": "0001771706", + "IEAG": "0002084396", + "ALT": "0001326190", + "MBVI": "0002073928", + "OBT": "0001754226", + "GLOO": "0002069785", + "TLNC": "0002073340", + "LAND": "0001495240", + "LGDTF": "0001755191", + "ETB": "0001308927", + "PLAY": "0001525769", + "CBAN": "0000711669", + "FGPR": "0000922358", + "DNA": "0001830214", + "COFS": "0000803164", + "KRAQ": "0002082119", + "TDUP": "0001484778", + "WEST": "0001806347", + "MESH": "0002081468", + "EBS": "0001367644", + "CSHR": "0002087587", + "ANGO": "0001275187", + "ZNOG": "0001131312", + "NATR": "0000275053", + "LXEO": "0001907108", + "FINS": "0001745059", + "GSKRF": "0001944955", + "LSAK": "0001041514", + "MTW": "0000061986", + "HPI": "0001176199", + "FRPH": "0000844059", + "NMAI": "0001861115", + "CMDB": "0002033535", + "BGR": "0001306550", + "ATNI": "0000879585", + "AURA": "0001501796", + "AUNA": "0001799207", + "NAUT": "0001808805", + "CIGL": "0002001794", + "BCAR": "0002065779", + "BMRC": "0001403475", + "LOCO": "0001606366", + "DFP": "0001559991", + "PTOR": "0002093912", + "EVN": "0001074540", + "OPAL": "0001842279", + "CDZI": "0000727273", + "VNDA": "0001347178", + "AIOT": "0001774170", + "ITIC": "0000720858", + "SAAQ": "0002091222", + "SGU": "0001002590", + "NATH": "0000069733", + "CWH": "0001669779", + "FFA": "0001291334", + "PINWF": "0002059573", + "MSB": "0000065172", + "CYH": "0001108109", + "KFII": "0002029976", + "ELTP": "0001053369", + "LND": "0001499849", + "WTBA": "0001166928", + "PERI": "0001338940", + "XRPN": "0002044009", + "OSPN": "0001044777", + "MUA": "0000901243", + "KIDS": "0001425450", + "BXC": "0001301787", + "OOMA": "0001327688", + "DBCA": "0002095161", + "AVTX": "0001534120", + "PACB": "0001299130", + "GLAD": "0001143513", + "TITN": "0001409171", + "CLBR": "0002091024", + "CZNC": "0000810958", + "CMCO": "0001005229", + "PTLO": "0001871509", + "ISSC": "0000836690", + "GBAB": "0001495825", + "KREF": "0001631596", + "NIKA": "0001145604", + "ELVA": "0001844450", + "GBFH": "0001791145", + "BGS": "0001278027", + "VHI": "0000059255", + "LEO": "0000818972", + "RNGR": "0001699039", + "CRAQ": "0002058359", + "GBLI": "0001494904", + "MGPI": "0000835011", + "NPAC": "0002048948", + "BWFG": "0001505732", + "PRTH": "0001653558", + "STRO": "0001382101", + "SDHY": "0001812923", + "PSFE": "0001833835", + "XOMA": "0000791908", + "CLDT": "0001476045", + "RTAC": "0002035173", + "NOA": "0001368519", + "PUBM": "0001422930", + "XWIN": "0001473334", + "CCIX": "0002006291", + "LCTX": "0000876343", + "GPAT": "0001834526", + "BSVN": "0001746129", + "ZDCAF": "0002025583", + "NRC": "0000070487", + "GCBC": "0001070524", + "VACH": "0002006815", + "MGMNF": "0001965615", + "PPHC": "0001903508", + "PNRG": "0000056868", + "BOC": "0001494582", + "ALF": "0002010930", + "TWN": "0000804123", + "PDLB": "0001874071", + "CDRO": "0001866782", + "WEAV": "0001609151", + "PCAP": "0002056634", + "BRBI": "0002058601", + "MBAV": "0002016072", + "XFOR": "0001501697", + "RCKT": "0001281895", + "ZKP": "0002087447", + "VKI": "0000908993", + "RBBN": "0001708055", + "LTBR": "0001084554", + "NC": "0000789933", + "TSSI": "0001320760", + "BBCQ": "0002088295", + "RDAG": "0002055459", + "TACO": "0002033122", + "PFL": "0001244183", + "EAD": "0001210123", + "IPSC": "0001850119", + "FRA": "0001259708", + "WENN": "0002057043", + "ENTA": "0001177648", + "CLMB": "0000945983", + "LX": "0001708259", + "PRTC": "0001782999", + "ISTR": "0001602658", + "GNE": "0001528356", + "BRBS": "0000842717", + "AII": "0002007587", + "SIGA": "0001010086", + "AUTL": "0001730463", + "NMG": "0001649752", + "ECX": "0001861974", + "BNTC": "0001808898", + "SOR": "0000091847", + "IBEX": "0001720420", + "ARMP": "0000921114", + "LOGC": "0002064307", + "VMD": "0001729149", + "INV": "0002001557", + "MYN": "0000882150", + "CV": "0001378325", + "MEC": "0001766368", + "AKBA": "0001517022", + "RBB": "0001499422", + "MCI": "0000275694", + "ALOV": "0002083989", + "SMC": "0002024218", + "XNET": "0001510593", + "MNPR": "0001645469", + "CLFD": "0000796505", + "NEXN": "0001849396", + "HLLY": "0001822928", + "ZUMZ": "0001318008", + "CBK": "0001981546", + "AVBC": "0002058758", + "CADL": "0001841387", + "ABAT": "0001576873", + "UP": "0001819516", + "KROS": "0001664710", + "SES": "0001819142", + "NMRA": "0001885522", + "CAL": "0000014707", + "VOXR": "0001907909", + "FVAV": "0001850733", + "SDHI": "0002034037", + "CTRN": "0001318484", + "ILPT": "0001717307", + "OIM": "0002088325", + "IVVD": "0001832038", + "FCRS": "0002074697", + "CAEP": "0002034268", + "SOPH": "0001840706", + "ALTO": "0000778164", + "SRTA": "0001779128", + "FVRR": "0001762301", + "BTQ": "0001821866", + "QUAD": "0001481792", + "FOF": "0001375340", + "GIX": "0002098712", + "ALUB": "0002041493", + "BGIN": "0001945565", + "ADUR": "0001863934", + "CERS": "0001020214", + "SAR": "0001377936", + "OEC": "0001609804", + "FWDI": "0000038264", + "NUS": "0001021561", + "FMAO": "0000792966", + "EU": "0001500881", + "LE": "0000799288", + "OTGA": "0002077010", + "TAKOF": "0001547452", + "TACH": "0002009183", + "CCII": "0002064683", + "GIG": "0002023730", + "CGCT": "0002049662", + "GASS": "0001328919", + "LAB": "0001162194", + "RPD": "0001560327", + "KTF": "0000839533", + "CION": "0001534254", + "BBCP": "0001703956", + "ELLO": "0000946394", + "KNOP": "0001564180", + "SNDL": "0001766600", + "IMRX": "0001790340", + "IPCX": "0002012318", + "DMAA": "0002028614", + "INRE": "0001528985", + "BCYC": "0001761612", + "TOYO": "0001985273", + "KCHV": "0002053799", + "PBFS": "0001769663", + "PBYI": "0001401667", + "NAGE": "0001386570", + "HIX": "0001058239", + "PAII": "0002069238", + "DBP": "0001383057", + "NAN": "0001074769", + "FCEL": "0000886128", + "JRI": "0001539337", + "DMAC": "0001401040", + "NNDM": "0001643303", + "ARCI": "0002083910", + "BKRRF": "0001699906", + "HCIC": "0002099093", + "SOUL": "0002025608", + "ALLT": "0001365767", + "USCB": "0001901637", + "WILC": "0001030997", + "CRLBF": "0001832928", + "FVR": "0001988494", + "APPS": "0000317788", + "BDCI": "0002042292", + "JGH": "0001615905", + "NCV": "0001214935", + "CD": "0001527762", + "PKOH": "0000076282", + "OYSE": "0002042182", + "SORN": "0002086263", + "PLBC": "0001168455", + "BKT": "0000832327", + "BLZR": "0002075310", + "HIO": "0000910068", + "SBXE": "0002081909", + "PPT": "0000827773", + "AXIN": "0002057030", + "WNC": "0000879526", + "CLLS": "0001627281", + "CYDY": "0001175680", + "SCD": "0001270131", + "RLGT": "0001171155", + "AWP": "0001390195", + "AENT": "0001823584", + "DCTH": "0000872912", + "HCMA": "0002069856", + "MIY": "0000890393", + "LVWR": "0001898795", + "ONIT": "0000873860", + "HCKT": "0001057379", + "DSAC": "0002082149", + "HVT": "0000216085", + "NGEN": "0001751912", + "SPT": "0001517375", + "NECB": "0001847398", + "HELE": "0000916789", + "ISBA": "0000842517", + "WSBF": "0001569994", + "CEPT": "0002034269", + "LWAY": "0000814586", + "NVEC": "0000724910", + "HPF": "0001189740", + "PKBK": "0001315399", + "TLS": "0000320121", + "SSP": "0000832428", + "AZ": "0001866030", + "SCGX": "0001277575", + "DIN": "0000049754", + "BLUW": "0002050501", + "OVID": "0001636651", + "XPOF": "0001802156", + "UNTC": "0000798949", + "LZM": "0001958217", + "VALU": "0000717720", + "FBRX": "0001419041", + "ARTNA": "0000863110", + "PRE": "0001876431", + "CUB": "0002015955", + "BEAG": "0001852207", + "MCFT": "0001638290", + "FRST": "0001325670", + "CABA": "0001759138", + "SIMA": "0002014982", + "API": "0001802883", + "EDD": "0001388141", + "GETY": "0001898496", + "MTRX": "0000866273", + "CMTG": "0001666291", + "NWFL": "0001013272", + "RNLXY": "0001811115", + "STRT": "0000933034", + "MLAC": "0002029492", + "PAYS": "0001496443", + "PCB": "0001423869", + "CRNC": "0001768267", + "INR": "0002029118", + "OFLX": "0001317945", + "SUPX": "0001897087", + "LXFR": "0001096056", + "BCML": "0001730984", + "MTLS": "0001091223", + "IRD": "0001228627", + "HYAC": "0001970509", + "ALCO": "0000003545", + "FERA": "0002025401", + "FNLC": "0000765207", + "NGNE": "0001404644", + "RM": "0001519401", + "PACH": "0002040381", + "DRDB": "0002032528", + "SZZL": "0002030663", + "ANNA": "0001845123", + "OTLY": "0001843586", + "CEPV": "0002034266", + "MAGN": "0000041719", + "BBBY": "0001130713", + "OBA": "0002034313", + "SRZN": "0001824893", + "ZTR": "0000836412", + "MVBF": "0001277902", + "EVOX": "0002077954", + "NEWT": "0001587987", + "NKLR": "0002067627", + "TSBK": "0001046050", + "BKTI": "0000002186", + "HNST": "0001530979", + "OPTX": "0001866816", + "EWCZ": "0001856236", + "KOYN": "0002068454", + "PALI": "0001357459", + "BGT": "0001287480", + "MLP": "0000063330", + "AVBH": "0001443575", + "DSX": "0001318885", + "GLSI": "0001799788", + "PLTS": "0002053033", + "PHOE": "0002035709", + "PMTR": "0002061473", + "NREF": "0001786248", + "ALDF": "0002031561", + "IONR": "0001896084", + "LNKB": "0001756701", + "VFF": "0001584549", + "POLE": "0002025341", + "RNGT": "0002078653", + "SAC": "0002082844", + "AMCX": "0001514991", + "REI": "0001384195", + "JOF": "0000859796", + "USNA": "0000896264", + "JACS": "0002039058", + "SVAC": "0002074850", + "AEAQ": "0002083689", + "TVA": "0002033991", + "VACI": "0002080023", + "HFRO": "0001710680", + "RFMZ": "0001817159", + "MKLY": "0002067592", + "GGAZF": "0001515964", + "RIV": "0001501072", + "GRAF": "0001897463", + "BNED": "0001634117", + "LEGO": "0002087450", + "WEYS": "0000106532", + "PSBD": "0001794776", + "TOI": "0001799191", + "GCO": "0000018498", + "MXF": "0000065433", + "NWBO": "0001072379", + "ATII": "0002028516", + "CMII": "0002088805", + "LPAA": "0002015502", + "AGCC": "0002060016", + "RMNI": "0001635282", + "NCA": "0000818851", + "AMRN": "0000897448", + "LWAC": "0002061379", + "RAC": "0002047497", + "HYLN": "0001759631", + "EVI": "0000065312", + "ASPN": "0001145986", + "LPBB": "0002023676", + "TCI": "0000733590", + "EFR": "0001258623", + "CZFS": "0000739421", + "CVEO": "0001590584", + "ASG": "0000786035", + "GTERA": "0002043766", + "VHCP": "0002086264", + "TCPC": "0001370755", + "PACK": "0001712463", + "ITHA": "0002080985", + "LENZ": "0001815776", + "NTPIF": "0000829365", + "MBI": "0000814585", + "EFTY": "0002058349", + "NXG": "0001506488", + "SI": "0001699350", + "BIXI": "0002082542", + "PDYN": "0001826681", + "AFB": "0001162027", + "GTE": "0001273441", + "RFI": "0000891290", + "NBH": "0001178839", + "GSVRF": "0000865400", + "KELYA": "0000055135", + "KFS": "0001072627", + "DBI": "0001319947", + "LOKV": "0002048951", + "PINE": "0001786117", + "ALIT": "0001809104", + "AEF": "0000846676", + "RZLT": "0001509261", + "ARTC": "0002086545", + "TTGT": "0002018064", + "NLCP": "0001854964", + "SHMD": "0001987240", + "CCRN": "0001141103", + "CTEV": "0001793229", + "JENA": "0002060337", + "FSBW": "0001530249", + "COSO": "0001297107", + "VGZ": "0000783324", + "SHIP": "0001448397", + "ANGI": "0001705110", + "HVMC": "0002070602", + "ANVI": "0001570132", + "GSRF": "0002072404", + "TII": "0001791703", + "SVAQ": "0002085659", + "WRLGF": "0001733968", + "DEFT": "0001888274", + "VELO": "0001825079", + "NPCT": "0001835068", + "SMRT": "0001837014", + "BIOT": "0002072188", + "GPAC": "0002085408", + "DSM": "0000855887", + "GAMG": "0000055234", + "RCKY": "0000895456", + "ASLE": "0001754170", + "FSTR": "0000352825", + "SPXX": "0001338561", + "PNNT": "0001383414", + "HCAC": "0002079013", + "CAF": "0001368493", + "FJET": "0001947016", + "JMSB": "0001710482", + "TDRRF": "0001921050", + "OIA": "0000835333", + "FHTX": "0001822462", + "IRHO": "0002051985", + "BRW": "0000826020", + "FUND": "0000825202", + "SENS": "0001616543", + "ORGO": "0001661181", + "UCFI": "0001901203", + "DBL": "0001525201", + "SY": "0001758530", + "KLC": "0001873529", + "FUBO": "0001484769", + "ARDC": "0001515324", + "CIX": "0001049606", + "YSG": "0001819580", + "EM": "0001834253", + "AACB": "0002034334", + "BACC": "0002059654", + "TROO": "0001412095", + "NHIC": "0002043699", + "TEI": "0000909112", + "FGII": "0002090452", + "ADV": "0001776661", + "FUFU": "0001921158", + "LPCV": "0002083728", + "ADAC": "0002083002", + "PMO": "0000900422", + "SITC": "0000894315", + "CAN": "0001780652", + "LEGT": "0002002038", + "TYGO": "0001855447", + "SEG": "0002009684", + "IRAB": "0002077785", + "TG": "0000850429", + "NL": "0000072162", + "JRVR": "0001620459", + "MIN": "0000826735", + "EFT": "0001288992", + "ACIU": "0001651625", + "NPT": "0002014337", + "SLN": "0001479615", + "KRYXF": "0001318596", + "NBP": "0001778016", + "NCMI": "0001377630", + "MMD": "0001518557", + "FC": "0000886206", + "CLPT": "0001285550", + "ATLN": "0001605888", + "EVC": "0001109116", + "XCBE": "0002083493", + "TVAI": "0001872228", + "JWSMF": "0001831359", + "APAD": "0001956439", + "AVXL": "0001314052", + "FCCO": "0000932781", + "OVLY": "0001431567", + "TARA": "0001359931", + "CCCC": "0001662579", + "AERG": "0000879911", + "ABEO": "0000318306", + "FVCB": "0001675644", + "BGH": "0001521404", + "RXST": "0001111485", + "SSSS": "0001509470", + "SABS": "0001833214", + "AIRO": "0001927958", + "XSLL": "0002088807", + "AGD": "0001362481", + "GLATF": "0001716410", + "SBXD": "0002015947", + "TWFG": "0002007596", + "FOSL": "0000883569", + "FNRN": "0001114927", + "DDD": "0000910638", + "GDEV": "0001848739", + "BUUU": "0002047273", + "BYND": "0001655210", + "HVII": "0001846416", + "ZH": "0001835724", + "MUZE": "0002093484", + "XPER": "0001788999", + "RMM": "0001771226", + "ROMA": "0001945240", + "CEPO": "0002027708", + "WNEB": "0001157647", + "CPZ": "0001717457", + "TDF": "0000919893", + "DNMX": "0002081125", + "ALEC": "0001653087", + "RMR": "0001644378", + "SCM": "0001551901", + "ACCO": "0000712034", + "LODE": "0001120970", + "EMF": "0000809708", + "NODK": "0001681206", + "ACRE": "0001529377", + "EOT": "0001454741", + "AFRI": "0001903870", + "NCZ": "0001227857", + "EOLS": "0001570562", + "RC": "0001527590", + "USAU": "0000027093", + "EDIT": "0001650664", + "CLIR": "0001434524", + "GLDG": "0001538847", + "AVNW": "0001377789", + "RDNW": "0001596961", + "TLSI": "0001826667", + "SITKF": "0001747657", + "CARL": "0001794546", + "PMM": "0000844790", + "OACC": "0002029769", + "SMDRF": "0001939801", + "CHRS": "0001512762", + "ALXO": "0001810182", + "BRT": "0000014846", + "TENX": "0000034956", + "NUW": "0001450445", + "CHMG": "0000763563", + "SLGL": "0001684693", + "SVRSF": "0001682056", + "MLAA": "0002094265", + "FDBC": "0001098151", + "CIA": "0000024090", + "NUAI": "0002028336", + "FACT": "0002028935", + "ACV": "0001636289", + "RCS": "0000916183", + "PLMK": "0002030482", + "HELP": "0001833141", + "XFLT": "0001703079", + "MPTI": "0001902314", + "NTWO": "0002028027", + "KUBR": "0001081834", + "GRRR": "0001903145", + "MPX": "0001129155", + "NVA": "0001852551", + "JCE": "0001385763", + "EOD": "0001386067", + "VNME": "0002055879", + "AREC": "0001590715", + "ERC": "0001227073", + "ATLO": "0001132651", + "AACI": "0002092897", + "EIC": "0001754836", + "ESCA": "0000033488", + "EVH": "0001628908", + "HDSN": "0000925528", + "PCYO": "0000276720", + "FLYX": "0001843973", + "CNTX": "0001842952", + "OBIO": "0001814114", + "RLTY": "0001866874", + "AUDC": "0001086434", + "TSNDF": "0001778129", + "DBB": "0001383084", + "PPIH": "0000914122", + "RWAY": "0001653384", + "FLXS": "0000037472", + "MCR": "0000851170", + "SCII": "0002076739", + "SNFCA": "0000318673", + "HBB": "0001709164", + "MMT": "0000809173", + "MASS": "0001555279", + "AMPY": "0001533924", + "DAVA": "0001656081", + "WHGOF": "0001423867", + "FCT": "0001282850", + "FXNC": "0000719402", + "COPL": "0002045473", + "ELDN": "0001404281", + "BNAI": "0001838163", + "TBRG": "0001169445", + "ESOA": "0001357971", + "POWW": "0001015383", + "ALMU": "0001828805", + "EGHT": "0001023731", + "MYFW": "0001327607", + "SLP": "0001023459", + "FUNC": "0000763907", + "RAAQ": "0002052161", + "ASUR": "0000884144", + "STRS": "0000885508", + "PTNM": "0002046573", + "LAW": "0001625641", + "MCGA": "0002064658", + "GLO": "0001350869", + "SOCA": "0002065948", + "CLW": "0001441236", + "BUKS": "0000015847", + "ARL": "0001102238", + "IKT": "0001750149", + "SSAC": "0002081300", + "CVRX": "0001235912", + "PSF": "0001498612", + "RILY": "0001464790", + "MITT": "0001514281", + "RXT": "0001810019", + "IGAC": "0002075068", + "BPRN": "0001913971", + "PSRHF": "0001991413", + "VYGR": "0001640266", + "DAAQ": "0002052162", + "LMNR": "0001342423", + "CFFI": "0000913341", + "FTF": "0001233087", + "AMBR": "0001697818", + "TDWD": "0002076616", + "PROF": "0001628808", + "EVTL": "0001867102", + "HWBK": "0000893847", + "CCFN": "0000731122", + "SMWB": "0001842731", + "MACI": "0002016221", + "PTHRF": "0001621910", + "SABA": "0000828803", + "FRAF": "0000723646", + "REFI": "0001867949", + "CAMP": "0001736730", + "SUGRF": "0001996493", + "ETHM": "0002028699", + "NKSH": "0000796534", + "TWLV": "0002052243", + "CAQ": "0002100125", + "TDAC": "0001926599", + "ATGL": "0001967621", + "HUHU": "0001945415", + "JAKK": "0001009829", + "SPOK": "0001289945", + "BRCB": "0002068577", + "LCNB": "0001074902", + "CBNA": "0001392272", + "DYOR": "0002079292", + "NERV": "0001598646", + "ARCT": "0001768224", + "ENLV": "0001596812", + "BLRK": "0002081532", + "MRBK": "0001750735", + "BIII": "0002087087", + "NUCL": "0002089283", + "SVCO": "0001943289", + "SVCC": "0002033593", + "RGCO": "0001069533", + "RPAY": "0001720592", + "GWRS": "0001434728", + "MAGH": "0002046117", + "TC": "0001743340", + "BKKT": "0001820302", + "PEVM": "0001879848", + "SNNGF": "0001384831", + "LANV": "0001922097", + "JFIN": "0001743102", + "APN": "0002085795", + "CMRC": "0001626450", + "STEX": "0001530766", + "OABI": "0001846253", + "TWIN": "0000100378", + "PLG": "0001095052", + "FENC": "0001211583", + "JRS": "0001158289", + "PED": "0001141197", + "SJT": "0000319655", + "CFNB": "0000803016", + "NIU": "0001744781", + "TSKFF": "0001803800", + "GENC": "0000064472", + "CURR": "0001862935", + "BZAI": "0001871638", + "HLXC": "0002099656", + "MRAM": "0001438423", + "MAMK": "0002008007", + "BLZE": "0001462056", + "ARQQ": "0001859690", + "ONCH": "0002054272", + "OZ": "0001807046", + "LIEN": "0001843162", + "FXE": "0001328598", + "FINW": "0001856365", + "NPV": "0000897421", + "PRLD": "0001678660", + "NXDT": "0001356115", + "MFM": "0000801961", + "CRAC": "0002070887", + "MDWD": "0001593984", + "GLND": "0002093507", + "TSI": "0000809559", + "LGI": "0001278211", + "CNDT": "0001677703", + "WEWA": "0001616156", + "CGEN": "0001119774", + "LTRX": "0001114925", + "EGAN": "0001066194", + "ANIK": "0000898437", + "SDSYA": "0001163609", + "OSUR": "0001116463", + "GSHR": "0002044635", + "PESI": "0000891532", + "MINE": "0001823255", + "MPAA": "0000918251", + "AIRRF": "0001476573", + "PEBK": "0001093672", + "AMTX": "0000738214", + "KINS": "0000033992", + "LOVE": "0001701758", + "EGHA": "0002052547", + "IPOD": "0002041047", + "RNA": "0002093101", + "OVBC": "0000894671", + "VABK": "0001572334", + "OSG": "0000874501", + "HAVA": "0002042460", + "MEI": "0000065270", + "FLWS": "0001084869", + "TRVG": "0001683825", + "MGRT": "0002033377", + "TPVG": "0001580345", + "SIDU": "0001879726", + "LZMH": "0001967397", + "OPRT": "0001538716", + "BYRN": "0001354866", + "RDCM": "0001016838", + "HRZN": "0001487428", + "FT": "0000833040", + "NHS": "0001487610", + "AOMR": "0001766478", + "STRZ": "0000929351", + "NEN": "0000746514", + "HITI": "0001847409", + "SND": "0001529628", + "OPBK": "0001722010", + "GORO": "0001160791", + "UTMD": "0000706698", + "NRDY": "0001819404", + "KRRO": "0001703647", + "ETX": "0001563696", + "ACH": "0000075252", + "DBE": "0001383062", + "KRMD": "0000704440", + "NVCT": "0001875558", + "SPCE": "0001706946", + "SRV": "0001400897", + "GPJA": "0000041091", + "DUOT": "0001396536", + "MFIN": "0001000209", + "TBCH": "0001493761", + "CHCI": "0001299969", + "CMTV": "0000718413", + "GRO": "0001472326", + "TCX": "0000909494", + "KTWO": "0002086524", + "BEBE": "0002079933", + "AIRS": "0001870940", + "DPRO": "0001786286", + "TNXP": "0001430306", + "CXDO": "0001075736", + "CRNT": "0001119769", + "GSIT": "0001126741", + "DIBS": "0001600641", + "VUZI": "0001463972", + "INSG": "0001022652", + "HWAIF": "0001999124", + "FIGX": "0002059033", + "SMHI": "0001690334", + "ELTX": "0001601485", + "CMT": "0001026655", + "IIF": "0000916618", + "SPMC": "0001930147", + "MGNX": "0001125345", + "ACB": "0001683541", + "ABOS": "0001576885", + "LFAC": "0002084563", + "DHY": "0001061353", + "UTGN": "0000832480", + "MVIS": "0000065770", + "CNCK": "0001913847", + "ELMD": "0001488917", + "LUCD": "0001799011", + "DMB": "0001565381", + "BHLL": "0001407583", + "AIIA": "0002073553", + "CZWI": "0001367859", + "EFSI": "0000880641", + "VENU": "0001770501", + "HHLKF": "0001562823", + "EPSN": "0001726126", + "SWKH": "0001089907", + "VTIX": "0001606242", + "BXSY": "0001059213", + "OPP": "0001678130", + "NFTN": "0001544400", + "JACK": "0000807882", + "OGI": "0001620737", + "FCCN": "0001131903", + "SGHT": "0001531177", + "FBLA": "0002013639", + "RICK": "0000935419", + "III": "0001371489", + "HGLB": "0001622148", + "OMSE": "0002012219", + "IDE": "0001417802", + "OSS": "0001394056", + "INFU": "0001337013", + "WIA": "0001254370", + "ADAG": "0001818838", + "KGEI": "0001477081", + "CRBU": "0001619856", + "INSE": "0001615063", + "PAL": "0001998768", + "VPV": "0000895528", + "ZNTL": "0001725160", + "CRSF": "0000924396", + "GLAI": "0001473490", + "MENS": "0001954488", + "MPV": "0000831655", + "LNZA": "0001843724", + "IMMR": "0001058811", + "KF": "0000748691", + "PAMT": "0000798287", + "HERE": "0001932770", + "PROP": "0001162896", + "NRO": "0001261166", + "WLAC": "0002032379", + "CAST": "0001633369", + "SEVN": "0001452477", + "FF": "0001337298", + "PNPNF": "0000855950", + "LEE": "0000058361", + "CFBK": "0001070680", + "ELME": "0000104894", + "EXOD": "0001821534", + "STXS": "0001289340", + "AIRJ": "0001855474", + "TAYD": "0000096536", + "TGMPF": "0002025947", + "ORBS": "0001892492", + "CURV": "0001792781", + "SDA": "0001936804", + "CRBP": "0001595097", + "EHI": "0001228509", + "FNKO": "0001704711", + "PRQR": "0001612940", + "GDC": "0001641398", + "FOA": "0001828937", + "INBK": "0001562463", + "CURI": "0001776909", + "CBFV": "0001605301", + "EMP": "0000066901", + "FLX": "0001858724", + "AGL": "0001831097", + "WTF": "0001987363", + "FOTB": "0001099668", + "QTRX": "0001503274", + "BHR": "0001574085", + "KVHI": "0001007587", + "QUIK": "0000882508", + "PMTS": "0001641614", + "INTT": "0001036262", + "GALT": "0001133416", + "FLC": "0001245648", + "UNCY": "0001766140", + "ASYS": "0000720500", + "NLOP": "0001952976", + "BNR": "0001792267", + "NUTR": "0002006468", + "ZEPP": "0001720446", + "SLAMF": "0001838162", + "BVFL": "0001302387", + "CHEC": "0002047177", + "SGMT": "0001400118", + "DHF": "0001057861", + "PLX": "0001006281", + "EAF": "0000931148", + "XYF": "0001725033", + "NXPGY": "0001455632", + "LAWR": "0002007599", + "TGLO": "0001066684", + "PERF": "0001899830", + "RENT": "0001468327", + "EARN": "0001560672", + "ACHV": "0000949858", + "RBKB": "0001751783", + "TBXXF": "0001785476", + "ENJ": "0000071508", + "KLTR": "0001432133", + "CPSS": "0000889609", + "AIFU": "0001413855", + "CMCM": "0001597835", + "ACU": "0000002098", + "STLRF": "0001979408", + "VBF": "0000005094", + "CANG": "0001725123", + "GF": "0000858706", + "PLBY": "0001803914", + "TKNO": "0001850902", + "MGTE": "0001965052", + "INGN": "0001294133", + "ALTG": "0001759824", + "RANG": "0002035644", + "BCAC": "0002102072", + "EGG": "0001982961", + "PDEX": "0000788920", + "LFMD": "0000948320", + "ALPS": "0002025774", + "VERI": "0001615165", + "FCAP": "0001070296", + "CNTN": "0001861657", + "ESP": "0000033533", + "NNOX": "0001795251", + "CGEH": "0001009759", + "CSBB": "0000880417", + "GGT": "0000921671", + "CNTB": "0001835268", + "PONO": "0002108164", + "ARTV": "0001817241", + "EBMT": "0001478454", + "ANTA": "0002044255", + "JILL": "0001687932", + "RNAC": "0001453687", + "FGFH": "0000786298", + "WHWK": "0001422142", + "SSVFF": "0001397616", + "MNSB": "0001693577", + "NKTX": "0001787400", + "CDXS": "0001200375", + "BSL": "0001486298", + "RENEF": "0001889112", + "DERM": "0001867066", + "WHF": "0001552198", + "BRR": "0002076163", + "USGO": "0001947244", + "ONEW": "0001772921", + "IMPP": "0001876581", + "SGC": "0000095574", + "PCQ": "0001140411", + "MIST": "0001408443", + "MNTK": "0001826600", + "NMP": "0002054876", + "NFE": "0001749723", + "VTVT": "0001641489", + "XRX": "0001770450", + "BMBN": "0000804563", + "QSI": "0001816431", + "GEOS": "0001001115", + "RELL": "0000355948", + "VTN": "0000883265", + "NNY": "0000818850", + "SRGXF": "0001644540", + "MBOT": "0000883975", + "AMFN": "0000096664", + "BMN": "0001832871", + "AGMRF": "0002022059", + "CBUS": "0001705843", + "KORE": "0001855457", + "ZIP": "0001617553", + "PIM": "0000830622", + "ZHJD": "0001794276", + "TLSA": "0001723069", + "EMIS": "0002075816", + "LGCY": "0001836754", + "OXSQ": "0001259429", + "IDN": "0001040896", + "SMTI": "0000714256", + "APGOF": "0001811931", + "LKSP": "0002043508", + "ATOM": "0001420520", + "EDF": "0001501103", + "CRDL": "0001702123", + "MRT": "0001852767", + "AXREF": "0001175596", + "RAIL": "0001320854", + "LAFA": "0002079106", + "BCBP": "0001228454", + "SPEG": "0002028735", + "SRG": "0001628063", + "AFJK": "0001979005", + "LARK": "0001141688", + "NYXH": "0001857190", + "HNVR": "0001828588", + "KALA": "0001479419", + "EPM": "0001006655", + "WPAC": "0002081536", + "NCSM": "0001692427", + "DGXX": "0001854368", + "APYX": "0000719135", + "WHG": "0001165002", + "RVLGF": "0001616885", + "SKYX": "0001598981", + "DTI": "0001884516", + "MHF": "0000830487", + "MDV": "0001645873", + "ECF": "0000793040", + "SKYQ": "0001812447", + "DOYU": "0001762417", + "QNBC": "0000750558", + "NVX": "0001859795", + "FNWD": "0000919864", + "HTLM": "0002023153", + "BANX": "0001578987", + "HUSIF": "0001526475", + "IMUX": "0001280776", + "PMMCF": "0001930459", + "SMID": "0000924719", + "TETOF": "0001783432", + "DLNG": "0001578453", + "TNYA": "0001858848", + "HRTX": "0000818033", + "CPKF": "0000847538", + "NAKA": "0001946573", + "INAC": "0002063816", + "EMYB": "0001449794", + "PNBK": "0001098146", + "SPWR": "0001838987", + "UIS": "0000746838", + "ECBK": "0001914605", + "BDSX": "0001439725", + "CEPS": "0002089536", + "YCY": "0002075336", + "CTW": "0002047148", + "AXR": "0000006207", + "VXRT": "0000072444", + "UTKN": "0001919182", + "KISB": "0000803742", + "BZUN": "0001625414", + "SPE": "0000897802", + "NAZ": "0000892992", + "NTHI": "0001979414", + "AP": "0000006176", + "DOUG": "0001878897", + "FGBI": "0001408534", + "SNWV": "0001417663", + "HOFT": "0001077688", + "IGA": "0001332943", + "PFD": "0000868578", + "PZG": "0001629210", + "ICTSF": "0001010134", + "MOLN": "0001745114", + "ALTS": "0000862861", + "LFCR": "0001005286", + "DTIL": "0001357874", + "HQI": "0001140102", + "OWLT": "0001816708", + "MPA": "0000891038", + "EMPG": "0002005569", + "RCMT": "0000700841", + "EVG": "0001287498", + "WW": "0000105319", + "HUMA": "0001818382", + "GARLF": "0001725569", + "MSD": "0000904112", + "DHX": "0001393883", + "CCLD": "0001582982", + "RFAM": "0002091712", + "GLQ": "0001316463", + "FATE": "0001434316", + "LPRO": "0001806201", + "SHIM": "0001887944", + "TONX": "0001566610", + "LMRXF": "0001001500", + "YRD": "0001631761", + "SPRO": "0001701108", + "VLTLF": "0001872061", + "UAC": "0002098669", + "INVZ": "0001835654", + "CIK": "0000810766", + "ROC": "0002077709", + "AGXPF": "0001482436", + "ENBP": "0001437479", + "ORMP": "0001176309", + "GNT": "0001438893", + "NEOV": "0001748137", + "TRAK": "0000050471", + "GRX": "0001391437", + "ACR": "0001332551", + "MTC": "0001742518", + "UNG": "0001376227", + "BDTX": "0001701541", + "BGX": "0001504234", + "BEOB": "0001480170", + "HYI": "0001497186", + "AFBI": "0001823406", + "GOAI": "0001983736", + "SRBK": "0001951276", + "SCPQ": "0002083143", + "FTCO": "0001828377", + "AMCI": "0001937891", + "SRI": "0001043337", + "OIO": "0001957538", + "JMG": "0002049717", + "CODA": "0001334325", + "GAMB": "0001839799", + "BUDA": "0002079720", + "IPHA": "0001598599", + "SCTSF": "0001790538", + "HEQ": "0001496749", + "KPTI": "0001503802", + "KLRS": "0001754068", + "RMBI": "0001767837", + "NPWR": "0001845437", + "USBC": "0001074828", + "COE": "0001659494", + "BRLT": "0001866757", + "SANG": "0001753368", + "LCUT": "0000874396", + "EMPD": "0001829794", + "ACOG": "0001655923", + "SBFG": "0000767405", + "WRIV": "0001328409", + "BWG": "0001504545", + "JHS": "0000759866", + "TLYS": "0001524025", + "AGEN": "0001098972", + "JYNT": "0001612630", + "EDAP": "0001041934", + "SILC": "0000916793", + "ATLX": "0001540684", + "GPRO": "0001500435", + "ZENA": "0001997403", + "BCV": "0000009521", + "CAAS": "0002037400", + "ZJK": "0001941506", + "DMRC": "0001438231", + "EML": "0000031107", + "GCUMF": "0001514860", + "VLN": "0001863006", + "WEA": "0001163792", + "SLBK": "0001657642", + "RMMZ": "0001870833", + "EQ": "0001746466", + "ACRG": "0000773717", + "ELRE": "0001438461", + "CLPR": "0001649096", + "TYFG": "0001725262", + "TTEC": "0001013880", + "SGMO": "0001001233", + "ACNT": "0000095953", + "ONL": "0001873923", + "GHG": "0001724755", + "ASRT": "0001808665", + "IPEX": "0002028355", + "THRY": "0001556739", + "JLHL": "0002007846", + "RGP": "0001084765", + "PHD": "0001305767", + "OPRX": "0001448431", + "MAPS": "0001779474", + "FRD": "0000039092", + "MCN": "0001289868", + "DMO": "0001478102", + "DOWAY": "0002038919", + "SDHC": "0001982518", + "MSLE": "0001421642", + "CVGI": "0001290900", + "BSET": "0000010329", + "DOMO": "0001505952", + "TAVI": "0002020385", + "VFL": "0000895574", + "IMDX": "0001642380", + "PCSC": "0002017526", + "LSBK": "0002059653", + "TBI": "0000768899", + "NAMM": "0002026514", + "HYSR": "0001481028", + "NCAUF": "0001627868", + "NMT": "0000897419", + "PFO": "0000882071", + "PEPG": "0001835597", + "FKYS": "0000737875", + "KBLB": "0001413119", + "GHI": "0001059142", + "GRAY": "0002073548", + "BNC": "0001482541", + "TUSK": "0001679268", + "QSEA": "0002047455", + "NZAUF": "0001925511", + "GFLT": "0001796949", + "CWBHF": "0001750155", + "FXY": "0001353613", + "RFIL": "0000740664", + "IHD": "0001496292", + "ANTX": "0001880438", + "BSAI": "0001416090", + "FONR": "0000355019", + "GGZ": "0001585855", + "CEE": "0000860489", + "LCGMF": "0001339688", + "FURY": "0001514597", + "CXE": "0000845606", + "GLU": "0001282957", + "NIM": "0000890119", + "CFSU": "0001621888", + "CHAR": "0002024459", + "SKIN": "0001818093", + "PGAC": "0002030829", + "ZOMDF": "0001684144", + "QUMS": "0002070900", + "PAI": "0000075398", + "NMI": "0000830271", + "WALD": "0001840199", + "RMAX": "0001581091", + "GNLX": "0001231457", + "SRL": "0000016859", + "IAF": "0000779336", + "AIB": "0002070542", + "WSBK": "0002047235", + "CVVUF": "0001023109", + "DXST": "0001958133", + "BOOM": "0000034067", + "UNB": "0000706863", + "JEQ": "0000866095", + "MED": "0000910329", + "AOUT": "0001808997", + "MGYR": "0001337068", + "RCEL": "0001762303", + "DLTH": "0001649744", + "CHPT": "0001777393", + "RVSB": "0001041368", + "BSBK": "0001787414", + "AKA": "0001865107", + "NINE": "0001532286", + "JHI": "0000759828", + "BAER": "0001941536", + "CGO": "0001285650", + "VWAV": "0002038439", + "TNYZF": "0001836775", + "DH": "0001861795", + "PMN": "0001374339", + "ANPA": "0002031688", + "TORO": "0001941131", + "HYNE": "0002073153", + "BMEA": "0001840439", + "SVRE": "0001894693", + "WPGCF": "0001404353", + "ULBI": "0000875657", + "MDXH": "0001872529", + "SAMG": "0001549966", + "KVAC": "0001889983", + "HYPR": "0001833769", + "MMLP": "0001176334", + "ERH": "0001279014", + "ODYS": "0001577445", + "FMBM": "0000740806", + "HFUS": "0001482554", + "PCOK": "0001452936", + "DRTTF": "0001340476", + "CRDF": "0001213037", + "HFFG": "0001680873", + "SBI": "0000882300", + "CYDVF": "0001394039", + "SLQT": "0001794783", + "LONA": "0001620463", + "JUSHF": "0001909747", + "VATE": "0001006837", + "ARQ": "0001515156", + "WYGC": "0000723533", + "CMTL": "0000023197", + "STIM": "0001227636", + "CGDXF": "0001479480", + "PCF": "0000810943", + "FORR": "0001023313", + "FREVS": "0000036840", + "DFDV": "0001805526", + "MX": "0001325702", + "FGMC": "0001906364", + "SUNS": "0002012706", + "BCRD": "0001496690", + "EP": "0000887396", + "PROV": "0001010470", + "ESGH": "0001883835", + "UNIB": "0000811211", + "CRMT": "0000799850", + "REKR": "0001697851", + "ONCY": "0001129928", + "CLAR": "0000913277", + "RPID": "0001380106", + "STHO": "0001953366", + "SCOR": "0001158172", + "AEC": "0001519469", + "CHPG": "0002024460", + "XTGRF": "0001288770", + "HSDT": "0001610853", + "LGO": "0001400438", + "DGNX": "0002010499", + "BLMOY": "0002109234", + "CSTAF": "0001834032", + "RPT": "0001614806", + "RVRC": "0001839140", + "SIREF": "0001577783", + "LUD": "0001984124", + "ALYAF": "0001734520", + "SWZ": "0000813623", + "BCHG": "0001732409", + "MRCC": "0001512931", + "JLS": "0001472215", + "BCIC": "0001372807", + "ALDX": "0001341235", + "SFBC": "0001541119", + "PGP": "0001318025", + "FTLF": "0001374328", + "MB": "0002027265", + "NOEM": "0001956648", + "FLNT": "0001460329", + "SLSN": "0000883107", + "TTRX": "0002023016", + "SPKL": "0001884046", + "ISPR": "0001948455", + "HURC": "0000315374", + "FTZFF": "0001819258", + "LPA": "0001997711", + "TSQ": "0001499832", + "KEQU": "0000055529", + "IGI": "0001462586", + "OPTN": "0002070577", + "VIRC": "0000751365", + "BHST": "0001723464", + "PFBX": "0000770460", + "FSHP": "0001850059", + "SPRB": "0001683553", + "FPRGF": "0001555980", + "KULR": "0001662684", + "TWG": "0001978057", + "SEER": "0001726445", + "BOTJ": "0001275101", + "VMCAF": "0001892747", + "NOBH": "0000072205", + "MGF": "0000811922", + "RMI": "0001746967", + "AAWH": "0001756390", + "JELD": "0001674335", + "VRA": "0001495320", + "NWPP": "0001163389", + "OPXS": "0001397016", + "MERC": "0001333274", + "HIT": "0002019505", + "REDW": "0000942895", + "CHMI": "0001571776", + "COYA": "0001835022", + "ZKIN": "0001687451", + "CRCUF": "0000868822", + "VRCA": "0001660334", + "AARD": "0001774857", + "HYDTF": "0001958389", + "TMCI": "0001630627", + "BEEP": "0001847874", + "QTTB": "0001661998", + "BMHL": "0002027815", + "PYXS": "0001782223", + "BRCC": "0001891101", + "JFB": "0002024306", + "DWSN": "0000799165", + "AREN": "0000894871", + "CWGL": "0001562151", + "GGOXF": "0000877019", + "UBCP": "0000731653", + "FLL": "0000891482", + "TUNGF": "0002049560", + "LCCC": "0002049248", + "NEXM": "0000795800", + "LQMT": "0001141240", + "VANI": "0001266806", + "SUIG": "0001425355", + "SEV": "0001786471", + "CHSN": "0001825349", + "RFAI": "0002012807", + "AMWL": "0001393584", + "CMU": "0000809844", + "GDL": "0001378701", + "ORRCF": "0001390352", + "LGCXF": "0001921582", + "BYNO": "0001801417", + "RDZN": "0001868640", + "INVE": "0001036044", + "PEW": "0002051380", + "CCNB": "0001437213", + "CRGO": "0001927719", + "EVF": "0001070732", + "DIT": "0000928465", + "SRFM": "0001936224", + "ITMSF": "0001285170", + "MCRB": "0001609809", + "FUSB": "0000717806", + "SIF": "0000090168", + "SAFX": "0002019793", + "RGT": "0001514490", + "SMJF": "0002070954", + "MMTX": "0002077033", + "SPAUF": "0001337090", + "OKYO": "0001849296", + "ORIQ": "0002044523", + "MCRP": "0001993431", + "NRT": "0000072633", + "TGEN": "0001537435", + "MRDN": "0001437925", + "GCTS": "0001851961", + "GOSS": "0001728117", + "AGGI": "0001109262", + "GCV": "0000845611", + "WATT": "0001575793", + "RFM": "0001790177", + "TOUR": "0001597095", + "SSTI": "0001351636", + "SPAI": "0002011208", + "HCAT": "0001636422", + "LSE": "0001985139", + "SLNG": "0001043186", + "KG": "0002055116", + "RSKIA": "0000084112", + "BARK": "0001819574", + "XTRAF": "0001684505", + "ANIX": "0000715446", + "BODI": "0001826889", + "AURE": "0001765850", + "OCCI": "0001716951", + "WRAP": "0001702924", + "BDCTF": "0001576159", + "FMN": "0001199004", + "COOK": "0001857853", + "ALIS": "0002026767", + "EXFY": "0001476840", + "KZIA": "0001075880", + "CHGG": "0001364954", + "PYPD": "0001611842", + "CSPI": "0000356037", + "RANI": "0001856725", + "VGI": "0001528811", + "PLRX": "0001746473", + "FLNA": "0001069530", + "DTCX": "0001853825", + "OPTT": "0001378140", + "IH": "0001814423", + "YHNA": "0002020987", + "QMCO": "0000709283", + "LAKE": "0000798081", + "ATYR": "0001339970", + "LIDR": "0001818644", + "PLMJF": "0001845550", + "AEYE": "0001362190", + "FNWB": "0001556727", + "BLNK": "0001429764", + "AURX": "0001091596", + "GNSS": "0000924383", + "NCTY": "0001296774", + "INTG": "0000069422", + "PYRGF": "0001743344", + "DLHC": "0000785557", + "FBIO": "0001429260", + "GDO": "0001472341", + "NRXS": "0001933567", + "AUBN": "0000750574", + "CBKM": "0001006830", + "FVN": "0002010653", + "ZVIA": "0001854139", + "APAC": "0002043630", + "PBHC": "0001609065", + "OCC": "0001000230", + "MAIA": "0001878313", + "WSTN": "0002076192", + "PARK": "0002069604", + "NIPG": "0001966233", + "LICN": "0001876766", + "RYDE": "0001971115", + "MAYS": "0000054187", + "DTF": "0000879535", + "CSBR": "0000771856", + "MXCT": "0001287098", + "GMM": "0001913749", + "HTCO": "0001928948", + "UYSC": "0002036973", + "HURA": "0001498382", + "VNJA": "0001532383", + "MIND": "0000926423", + "BATL": "0001282648", + "SLNH": "0000064463", + "QTI": "0001844505", + "SERA": "0001534969", + "RSSS": "0001386301", + "AMTD": "0001769731", + "GANX": "0001819411", + "ARBE": "0001861841", + "CPHC": "0001672909", + "FDSB": "0002012726", + "WWR": "0000839470", + "IAE": "0001385632", + "XPL": "0000917225", + "INO": "0001055726", + "ARSMF": "0001804792", + "GRCE": "0001444192", + "ICG": "0001895597", + "PNI": "0001170311", + "CGTX": "0001455365", + "SSEA": "0002059165", + "AISP": "0001842566", + "HNNA": "0001145255", + "ASPS": "0001462418", + "SCTH": "0001703157", + "NRRSF": "0001778940", + "BSEM": "0001658678", + "PFX": "0001490349", + "EUBG": "0001171326", + "CUAUF": "0001737319", + "CHUC": "0001134765", + "SGA": "0000886136", + "FBSI": "0000912967", + "BSAA": "0002051587", + "ZEO": "0001865506", + "NMS": "0001607997", + "UWHR": "0000898171", + "SCAG": "0002000366", + "SIEB": "0000065596", + "AEAE": "0001852016", + "NTIC": "0000875582", + "UMEW": "0001114936", + "HAIN": "0000910406", + "WTG": "0002053927", + "CNDA": "0001851959", + "VCUFF": "0001884122", + "IOR": "0000949961", + "COEP": "0001759186", + "NBRG": "0001918414", + "CCG": "0001965473", + "VRM": "0001580864", + "EXOZ": "0002010788", + "TISI": "0000318833", + "RLEA": "0001893657", + "GCL": "0002002045", + "BPAC": "0002064177", + "STEM": "0001758766", + "WKEY": "0001738699", + "LOMLF": "0001509397", + "XGN": "0001274737", + "PLCE": "0001041859", + "CPBI": "0001979332", + "SPRU": "0001772720", + "OM": "0001484612", + "VIOT": "0001742770", + "SOGP": "0001783407", + "LBCMF": "0001580110", + "ATVK": "0001530185", + "NRXP": "0001719406", + "GLV": "0001288795", + "AGH": "0002009312", + "LNSR": "0001320350", + "BLNC": "0001632121", + "CBAT": "0001117171", + "GGR": "0001886190", + "FSP": "0001031316", + "PDCC": "0001998043", + "CPSH": "0000814676", + "GRUSF": "0001463000", + "GUTS": "0001572616", + "DMA": "0001523289", + "SRCRF": "0001467093", + "NSPR": "0001433607", + "LOOP": "0001504678", + "MOB": "0001898643", + "YOUL": "0002028177", + "NNBR": "0000918541", + "XBIT": "0001626878", + "BDMD": "0001982444", + "JUVF": "0000714712", + "CCTC": "0001477960", + "PMI": "0002030617", + "PMVP": "0001699382", + "CING": "0001862150", + "DWNX": "0000927719", + "KNDI": "0001720250", + "BGSF": "0001474903", + "INLF": "0001991592", + "SFWL": "0001863218", + "BYSI": "0001677940", + "MNOV": "0001226616", + "PCM": "0000908187", + "PRPL": "0001643953", + "HAIAF": "0001848861", + "CEV": "0001074692", + "NUVR": "0000071557", + "USPCY": "0001939479", + "SLND": "0001883814", + "DWTX": "0001818844", + "WAMFF": "0001893899", + "BTMD": "0001819253", + "GECC": "0001675033", + "SEAT": "0001856031", + "CLST": "0001849867", + "AUXXF": "0001725603", + "ALOT": "0000008146", + "SLMT": "0001939965", + "MCHX": "0001224133", + "BTCS": "0001436229", + "AVD": "0000005981", + "XTIA": "0001529113", + "CCIF": "0001517767", + "XTNT": "0001453593", + "YTRA": "0001516899", + "SNT": "0001993727", + "MHH": "0001437226", + "CYPH": "0001509745", + "IMAQ": "0001846235", + "PTHS": "0001919246", + "NA": "0001872302", + "IBIO": "0001420720", + "UHG": "0001830188", + "BRID": "0000014177", + "THMG": "0000711034", + "AEI": "0001750106", + "SOHOB": "0001313536", + "RIBB": "0002035016", + "HPAI": "0002001699", + "FSI": "0001069394", + "VGAS": "0001841425", + "SYHBF": "0001541190", + "SRTS": "0001494891", + "BGM": "0001779578", + "TEAD": "0001454938", + "UPXI": "0001775194", + "BYFC": "0001001171", + "NKGFF": "0001839154", + "HANNF": "0001123267", + "SYPR": "0000864240", + "ATHE": "0001131343", + "ACET": "0001720580", + "EEA": "0000791718", + "LGCL": "0001954694", + "KGFMF": "0001853889", + "THCH": "0001877333", + "PGZ": "0001557523", + "UFI": "0000100726", + "AIRG": "0001272842", + "VLT": "0000846671", + "WFCF": "0001360565", + "AFCG": "0001822523", + "GRWG": "0001604868", + "XCH": "0001979887", + "IFRX": "0001708688", + "CXH": "0000847411", + "FORA": "0001829280", + "BLNE": "0001534708", + "FNUC": "0001769697", + "AOTVF": "0001407582", + "STLE": "0000779227", + "VHC": "0001082324", + "HOVR": "0001930021", + "LIVG": "0001593549", + "ANVS": "0001477845", + "TZOO": "0001133311", + "CRT": "0000881787", + "LFT": "0001547546", + "NOMA": "0001994214", + "LFS": "0002030277", + "PMVC": "0001807765", + "OTH": "0002067767", + "HOUR": "0001874875", + "WSHP": "0002048271", + "GAIA": "0001089872", + "DMNIF": "0002000640", + "IBO": "0001834105", + "IZEA": "0001495231", + "KSCP": "0001600983", + "LTCN": "0001732406", + "RFL": "0001713863", + "ELBM": "0001907184", + "SOTK": "0000806172", + "ASRV": "0000707605", + "GPMT": "0001703644", + "FNGR": "0001602409", + "RSF": "0001644771", + "PRTS": "0001378950", + "FLD": "0001889123", + "CDLX": "0001666071", + "PAVM": "0001624326", + "CTOR": "0001851484", + "RYM": "0001800637", + "GEG": "0001831096", + "PYYX": "0000939930", + "HLP": "0001855557", + "MYPS": "0001823878", + "IBAC": "0001998781", + "JANL": "0001133062", + "DRIO": "0001533998", + "OPHC": "0001288855", + "ZBAI": "0001755058", + "RGS": "0000716643", + "CTM": "0001877939", + "PVL": "0001520048", + "FEAM": "0001888654", + "LRDC": "0001442492", + "TMRC": "0001445942", + "EDVR": "0001917599", + "SNTL": "0000889353", + "CLNN": "0001822791", + "HAO": "0001954594", + "BDL": "0000012040", + "CDAQF": "0001851909", + "RTGN": "0001836295", + "TLGYF": "0001879814", + "FSEA": "0001943802", + "AASP": "0000930245", + "ACRV": "0001781174", + "VOC": "0001505413", + "ACTU": "0001652935", + "MDNC": "0001931055", + "MDIA": "0001784254", + "SDM": "0002014955", + "PODC": "0001940177", + "OKUR": "0001637715", + "AIRT": "0000353184", + "SELF": "0001031235", + "KBSX": "0002014254", + "MASK": "0001993097", + "ICCC": "0000811641", + "HYOR": "0001070789", + "CAPN": "0002024203", + "VIPRF": "0001684662", + "MXE": "0000863900", + "POSC": "0000844985", + "NORD": "0001011060", + "TCRX": "0001783328", + "COCH": "0001840877", + "MPU": "0001953021", + "DDC": "0001808110", + "NSTS": "0001881592", + "WBX": "0001866501", + "EDRY": "0001731388", + "VRDR": "0001506929", + "ZTEK": "0001904501", + "FTCI": "0001828161", + "DXR": "0000027367", + "VHUB": "0001972234", + "FIEE": "0001467761", + "SJ": "0001753673", + "DCGO": "0001822359", + "LVO": "0001491419", + "MNY": "0001974044", + "JMM": "0000838131", + "LUNG": "0001127537", + "FRMM": "0001690080", + "SODI": "0000091668", + "YI": "0001738906", + "ELTK": "0001024672", + "FMFG": "0001698022", + "STKS": "0001399520", + "IMA": "0001835579", + "LEAT": "0001456189", + "RRGB": "0001171759", + "UCL": "0001775898", + "PLNH": "0001813452", + "GNS": "0001847806", + "YIBO": "0001868395", + "GMHS": "0002000530", + "ECOR": "0001560258", + "CATO": "0000018255", + "APWC": "0001026980", + "EURK": "0002000410", + "UEIC": "0000101984", + "NXXT": "0001817004", + "KZR": "0001645666", + "TIL": "0001789769", + "LFVN": "0000849146", + "TGE": "0002053456", + "PSIG": "0001997201", + "IDXG": "0001054102", + "UBXG": "0001888525", + "HSPT": "0002032950", + "LVPA": "0000831378", + "HFBL": "0001500375", + "OSTX": "0001795091", + "QSEP": "0001103795", + "GROV": "0001841761", + "AGIG": "0001156041", + "IMMP": "0001506184", + "HYFT": "0001715925", + "ZOOZ": "0001992818", + "WHEN": "0000943535", + "GPUS": "0000896493", + "BSPA": "0002094107", + "CTNT": "0001951667", + "LOAN": "0001080340", + "AVX": "0001826397", + "KRFG": "0000774415", + "SCLX": "0001820190", + "GPGCF": "0001813241", + "AZASF": "0001701599", + "CNVS": "0001173204", + "EDSA": "0001540159", + "SORA": "0002033515", + "TRT": "0000732026", + "GLBS": "0001499780", + "MREO": "0001719714", + "MGX": "0001785279", + "JAGU": "0002039273", + "TCBS": "0001849466", + "INDO": "0001757840", + "BENF": "0001775734", + "NDLS": "0001275158", + "BEWFF": "0001113152", + "INKT": "0001840229", + "GENK": "0001891856", + "ELUT": "0001708527", + "ALCY": "0001901336", + "FMY": "0001319183", + "RKHNF": "0001422532", + "SCWO": "0000933972", + "SPWH": "0001132105", + "SACH": "0001682220", + "BOF": "0001962481", + "ARAY": "0001138723", + "ALGS": "0001799448", + "XLO": "0001840233", + "HOWL": "0001785530", + "RDEXF": "0001856082", + "DRYGF": "0002006413", + "PETS": "0001040130", + "KLXE": "0001738827", + "BREZ": "0002095443", + "SRXH": "0001471727", + "BCHT": "0000728385", + "OAKV": "0001865429", + "AMPG": "0001518461", + "STI": "0001881551", + "PLUT": "0001933021", + "NTRP": "0000788611", + "ABVE": "0001979484", + "INVU": "0000862651", + "ONMD": "0001849380", + "BEAT": "0001779372", + "OMEX": "0000798528", + "FFAI": "0001805521", + "WYY": "0001034760", + "BKHA": "0002000775", + "MGLD": "0001005101", + "ISTKF": "0001678748", + "BLGO": "0000880242", + "IEHC": "0000050292", + "HGBL": "0000849145", + "STG": "0001723935", + "AXIL": "0001718500", + "LINK": "0000828146", + "HMR": "0002029471", + "MLGO": "0001800392", + "BWEN": "0001120370", + "KANP": "0001230058", + "CPIX": "0001087294", + "DSWL": "0000946936", + "KNRX": "0001982960", + "BRAG": "0001867834", + "COLA": "0002028201", + "CVU": "0000889348", + "MATH": "0001682241", + "HCHL": "0002046656", + "POCI": "0000867840", + "LGL": "0000061004", + "SKBL": "0002031009", + "MIRA": "0001904286", + "WTHVF": "0001562530", + "RNXT": "0001574094", + "ESHA": "0001918661", + "MKTW": "0001805651", + "OFS": "0001487918", + "ATOS": "0001488039", + "MDAI": "0001833498", + "PXS": "0001640043", + "CHEV": "0001459188", + "CPPMF": "0001968617", + "GLXZ": "0000013156", + "NAMI": "0001967631", + "MHUBF": "0001869137", + "HOLO": "0001841209", + "ALAR": "0001725332", + "LSTA": "0000320017", + "USEG": "0000101594", + "PRPO": "0001043961", + "AAME": "0000008177", + "APT": "0000884269", + "MLCI": "0002051820", + "BIOF": "0001549145", + "BRFH": "0001487197", + "ASFH": "0001828748", + "MMCP": "0001879293", + "FKWL": "0000722572", + "EPWKF": "0001900720", + "SMOFF": "0001538189", + "IMTCF": "0001288268", + "LISMF": "0001643715", + "ESLA": "0001844417", + "RYES": "0001424864", + "DOMH": "0000012239", + "RLYB": "0001739410", + "FOFA": "0001871181", + "REED": "0001140215", + "BHM": "0001903382", + "NTRB": "0001676047", + "GRML": "0001907223", + "XHG": "0001769256", + "TMDE": "0002009714", + "BRIA": "0002000230", + "FSTJ": "0001525306", + "STSS": "0001737995", + "ESAUF": "0001657800", + "TELO": "0001971532", + "RDI": "0000716634", + "ACFN": "0000880984", + "QETA": "0001978528", + "ELWT": "0002063863", + "FCO": "0000876717", + "SAGGF": "0001727370", + "RMCO": "0001843656", + "VTSI": "0001085243", + "CNTY": "0000911147", + "XBP": "0001839530", + "LEEEF": "0001711141", + "TAOX": "0001571934", + "INIS": "0001038277", + "PTLE": "0002016337", + "GIBO": "0002034520", + "QNTO": "0001391933", + "GKOR": "0001474558", + "GRF": "0000850027", + "MAMO": "0001952853", + "DUO": "0001750593", + "LITB": "0001523836", + "ZYBT": "0001975641", + "INCR": "0001857030", + "BGL": "0002019435", + "MBBC": "0001835385", + "AVAI": "0001740797", + "PRT": "0001724009", + "TETEF": "0001900679", + "LITS": "0001262104", + "ASTI": "0001350102", + "DTSQ": "0002017950", + "MSSAF": "0001882464", + "ATRA": "0001604464", + "JG": "0001737339", + "COHN": "0001270436", + "RGCCF": "0001918151", + "NTWK": "0001039280", + "IXHL": "0001873875", + "NMTC": "0001500198", + "BDCO": "0000793306", + "VNOV": "0001699709", + "SFCX": "0001624985", + "SEOVF": "0001491434", + "UAVS": "0000008504", + "RDAC": "0002018145", + "STLNF": "0001729653", + "SCYX": "0001178253", + "AAPI": "0001134982", + "EONR": "0001842556", + "FOXX": "0002013807", + "LIVE": "0001045742", + "PFAI": "0002032755", + "SQNS": "0001383395", + "EHTH": "0001333493", + "SNSE": "0001829802", + "SKLZ": "0001801661", + "MRNO": "0001988776", + "ATCMF": "0001567663", + "PTNT": "0000911216", + "SMXT": "0001519472", + "SPCB": "0001291855", + "IBATF": "0001786318", + "BCG": "0001953984", + "KMRK": "0002049187", + "KCCFF": "0001726906", + "ENGS": "0001971828", + "CSTE": "0001504379", + "CELU": "0001752828", + "CRVO": "0001053691", + "RDGL": "0001449349", + "DYNR": "0001111741", + "SPND": "0000867038", + "TURB": "0001963439", + "YYAI": "0001674440", + "NXTC": "0001661059", + "JRSH": "0001696558", + "HLEO": "0001953988", + "RMTI": "0001041024", + "ZDGE": "0001667313", + "ROLR": "0001947210", + "SKIL": "0001774675", + "OESX": "0001409375", + "FTEK": "0000846913", + "NALG": "0001059689", + "PHUN": "0001665300", + "RCT": "0002027360", + "MOBX": "0001855467", + "GWH": "0001819438", + "PPSI": "0001449792", + "IPWR": "0001507957", + "PRKR": "0000914139", + "CREX": "0001356093", + "NCEW": "0001968043", + "VERU": "0000863894", + "LOCL": "0001840780", + "GOCO": "0001808220", + "CDIX": "0000811222", + "CTSO": "0001175151", + "HAFG": "0001367993", + "STRR": "0001210708", + "TLPH": "0001427925", + "RAVE": "0000718332", + "TKRFF": "0001368845", + "WSTRF": "0001621906", + "WELNF": "0001877557", + "RMXI": "0001970743", + "NSYS": "0000722313", + "GDHG": "0001928340", + "SST": "0001805833", + "KDKGF": "0000872699", + "FOFO": "0002060083", + "QZMRF": "0000811522", + "PDSB": "0001472091", + "MCAG": "0001859035", + "VIVO": "0001681348", + "NSFDF": "0001009922", + "UNXP": "0001751707", + "TACT": "0001017303", + "PXLW": "0001040161", + "KWM": "0002000756", + "JFU": "0001619544", + "ITHUF": "0001643154", + "KOSS": "0000056701", + "RAND": "0000081955", + "KFFB": "0001297341", + "RADX": "0001949257", + "AZZTF": "0001706404", + "SRLZF": "0000861972", + "CXXIF": "0000831609", + "EQTRF": "0001635729", + "WAVE": "0001846715", + "JETMF": "0001846084", + "AHMA": "0002010959", + "BIOX": "0001769484", + "KPLT": "0001785424", + "RITR": "0001951229", + "VPLM": "0001410738", + "GIFT": "0001760233", + "CULP": "0000723603", + "GROW": "0000754811", + "RNTX": "0001420565", + "NTIP": "0001065078", + "HYEX": "0001630176", + "CSDX": "0001106861", + "NTZ": "0000900391", + "INLX": "0001081745", + "EKSO": "0001549084", + "YSXT": "0001993463", + "RSRV": "0000083350", + "HWAUF": "0001817161", + "PLUR": "0001158780", + "TOON": "0001355848", + "AIFF": "0000803578", + "VGES": "0001746119", + "ONEG": "0002030834", + "AIRE": "0001859199", + "MDBH": "0001934642", + "ACCS": "0000843006", + "RPMT": "0001437283", + "BAYA": "0001969475", + "OPAD": "0001825024", + "CNTM": "0001895249", + "WPRT": "0001370416", + "DYAI": "0001213809", + "LVLU": "0001780201", + "DXLG": "0000813298", + "SFCO": "0001831523", + "EPOW": "0001780731", + "INMB": "0001711754", + "REFR": "0000793524", + "BTAI": "0001720893", + "CGTL": "0001967822", + "RYET": "0001873454", + "AVNI": "0001113313", + "VNCE": "0001579157", + "APLM": "0001944885", + "FGNX": "0001591890", + "EVAX": "0001828253", + "EMGDF": "0001790607", + "USIO": "0001088034", + "LGVN": "0001721484", + "LPSN": "0001102993", + "QTZM": "0001663038", + "ANGH": "0001871983", + "SWAG": "0001872525", + "INUV": "0000829323", + "KTCC": "0000719733", + "JSDA": "0001083522", + "OMH": "0001944902", + "AACG": "0001420529", + "ATNM": "0001388320", + "TPCS": "0001328792", + "CLRCF": "0001903392", + "HERZ": "0000880406", + "NEPH": "0001196298", + "PC": "0001998056", + "NAAS": "0001712178", + "SSGC": "0001584693", + "USREF": "0002037786", + "ABLV": "0001957489", + "BRLS": "0001852973", + "FATN": "0001993400", + "CBLO": "0001882781", + "AMBI": "0001937441", + "UG": "0000101295", + "HSPOF": "0001946021", + "ZDAI": "0001966678", + "BCTX": "0001610820", + "CVV": "0000766792", + "TOP": "0001848275", + "MDWK": "0001295514", + "HRGN": "0001563665", + "PHNMF": "0001720553", + "VEEA": "0001840317", + "CVM": "0000725363", + "PGZFF": "0001566073", + "BLIV": "0001982448", + "CCEL": "0000862692", + "ATCH": "0001963088", + "RCON": "0001442620", + "ZLME": "0001489300", + "CIF": "0000833021", + "DTST": "0001419951", + "POM": "0001877971", + "BOSC": "0001005516", + "SAGT": "0002029138", + "BONXF": "0001544770", + "AYTU": "0001385818", + "STKE": "0001846839", + "WBQNL": "0001785494", + "GDST": "0001858007", + "SLGB": "0001987189", + "SUUN": "0002011053", + "ATCX": "0001684688", + "KYNB": "0000921299", + "TVRD": "0001346830", + "WBSR": "0001645155", + "AWRE": "0001015739", + "VASO": "0000839087", + "UONE": "0001041657", + "EMCGF": "0001869601", + "NRDE": "0001759546", + "BEEM": "0001398805", + "POAS": "0002024258", + "ABVC": "0001173313", + "CRWS": "0000025895", + "GRAN": "0002027722", + "VBIX": "0000797542", + "BAFN": "0001649739", + "ADGM": "0002006986", + "NRSN": "0001875091", + "FARM": "0000034563", + "EHSI": "0001089815", + "HYPD": "0001682639", + "NSRX": "0002029039", + "PRKA": "0001297937", + "GDSRF": "0001427901", + "RAPH": "0001415397", + "MILIF": "0001866460", + "BMNM": "0001275477", + "SDST": "0001831979", + "QCLS": "0001321834", + "TRXA": "0001437750", + "KNGRF": "0001191832", + "FUSE": "0002033383", + "LSF": "0001650696", + "SNBR": "0000827187", + "UFG": "0002021688", + "PMEC": "0001891944", + "JXG": "0001546383", + "TELA": "0001561921", + "XCUR": "0001698530", + "SNTI": "0001854270", + "MRMD": "0001522767", + "ZEFIF": "0001945138", + "LIXT": "0001335105", + "PETV": "0001512922", + "JL": "0001948436", + "TINFF": "0001864597", + "MVO": "0001371782", + "NOM": "0000899782", + "EZGO": "0001806904", + "APAAF": "0001419336", + "ARAI": "0001818274", + "KDOZF": "0001318482", + "IGC": "0001326205", + "FEMY": "0001339005", + "GRNQ": "0001597846", + "CLPS": "0001724542", + "SER": "0001708599", + "AAUAF": "0001015647", + "SRGZ": "0001401835", + "PSQH": "0001847064", + "ROMJF": "0001742195", + "LFWD": "0001607962", + "USGDF": "0001726159", + "AIIO": "0001932737", + "PASG": "0001787297", + "BRKCF": "0001019742", + "LEXX": "0001348362", + "FMST": "0001935418", + "MYO": "0001369290", + "SMX": "0001940674", + "ETST": "0001538495", + "CFND": "0002044327", + "KLNG": "0001110607", + "REVFF": "0001002366", + "DARE": "0001401914", + "PFSB": "0001967656", + "ASPC": "0001890361", + "JOB": "0000040570", + "KARX": "0001729637", + "RYOJ": "0002012600", + "VNTG": "0002027160", + "STAK": "0002002453", + "SFRX": "0001106213", + "FEDU": "0001709819", + "CPOP": "0001807389", + "MKDW": "0001991332", + "QRHC": "0001442236", + "TDTH": "0001983550", + "BRNS": "0001828185", + "WIMI": "0001770088", + "PSTV": "0001095981", + "ATHR": "0002026353", + "ICCM": "0001584371", + "WNDW": "0001071840", + "RAIN": "0002028293", + "YXT": "0001872090", + "GSIW": "0001954269", + "BOLD": "0001782303", + "NHTC": "0000912061", + "AERT": "0001853044", + "ITHR": "0001919191", + "BHIC": "0001784440", + "BTM": "0001901799", + "ZBAO": "0001966750", + "PHGE": "0001739174", + "FLUX": "0001083743", + "PSHG": "0001481241", + "ARKR": "0000779544", + "NEUP": "0001191070", + "CRMZ": "0000315958", + "LASE": "0001807887", + "GAME": "0001714562", + "APUS": "0001894525", + "NIXX": "0001462223", + "TPET": "0001898766", + "QNTM": "0001771885", + "NEON": "0000087050", + "CYCN": "0001755237", + "AITX": "0001498148", + "MODD": "0001074871", + "WKHS": "0001425287", + "SKYE": "0001516551", + "HBIO": "0001123494", + "VNRX": "0000093314", + "VTGN": "0001411685", + "TIGCF": "0001387473", + "CYAB": "0002032341", + "BIRD": "0001653909", + "TXMD": "0000025743", + "JVA": "0001007019", + "BZDLF": "0001527038", + "LSH": "0001996192", + "UTSI": "0001030471", + "SDEV": "0001389545", + "OTLK": "0001649989", + "SELX": "0001990950", + "ECRO": "0001300317", + "MNDO": "0001119083", + "TPST": "0001544227", + "WYHG": "0001999860", + "DFLI": "0001847986", + "COGDF": "0001557440", + "IGTA": "0001866838", + "ORIO": "0001602842", + "AEON": "0001837607", + "SPEX": "0002099188", + "CNF": "0001733868", + "RCG": "0000919567", + "BZFD": "0001828972", + "MLSS": "0000855683", + "NYC": "0001595527", + "BFRG": "0001829247", + "EVTV": "0001563568", + "GTHP": "0000924515", + "TBTC": "0001090396", + "BMR": "0001899005", + "CYN": "0001874097", + "VIPZ": "0001832161", + "CNOBF": "0001683408", + "RDGMF": "0001820025", + "BURU": "0001814215", + "CRIS": "0001108205", + "CKX": "0000352955", + "PLSM": "0002064764", + "SNNF": "0002072421", + "YHC": "0001843165", + "POWMF": "0001988634", + "TRSG": "0001943444", + "DAIO": "0000351998", + "EHLD": "0002032779", + "STLY": "0000797465", + "SCIA": "0000830616", + "AAQL": "0001672571", + "FENG": "0001509646", + "DFNS": "0001787518", + "LIMX": "0001803977", + "TARSF": "0001409036", + "EQS": "0000878932", + "AUST": "0001817740", + "JGLDF": "0001686000", + "IINN": "0001837493", + "AQUC": "0001861063", + "IPM": "0001355839", + "XOS": "0001819493", + "COCP": "0001412486", + "BHSIF": "0001432588", + "YTFD": "0001311673", + "CHAI": "0001649009", + "KAYS": "0001530746", + "RVP": "0000946563", + "ICMB": "0001578348", + "DOGZ": "0001707303", + "PRHI": "0001502292", + "PVCT": "0000315545", + "PLAG": "0001117057", + "RMCF": "0001616262", + "MMTIF": "0001085921", + "PRZO": "0001916241", + "OBAI": "0001756064", + "NNVC": "0001379006", + "VYNE": "0001566044", + "CLOQ": "0001437517", + "MSGM": "0001821175", + "TTIPF": "0001877778", + "GNOLF": "0001261002", + "MXC": "0000066418", + "PAYD": "0001017655", + "VRHI": "0002078149", + "IRVRF": "0001666782", + "PLRZ": "0001893645", + "UPLD": "0001505155", + "LIQT": "0001307579", + "EPSM": "0001883437", + "FTHM": "0001753162", + "USEA": "0001912847", + "NPRFF": "0001859022", + "AUID": "0001534154", + "CMGHF": "0001169760", + "MSAI": "0001863990", + "RVSN": "0001743905", + "BANL": "0001914805", + "SNAL": "0001886894", + "GUER": "0001832487", + "JSPR": "0001788028", + "TLF": "0000909724", + "CHKR": "0001524769", + "LHAI": "0002017758", + "CNTMF": "0001758124", + "CTXR": "0001506251", + "YMT": "0001991605", + "ACCL": "0002038378", + "DLPN": "0001282224", + "AIDX": "0001139685", + "SPRS": "0000747540", + "GOVB": "0001978811", + "PBMLF": "0001319150", + "REE": "0001843588", + "TRGEF": "0001989815", + "APCX": "0001070050", + "DUKR": "0001638911", + "RITE": "0001096296", + "ALLR": "0001860657", + "CDT": "0001896212", + "CMHSF": "0001889352", + "HHS": "0000045919", + "MOBQ": "0001084267", + "SMSI": "0000948708", + "LTRN": "0001763950", + "SPST": "0001192323", + "IVFH": "0000312257", + "TVGN": "0001860871", + "MTWO": "0001753373", + "GEBRF": "0001570843", + "RLBY": "0000034285", + "RNGE": "0001438943", + "GYRO": "0001589061", + "HUDI": "0001791725", + "ULTHF": "0001850269", + "KTTA": "0001841330", + "EUDA": "0001847846", + "OTLC": "0000908259", + "INTZ": "0000736012", + "NZERF": "0001509705", + "MOGU": "0001743971", + "BIAF": "0001712762", + "VAUCF": "0001723047", + "DQWS": "0001652561", + "CTRM": "0001720161", + "CUE": "0001645460", + "CRVW": "0001377149", + "SURG": "0001392694", + "IVF": "0001417926", + "BKUCF": "0001463978", + "ZGM": "0002011458", + "AHT": "0001232582", + "LRE": "0001888980", + "IAALF": "0001450894", + "AMOD": "0001862463", + "RECT": "0001995116", + "STCB": "0001539850", + "AUIAF": "0001568183", + "ICU": "0001831868", + "COOT": "0001959994", + "MSBB": "0001967306", + "GMVMF": "0001495730", + "LGCB": "0001969401", + "THH": "0002044241", + "MRKR": "0001094038", + "CCM": "0001472072", + "PAPL": "0001938109", + "GTEC": "0001735041", + "IRIX": "0001006045", + "SAIH": "0001847075", + "NNUP": "0000888981", + "ZEOX": "0001557376", + "RMESF": "0001358654", + "APHP": "0001771995", + "GNTA": "0001838716", + "GREE": "0001844971", + "WETH": "0001826660", + "BHV": "0001169034", + "FAMI": "0001701261", + "AIJTY": "0001713923", + "NAII": "0000787253", + "MAPPF": "0001493130", + "MYND": "0001708441", + "PASW": "0001897532", + "CRWE": "0001103833", + "REBN": "0001707910", + "RWAX": "0001119190", + "ABIT": "0001095146", + "CABR": "0002020737", + "EDTK": "0001782309", + "BESS": "0001066764", + "MDRR": "0001654595", + "RGNT": "0001912966", + "JF": "0001716338", + "QVCGA": "0001355096", + "UUU": "0000102109", + "MGIH": "0001903995", + "KPEA": "0001502557", + "GIGM": "0001105101", + "NVNI": "0001965143", + "UPYY": "0001677897", + "BGAVF": "0001500620", + "AWHL": "0000926617", + "GNVR": "0001792941", + "PDC": "0001944399", + "INTI": "0001042418", + "AIRI": "0001009891", + "ELSE": "0000351789", + "LGPS": "0002040290", + "YQ": "0001821468", + "LDDD": "0001892316", + "PCSV": "0001122020", + "FDCT": "0001722731", + "TOPP": "0001960847", + "MWYN": "0002030522", + "ILAL": "0001657214", + "RBNE": "0002039060", + "BFNH": "0001310488", + "VVOS": "0001716166", + "SKKY": "0001546853", + "LPCN": "0001535955", + "AUSI": "0000826253", + "HIND": "0001427570", + "IEGCF": "0001537317", + "PHIO": "0001533040", + "SVRN": "0001869467", + "TOPS": "0001296484", + "SEED": "0001321851", + "LRRIF": "0001992500", + "NEWH": "0001371128", + "PFHO": "0001138476", + "AHNRF": "0001304409", + "CCHH": "0002074123", + "ALTUF": "0001977971", + "HIRU": "0000925779", + "COPAF": "0001420049", + "CISO": "0001777319", + "INTJ": "0001916416", + "INTS": "0001567264", + "ZJYL": "0001837821", + "HUIZ": "0001778982", + "CSAI": "0001709628", + "NCI": "0001916331", + "GAUZ": "0001781446", + "UGRO": "0001706524", + "INIKF": "0001928722", + "AIEV": "0001912582", + "GTBP": "0000109657", + "INAB": "0001740279", + "GCDT": "0001926293", + "OSRH": "0001840425", + "BGI": "0001179821", + "DBGI": "0001668010", + "NTCL": "0001927578", + "CURX": "0002025942", + "BRN": "0000010048", + "AGPU": "0001446159", + "CAPT": "0001967478", + "BNET": "0000875729", + "RLYGF": "0001829538", + "ZSTK": "0001790169", + "ABCP": "0000020639", + "NWGL": "0001948294", + "CHOW": "0002041829", + "SLAI": "0001517496", + "BNKK": "0001760903", + "SWVL": "0001875609", + "CFOO": "0001310630", + "GLXG": "0001905920", + "HKPD": "0002007702", + "BNGO": "0001411690", + "MDCX": "0001997296", + "BTTC": "0002034400", + "MBAI": "0001610590", + "GXAI": "0001895618", + "ALUR": "0001964979", + "TRAW": "0001130598", + "BON": "0001816815", + "EFOI": "0000924168", + "UEEC": "0001096938", + "CMCT": "0000908311", + "SUND": "0001171838", + "IDAI": "0001718939", + "SGRP": "0001004989", + "BCDA": "0000925741", + "JUNS": "0001679628", + "QMCI": "0001101433", + "QNRX": "0001671502", + "WVVI": "0000838875", + "FEBO": "0001957001", + "KLGDF": "0001901931", + "MTEK": "0001872964", + "GTIM": "0000825324", + "JPOTF": "0001061612", + "YAAS": "0001964946", + "NGLD": "0001605481", + "KAPA": "0001962011", + "QYOUF": "0001650287", + "RSMXF": "0001858994", + "OCLN": "0001419793", + "BTOC": "0001972529", + "CVAT": "0001376793", + "MBRX": "0001659617", + "VCGMF": "0001650196", + "TAOP": "0001552670", + "VERTF": "0001178526", + "AWCA": "0001021917", + "TOMZ": "0000314227", + "JZ": "0001852440", + "NXPL": "0001058307", + "SCNX": "0001382574", + "TJGC": "0001969928", + "CCOOF": "0001853599", + "SUGP": "0001969863", + "IVDN": "0001190370", + "GURE": "0000885462", + "NRIS": "0001603793", + "BLTH": "0001487718", + "LESL": "0001821806", + "CAHO": "0001678105", + "KTEL": "0000845819", + "PETZ": "0001684425", + "ULYX": "0001603652", + "ORGN": "0001802457", + "WKSP": "0001096275", + "RAY": "0001948443", + "PBSV": "0001304161", + "FRECF": "0001816133", + "DSY": "0001999297", + "BTBD": "0001718224", + "GDTC": "0001873093", + "MAXN": "0001796898", + "SPPL": "0001948697", + "AQMS": "0001621832", + "CLEV": "0001414382", + "SNGX": "0000812796", + "COSM": "0001474167", + "BRGX": "0001593184", + "BTCT": "0001796514", + "BFRI": "0001858685", + "ELECF": "0001817083", + "TRIB": "0000888721", + "GGRP": "0001854445", + "BNZI": "0001826011", + "MSW": "0001956166", + "ELOG": "0002013320", + "GFAI": "0001804469", + "MARPS": "0000062362", + "ADIA": "0001160420", + "CMMB": "0001534248", + "PCMC": "0001141964", + "QURT": "0001549631", + "PURE": "0001006028", + "BMGL": "0002004489", + "EDUC": "0000031667", + "MMA": "0001981519", + "BLIN": "0001378590", + "GULTU": "0001565146", + "APMCF": "0001628935", + "WETO": "0001941158", + "MTEX": "0001056358", + "ETS": "0002053641", + "EBON": "0001799290", + "CVKD": "0001937993", + "AGAE": "0001708341", + "IMNN": "0000749647", + "RMSL": "0001412126", + "JBDI": "0001964314", + "SVBL": "0001031093", + "CLRB": "0001279704", + "BCAB": "0001826892", + "HNOI": "0001342916", + "ARTW": "0000007623", + "EEIQ": "0001781397", + "BIVI": "0001580149", + "FCCI": "0001807689", + "FXBY": "0001068897", + "AGRZ": "0002009233", + "WGRX": "0002030763", + "PMNT": "0001849221", + "UECXF": "0001834607", + "TOVX": "0000894158", + "VSEE": "0001864531", + "ACXP": "0001736243", + "AIMD": "0001014763", + "CETY": "0001329606", + "STSBF": "0001307926", + "VRME": "0001104038", + "CENN": "0001707919", + "HGTXU": "0000862022", + "SINT": "0001269026", + "CETI": "0001935092", + "URZEF": "0001398713", + "FWFW": "0001492617", + "CNFN": "0001352952", + "TRBMF": "0001406944", + "NCEL": "0001783036", + "HLRTF": "0001418149", + "CXAI": "0001820875", + "LILIF": "0001689448", + "SFHG": "0001926792", + "GWTI": "0001572386", + "AWX": "0001061069", + "OST": "0001803407", + "AZI": "0001959726", + "OFAL": "0002036307", + "LEDS": "0001333822", + "BLRX": "0001498403", + "CVR": "0000019871", + "KXIN": "0001713539", + "STKH": "0001828098", + "NXTT": "0001784970", + "USIC": "0001940366", + "SNTW": "0001619096", + "SABOF": "0001896752", + "TKLF": "0001836242", + "PCLA": "0002018462", + "JTAI": "0001861622", + "PRSO": "0000890394", + "SRRE": "0001083490", + "DTSS": "0001631282", + "ENDMF": "0001524326", + "GBMIF": "0001715272", + "PAXH": "0001350156", + "ASNS": "0001141284", + "RETO": "0001687277", + "BCLI": "0001137883", + "BICX": "0001443863", + "DLXY": "0002025218", + "IHT": "0000082473", + "SDCH": "0001022505", + "FTSP": "0001319643", + "STQN": "0000847942", + "DSS": "0000771999", + "ECTM": "0001487798", + "MGNC": "0001949864", + "KWIK": "0001884164", + "CLWT": "0001026662", + "WLFFF": "0001544883", + "SBDS": "0001870600", + "RVPH": "0001742927", + "CALC": "0001534133", + "ZTSTF": "0001047227", + "NOTV": "0000720154", + "ELDCF": "0001572236", + "AWLIF": "0001866034", + "TSEOF": "0001519061", + "HOTH": "0001711786", + "UUUFF": "0002056751", + "ADTI": "0001420924", + "HWNI": "0001413891", + "HLYK": "0001680139", + "USAQ": "0000856984", + "MTR": "0000313364", + "ALDS": "0001755101", + "LNAI": "0001527728", + "SSM": "0001840416", + "SNYR": "0001562733", + "MCUJF": "0001133519", + "MRM": "0001819704", + "ZCRMF": "0001425061", + "FNFI": "0001065823", + "AMS": "0000744825", + "VRSSF": "0001879001", + "GLE": "0001908705", + "GPMTF": "0001677084", + "FTRK": "0002027262", + "SCND": "0000087802", + "INHD": "0001961847", + "HAMRF": "0001868866", + "MWG": "0001941500", + "INBP": "0001016504", + "GITS": "0001911545", + "TWOH": "0001494413", + "TBH": "0001903595", + "LHSW": "0002004024", + "LTUM": "0001415332", + "SNES": "0001680378", + "SOS": "0001346610", + "NMEX": "0001415744", + "MSN": "0000032621", + "HGYN": "0001324759", + "SEGG": "0001673481", + "GARWF": "0001403870", + "CETX": "0001435064", + "CEIN": "0001309082", + "HTOO": "0001819794", + "INEO": "0001933951", + "NIOMF": "0001937453", + "CPIVF": "0001712294", + "LPSIF": "0001472466", + "PWDY": "0001435617", + "ELVG": "0001741489", + "BOLT": "0001641281", + "APRE": "0001781983", + "IMRN": "0001660046", + "KRKR": "0001779476", + "ACON": "0001635077", + "AMST": "0001807166", + "TNON": "0001560293", + "ORESF": "0001481857", + "ALRTF": "0001930419", + "JYD": "0001938186", + "GRDX": "0001604191", + "IMIMF": "0001866146", + "XELB": "0001083220", + "GLGI": "0001088413", + "RNAZ": "0001829635", + "VYND": "0001745078", + "MRAI": "0001844392", + "HWH": "0001897245", + "AETN": "0000764630", + "IQST": "0001527702", + "DSNY": "0001099369", + "BMXI": "0001122993", + "NROM": "0000709005", + "EVGN": "0001574565", + "NIMU": "0000720762", + "CVSI": "0001510964", + "TCRI": "0001481443", + "FBGL": "0001938534", + "YCBD": "0001644903", + "IFBD": "0001815566", + "OLB": "0001314196", + "KPRX": "0001372514", + "REDRF": "0001898404", + "RTCJF": "0001381074", + "CELZ": "0001187953", + "KLYG": "0001372114", + "WCT": "0001990251", + "NYMXF": "0001018735", + "ARBB": "0001930179", + "ITOC": "0001970544", + "TRRFF": "0001713979", + "APM": "0001734005", + "EWSB": "0002013792", + "TULP": "0000875355", + "BASA": "0001448705", + "XAIR": "0001641631", + "MOJO": "0001414953", + "AITTF": "0001520556", + "LCFY": "0001875547", + "PMCB": "0001157075", + "ATON": "0001095435", + "STME": "0001493712", + "YJ": "0001759614", + "FGI": "0001864943", + "YHGJ": "0001042187", + "PCSA": "0001533743", + "YOTA": "0001907730", + "HSCS": "0001468492", + "SPFX": "0001807893", + "FMFC": "0002024656", + "GELS": "0001920092", + "CUPR": "0001995704", + "LOBO": "0001932072", + "RIME": "0000923601", + "NXL": "0001527352", + "NGTF": "0001593001", + "PIAC": "0000845385", + "WAFU": "0001716770", + "HCAI": "0001958399", + "VRRCF": "0001717695", + "MHUAF": "0001835615", + "HXHX": "0001936817", + "TLIH": "0001982012", + "BETRF": "0001464165", + "JCSE": "0001905511", + "BRTX": "0001505497", + "OHCFF": "0001735514", + "CLRO": "0000840715", + "APYP": "0001568969", + "EHGO": "0001879754", + "ADXN": "0001574232", + "RVYL": "0001419275", + "NDRA": "0001681682", + "ASTC": "0001001907", + "SERPY": "0002075349", + "TGHL": "0002024114", + "PN": "0002001288", + "SCKT": "0000944075", + "IZM": "0001854572", + "SYBX": "0001527599", + "MMTRS": "0000066496", + "GLNS": "0001375348", + "DKI": "0002058584", + "OLOX": "0001023994", + "KIQSF": "0001161814", + "NVNO": "0001661053", + "XBIO": "0001534525", + "SVUHF": "0001973368", + "LIMN": "0001971387", + "CWD": "0001627282", + "BCUFF": "0001477201", + "VSBGF": "0001757207", + "AMBO": "0001494558", + "ZCMD": "0001785566", + "NCNA": "0001709626", + "SKAS": "0001128281", + "CLGN": "0001631487", + "PLCKF": "0001848782", + "SYNX": "0001976443", + "ROYL": "0001694617", + "NWTG": "0001934245", + "BTCY": "0001630113", + "PUBC": "0001575858", + "AMLM": "0001356371", + "LUCY": "0001808377", + "DXYN": "0000029332", + "BABB": "0001123596", + "MYSE": "0001648960", + "MKZR": "0001550913", + "AIXC": "0001460702", + "CANF": "0001536196", + "MIMI": "0001998560", + "OXBR": "0001584831", + "BMRA": "0000073290", + "MSGY": "0002020228", + "TCRT": "0001107421", + "ATER": "0001757715", + "IONI": "0001580490", + "XPON": "0001894954", + "BITTF": "0001028357", + "GPOX": "0001673475", + "DEVS": "0001854480", + "BFGFF": "0001836503", + "MTVA": "0001638287", + "EJH": "0001769768", + "ILAG": "0001814963", + "HVGDF": "0000921968", + "NBLXF": "0001813419", + "WFF": "0001980210", + "IOTR": "0001997637", + "ODYY": "0001626644", + "PPBT": "0001614744", + "SSEBF": "0001771039", + "FBLG": "0001958777", + "TGL": "0001905956", + "MFBI": "0002024899", + "GVH": "0001978527", + "ADVB": "0001941029", + "AAMTF": "0001327899", + "SUNE": "0000022701", + "XWEL": "0001410428", + "FTFT": "0001066923", + "ESHSF": "0001907622", + "ADMT": "0000849401", + "ORKT": "0001979407", + "EUEMF": "0001993599", + "CDIO": "0001870144", + "AVPMF": "0001445467", + "XHLD": "0002030954", + "CIIT": "0001557798", + "CJMB": "0002032545", + "JCTC": "0000885307", + "SPHL": "0002002236", + "BKYI": "0001019034", + "MBIO": "0001680048", + "DROR": "0001282980", + "ERNA": "0000748592", + "YMAT": "0001875016", + "CBIH": "0001411057", + "BBGI": "0001099160", + "CLIK": "0002020027", + "XTLB": "0001023549", + "QUCY": "0001874252", + "ANY": "0001591956", + "IPDN": "0001546296", + "LUDG": "0001960262", + "ORGS": "0001460602", + "PBM": "0001985062", + "FRSX": "0001691221", + "THURF": "0001536811", + "BRQL": "0001854526", + "TOGI": "0001349706", + "TWAV": "0000746210", + "NVGLF": "0001607807", + "SOPA": "0001817511", + "MGN": "0001995075", + "HCWC": "0001948864", + "QNCX": "0001662774", + "MGRX": "0001938046", + "INBS": "0001725430", + "MITQ": "0001770236", + "CRE": "0002003977", + "MNTS": "0001781162", + "CREG": "0000721693", + "VS": "0001701963", + "AVCRF": "0001355736", + "SONM": "0001178697", + "EDHL": "0002024876", + "CPMV": "0000836564", + "TRCK": "0001045942", + "ZPHYF": "0001613979", + "AIHS": "0001711012", + "XERI": "0001481504", + "ONEI": "0001388295", + "DAIC": "0002033770", + "HCMC": "0000844856", + "MEGL": "0001881472", + "CAPS": "0000887151", + "CRCW": "0001688126", + "YDKG": "0001413745", + "GP": "0001584547", + "CLNV": "0001391426", + "PUCCF": "0001727428", + "BGLC": "0001737523", + "JWEL": "0001805594", + "SNTG": "0001810467", + "MAGE": "0001515317", + "RBOT": "0001812173", + "DRMA": "0001853816", + "CPCPF": "0001868050", + "ARTL": "0001621221", + "ZDPY": "0001279620", + "ADMQ": "0001588014", + "ACUT": "0001850767", + "ASBP": "0001847345", + "AKTX": "0001541157", + "SBFM": "0001402328", + "LCTC": "0001493137", + "CHNR": "0000793628", + "SOWG": "0001490161", + "WAI": "0001938865", + "LMRMF": "0001588837", + "MLEC": "0001937737", + "WLDS": "0001887673", + "VEST": "0001594968", + "JAGX": "0001585608", + "GHST": "0001121795", + "NGCG": "0001061040", + "TNMG": "0002013186", + "APVO": "0001671584", + "SILO": "0001514183", + "BIXT": "0001445815", + "CAPC": "0000814926", + "AIM": "0000946644", + "NOTE": "0001823466", + "WAST": "0001515139", + "GSUN": "0001826376", + "NXGL": "0001468929", + "STFS": "0002003061", + "FASLF": "0001731854", + "PULM": "0001574235", + "BRWC": "0001873213", + "POLA": "0001622345", + "BBBMF": "0001829809", + "ABTS": "0001864055", + "MI": "0001958713", + "AMZE": "0001880343", + "TDIC": "0002041338", + "RENX": "0001959023", + "HYFM": "0001695295", + "REVB": "0001810560", + "ALBT": "0001630212", + "RMSG": "0001983324", + "PRSI": "0000079661", + "SXTP": "0001946563", + "PAIYY": "0001757143", + "CYCU": "0001868419", + "RHEP": "0001004724", + "AMIX": "0001617867", + "YYGH": "0001985337", + "PMHS": "0001265521", + "VEEE": "0001855509", + "SKK": "0001991261", + "ENZN": "0000727510", + "DFSC": "0001889823", + "VIVS": "0001497253", + "APTOF": "0000882361", + "WTO": "0001789299", + "HTCR": "0001892322", + "GBR": "0000105744", + "XCRT": "0001138586", + "GREH": "0001084937", + "SHPH": "0001757499", + "CDTG": "0001793895", + "AIXN": "0000835662", + "ONFO": "0001825452", + "BLIS": "0001703625", + "SRCO": "0000318299", + "MSS": "0001892292", + "KIDZ": "0002022308", + "SNOA": "0001367083", + "QWTR": "0001487091", + "RDHL": "0001553846", + "WXM": "0001979610", + "SLXN": "0002022416", + "RUBI": "0001943421", + "DCX": "0001957413", + "SLE": "0001621672", + "AIPG": "0001289047", + "NTRX": "0001363598", + "TRLEF": "0001648636", + "ZSPC": "0001637147", + "GGLXF": "0000800523", + "BAOS": "0001811216", + "SEAV": "0001763660", + "ATXG": "0001650101", + "SOAR": "0001853070", + "LVRLF": "0001168981", + "VSTD": "0001898604", + "OCG": "0001776067", + "ENVB": "0000890821", + "EZRA": "0001812727", + "KCRD": "0001696025", + "CTTH": "0001035422", + "GTII": "0000356590", + "ALZN": "0001677077", + "TGNT": "0000846377", + "AZTR": "0001701478", + "HIHO": "0001026785", + "LMFA": "0001640384", + "PNYG": "0001784058", + "CHR": "0001738758", + "BNBX": "0000744452", + "XRTX": "0001729214", + "TOFB": "0000730349", + "FLYE": "0001975940", + "INDP": "0001857044", + "EGMCF": "0001199392", + "GNPX": "0001595248", + "JEM": "0002018222", + "GLVT": "0001693687", + "LIFD": "0001391135", + "GLMD": "0001595353", + "ABCFF": "0001284237", + "MEHA": "0001837254", + "IWSH": "0001279715", + "BQ": "0001815021", + "ICON": "0001995574", + "SQFT": "0001080657", + "MTNB": "0001582554", + "ENFY": "0000857949", + "LXEH": "0001814067", + "LINMF": "0001066130", + "GRI": "0001824293", + "SNRG": "0001652539", + "BTOG": "0001735556", + "AQB": "0001603978", + "KRTL": "0001288614", + "BYAH": "0001986247", + "WBUY": "0001946703", + "NCT": "0002018529", + "BRQSF": "0001650575", + "XITO": "0001651932", + "GRHI": "0000894501", + "AEMD": "0000882291", + "NXTS": "0001789192", + "ZNB": "0001747661", + "ORIS": "0001964664", + "PGOL": "0001080448", + "PMAX": "0002012096", + "CNEY": "0001780785", + "FCUV": "0001590418", + "BZYR": "0000724445", + "NCL": "0001923780", + "PSYCF": "0001847706", + "CMBMF": "0001738177", + "PLTYF": "0001433309", + "CODX": "0001692415", + "SRKZF": "0001723455", + "WTER": "0001532390", + "ITP": "0001358190", + "ATPC": "0001713210", + "CPHI": "0001106644", + "AUMN": "0001011509", + "CRCE": "0001911467", + "SYGCF": "0001917817", + "UK": "0001821424", + "NVSGF": "0001415758", + "MNDR": "0001976695", + "ELAB": "0001840563", + "WHLT": "0001025771", + "GRTX": "0001563577", + "FUNI": "0001502966", + "GEDC": "0001174891", + "DCOY": "0001615219", + "HIGR": "0001807616", + "WNW": "0001787803", + "CIMG": "0001527613", + "FMHS": "0001811999", + "VYCO": "0001424768", + "MVNC": "0001439264", + "MFON": "0001447380", + "GOVX": "0000832489", + "KITT": "0001849820", + "BGMS": "0001130166", + "IPSI": "0001591913", + "TWNPQ": "0002011954", + "NCRA": "0001756180", + "TUTH": "0001178660", + "IVDA": "0001397183", + "VCIG": "0001930510", + "TRNR": "0001785056", + "SGLY": "0001422892", + "LSBCF": "0001946399", + "SDOT": "0001701756", + "HCTI": "0001839285", + "SYRA": "0001922335", + "CPMD": "0001081938", + "BDRX": "0001643918", + "ZONE": "0001956741", + "GNLN": "0001743745", + "GWAV": "0001589149", + "RKDA": "0001469443", + "MDLK": "0001611046", + "SENR": "0001576197", + "LBSR": "0001172178", + "FDXTF": "0001970125", + "CLRI": "0001362516", + "VSME": "0001951294", + "OVTZ": "0001107280", + "BUDZ": "0001393772", + "CNRCF": "0001996586", + "PW": "0001532619", + "EZOO": "0001752372", + "SBLX": "0001086745", + "AIOS": "0001603993", + "TANH": "0001588084", + "REOS": "0001335288", + "NCPL": "0001414767", + "AUUD": "0001554818", + "FRGT": "0001687542", + "CMND": "0001892500", + "ELPW": "0002015691", + "YBGJ": "0000895464", + "CLDI": "0001855485", + "ZHDM": "0001950209", + "TIVC": "0001787740", + "NUWE": "0001506492", + "IPST": "0001788230", + "GPUSF": "0001708160", + "WCUFF": "0001902276", + "GV": "0001892274", + "TBLLF": "0001854257", + "BSPK": "0001409197", + "CASIF": "0001962738", + "DOGP": "0001360442", + "OGEN": "0001174940", + "MWAI": "0001520118", + "ADIL": "0001513525", + "SHFS": "0001854963", + "ALTX": "0000775057", + "CNET": "0001376321", + "IOBT": "0001865494", + "LUVU": "0001374567", + "BIYA": "0001944712", + "BVAXF": "0001882559", + "VPER": "0001133192", + "SMTK": "0001817760", + "DXF": "0001499494", + "MMEX": "0001440799", + "SETO": "0000794998", + "BBLG": "0001419554", + "FCHL": "0002023796", + "CYAN": "0000768408", + "ENSC": "0001716947", + "MYSZ": "0001211805", + "CISS": "0001951067", + "VTAK": "0001716621", + "VIIQ": "0001470129", + "FEED": "0001326706", + "PKTX": "0001128189", + "VGLS": "0001091326", + "ROIUF": "0001736289", + "IBG": "0001924482", + "VYST": "0001308027", + "VMAR": "0001813783", + "BJDX": "0001704287", + "DTCKF": "0001949478", + "SPRC": "0001611746", + "IMCC": "0001792030", + "AGMH": "0001705402", + "TRUG": "0001857086", + "INM": "0001728328", + "DRCT": "0001880613", + "MIGI": "0001218683", + "PTOS": "0001172069", + "CRUCF": "0001734427", + "SCNI": "0001611747", + "IMTE": "0001668438", + "WORX": "0001674227", + "PPCB": "0001517681", + "GTCH": "0001471781", + "AEHL": "0001470683", + "MGAM": "0001886362", + "FUST": "0001636051", + "OILCF": "0001922639", + "ATMH": "0001484674", + "IPW": "0001830072", + "JDZG": "0001976908", + "UPC": "0001809616", + "PRFX": "0001801834", + "ZICX": "0001465311", + "LAZRQ": "0001758057", + "VIZNF": "0001704476", + "AYRWF": "0001847462", + "PAVS": "0001751876", + "AIXI": "0001935172", + "AHRO": "0001338929", + "NBBI": "0001130781", + "PREM": "0001570937", + "EEGI": "0001043150", + "AGTX": "0001603345", + "CCTG": "0001931717", + "GEGP": "0001081188", + "LRHC": "0001879403", + "DEFG": "0001874907", + "AKAN": "0001888014", + "VPRB": "0001376231", + "BABYF": "0001807936", + "AGSS": "0001514443", + "ZVSA": "0001859007", + "SXTC": "0001723980", + "AREB": "0001648087", + "RPGL": "0001912884", + "ASFT": "0001651992", + "MITI": "0000802257", + "BNRG": "0001901215", + "KSEZ": "0001945619", + "HCWB": "0001828673", + "TRGXF": "0001861479", + "GBUX": "0001169138", + "XXII": "0001347858", + "WOK": "0001929783", + "MTEN": "0001948099", + "WHLR": "0001527541", + "GIPR": "0001651721", + "GTLL": "0000932021", + "VIVC": "0001703073", + "XYLB": "0001577351", + "FFLO": "0001543652", + "PTCO": "0001609258", + "GRNL": "0001282571", + "UCAR": "0001939780", + "ISPC": "0001558569", + "ADNH": "0001744494", + "XONI": "0002040753", + "VISM": "0001082733", + "ISCO": "0001355790", + "RAYA": "0001825875", + "CBMJ": "0001452583", + "MNTR": "0001599117", + "SBEV": "0001553788", + "LBUY": "0001643721", + "CNSP": "0001729427", + "VRAX": "0001885827", + "BRVO": "0001444839", + "LQWC": "0001060888", + "SKVI": "0001085277", + "NEXR": "0001885408", + "JZXN": "0001816172", + "AERA": "0001605331", + "NIVF": "0001981662", + "FATAQ": "0001705012", + "NRRWF": "0001680637", + "FECOF": "0000849997", + "ESMC": "0000862668", + "CBDL": "0001776073", + "OMQS": "0000278165", + "LITSF": "0001978165", + "ENRT": "0001346022", + "ATXI": "0001644963", + "CBDY": "0001586554", + "MDCE": "0001404593", + "VHAI": "0001880431", + "FGL": "0001989930", + "ONCO": "0001782107", + "GRXXF": "0001823126", + "CUEN": "0001424657", + "EVFM": "0001618835", + "EMMA": "0000822370", + "HKIT": "0001742341", + "BOXL": "0001624512", + "SOBR": "0001425627", + "PFSA": "0001859807", + "PTIX": "0001022899", + "QIND": "0001393781", + "RAKR": "0001872292", + "NULGF": "0001502758", + "GMEX": "0001928581", + "SKFG": "0001794942", + "NUMD": "0001543637", + "ARBK": "0001841675", + "DPLS": "0000866439", + "BMTM": "0001568385", + "TMGI": "0001434601", + "NIHK": "0001084475", + "CONC": "0000790273", + "LYRA": "0001327273", + "GCTK": "0001506983", + "NVVE": "0001836875", + "OWPC": "0001622244", + "HSTA": "0001813603", + "MRPT": "0001143994", + "IPTNF": "0001680513", + "OVATF": "0001751058", + "QPRC": "0000824416", + "GMER": "0001454742", + "TIRXF": "0001782941", + "AKOM": "0002103785", + "CLOW": "0001619227", + "LNKS": "0001972074", + "NAFS": "0001409253", + "VSA": "0001592560", + "GNTOF": "0001346917", + "CBDW": "0001877461", + "ARRT": "0001530425", + "EDBL": "0001809750", + "KLSVF": "0001655531", + "CERO": "0001870404", + "SPTY": "0001840102", + "CCCP": "0001696411", + "XAGE": "0001842939", + "DBMM": "0001127475", + "GTIJF": "0001879373", + "DREM": "0001518336", + "NFSN": "0001284454", + "FBCD": "0001370816", + "QSJC": "0001753391", + "MCOM": "0001788841", + "HEPA": "0001583771", + "PRTX": "0002079180", + "TAAG": "0001386044", + "FRZT": "0001485074", + "NRHI": "0001680689", + "TLSS": "0001463208", + "ILST": "0001100788", + "ETUGF": "0001877430", + "ZCAR": "0001854275", + "DTII": "0001533357", + "SPOWF": "0001227282", + "EMBYF": "0001487615", + "BPTH": "0001133818", + "IRME": "0001839133", + "FGNV": "0001687919", + "FMTOF": "0001888151", + "BBLR": "0001873722", + "OZSC": "0001679817", + "ILUS": "0001496383", + "KUST": "0001342958", + "NSTM": "0000912544", + "CLDVF": "0001971260", + "SKYI": "0001555017", + "DGTEF": "0001978151", + "HWKE": "0001750777", + "GFMH": "0000820771", + "STAI": "0001994624", + "RDGT": "0001856084", + "WNLV": "0001558740", + "MSPR": "0001802450", + "AIBT": "0001763329", + "SBIG": "0001801602", + "CRKN": "0001761696", + "CSUI": "0001680132", + "PRPH": "0000868278", + "GRVE": "0000918573", + "ADTX": "0001726711", + "LGHL": "0001806524", + "ITOX": "0001290658", + "JFIL": "0001517389", + "RMTG": "0001760026", + "LGMK": "0001566826", + "GSAC": "0000890725", + "CWPE": "0001741220", + "SATT": "0001661600", + "ABPO": "0001893219", + "SLDC": "0001427644", + "LNBY": "0001672572", + "WINT": "0000946486", + "BDCC": "0001495648", + "NNAX": "0001132509", + "CHMX": "0001657045", + "FOXO": "0001812360", + "LNTO": "0002006925", + "GPLB": "0001392449", + "SNBH": "0001358633", + "CYTOF": "0001601936", + "FYNN": "0001497230", + "ZAPPF": "0001955104", + "MTLK": "0001098462", + "ONAR": "0001682265", + "KAVL": "0001762239", + "HGAS": "0001817232", + "AOXY": "0000352991", + "OMTK": "0001404804", + "PTPI": "0001815903", + "ECPL": "0001356914", + "BHATF": "0001759136", + "LEEN": "0001230524", + "HUBC": "0001905660", + "LBGJ": "0001896425", + "GRPS": "0001990446", + "GCAN": "0001695473", + "NBND": "0001725911", + "BDPT": "0001575142", + "SVVC": "0001495584", + "RGBP": "0001589150", + "ALDA": "0001062506", + "GRLF": "0000915661", + "TOBAF": "0001823375", + "IVPR": "0001939365", + "LDTCF": "0001981462", + "CIRX": "0000813716", + "QTTOY": "0001733298", + "IMTH": "0001331612", + "FCHS": "0001416876", + "LIPO": "0001347242", + "CMLS": "0001058623", + "CNBX": "0001343009", + "UOKAF": "0001741534", + "EMRH": "0001300306", + "BOTY": "0001407704", + "OCEA": "0001869974", + "PNXP": "0001710495", + "RIVF": "0001342936", + "LILMF": "0001855756", + "ATDS": "0001068689", + "GTIC": "0001584480", + "BINI": "0001499961", + "BSFC": "0001730773", + "SIGY": "0001642159", + "BRST": "0000764897", + "NMHI": "0001947861", + "STBXF": "0001914818", + "YGMZF": "0001782037", + "BLMZF": "0001984014", + "MLRT": "0001375793", + "ASRE": "0001231339", + "STEK": "0001511820", + "CWNOF": "0001145898", + "WLGSF": "0001899658", + "NXUR": "0001722969", + "ALCE": "0001883984", + "PSUS": "0002002660", + "STRG": "0001803096", + "KMCM": "0002107523", + "CREVF": "0001960208", + "MIMDF": "0001920576", + "NWCYY": "0002073913", + "XXC": "0001875994", + "IBL": "0002075038", + "BWOW": "0002053791", + "MSBT": "0002103612", + "JTGEY": "0001472033", + "ELFTY": "0002073615", + "KNWAY": "0002109545", + "AELKY": "0002110583", + "CDTHY": "0002091663", + "SYNSY": "0002004340", + "PTAXY": "0002089174", + "TEICY": "0002089506", + "CPXXY": "0002071911", + "STJNY": "0002077242", + "NBKBY": "0002093618", + "BRRR": "0001841175", + "NGCOY": "0002092248", + "PSBTY": "0002063685", + "NHKSY": "0002087500", + "MPJS": "0002016864", + "TVCN": "0001952670", + "VCRDX": "0001812286", + "FUU": "0001703118", + "TVIV": "0002096755", + "STA": "0002049977", + "GHYP": "0002107730", + "AACO": "0002099906", + "CLRLY": "0002063231", + "HWEP": "0001980262", + "GLED": "0002091484", + "IDAC": "0002090441", + "AACP": "0002102123", + "NYB": "0002100835", + "FXB": "0001353611", + "QETH": "0001995569", + "PAAC": "0002087446", + "ETHB": "0002099103", + "BDRY": "0001610940", + "MNZLY": "0002062807", + "XRPZ": "0002059438", + "TGRGF": "0002094900", + "NATNF": "0002096533", + "PRNCF": "0002045300", + "MSTKY": "0002025217", + "FCHDF": "0002048847", + "AUGCF": "0001839290", + "MYCRY": "0002032399", + "MWC": "0002083526", + "BVENY": "0002095292", + "BAGZ": "0002115027", + "FRTT": "0002092967", + "AIMTF": "0001903464", + "LNTCY": "0002098381", + "MDKGY": "0002098332", + "ODKUY": "0002108124", + "MRUWY": "0002093667", + "NRGFF": "0002102593", + "SSHBY": "0002107375", + "ASKRY": "0002078895", + "ARCL": "0002073515", + "ENTXW": "0001638097", + "KWF": "0002068224", + "OPTH": "0002027329", + "ETCG": "0001705181", + "RGGG": "0002063022", + "BORMF": "0001994238", + "LRVIY": "0002029970", + "NSURF": "0002002326", + "PRBRY": "0001503812", + "BWGC": "0002080841", + "GLSA": "0002040733", + "ELMT": "0002101698", + "GIVE": "0002074158", + "OCTV": "0002083632", + "GSUI": "0002034012", + "MEON": "0002059702", + "GBNB": "0002106762", + "CITR": "0000894556", + "KPET": "0002095297", + "BWIV": "0002082847", + "HACQ": "0002089982", + "ALEUY": "0002046098", + "EIIA": "0001896036", + "LCDC": "0002071166", + "EUPX": "0002078871", + "UPX": "0002046370", + "TRBG": "0002088375", + "UDUD": "0002097903", + "VCCG": "0002052443", + "DBIM": "0002057757", + "GBH": "0002066522", + "KOGDF": "0002008257", + "OSOL": "0001868282", + "DDHLY": "0002034300", + "ZRCN": "0001901297", + "KCAC-UN": "0002102713", + "ETHW": "0002013744", + "TRGS": "0002098780", + "KCG": "0002067719", + "CGL": "0001934387", + "NSNFY": "0002027166", + "VROYF": "0002031760", + "SCSXY": "0002063116", + "DYBTY": "0002085208", + "CRGT": "0001958489", + "VNTXF": "0001754180", + "AWATY": "0002092258", + "FIT": "0002065232", + "FXF": "0001353615", + "MDKR": "0002078035", + "ACGC": "0002111542", + "IDXMF": "0002067171", + "SCOP": "0002108383", + "SICCY": "0002098860", + "JLZQ": "0002107062", + "ACMIF": "0002065282", + "VCX": "0001867090", + "JHPCY": "0002071868", + "UATCY": "0002084585", + "SSRLY": "0002073972", + "KYTFY": "0002042187", + "UNIU": "0002077715", + "PLAI": "0002058867", + "ONWRY": "0002059986", + "QADR": "0002083217", + "ETHV": "0001860788", + "EZET": "0002011535", + "TSOL": "0002028834", + "RSHL": "0001984192", + "UHP": "0002034767", + "AZBLY": "0002108185", + "ZSICY": "0002076398", + "GTLRY": "0002087843", + "TKCYY": "0002066601", + "MBSHY": "0002079706", + "MSSHY": "0002087844", + "SMGSY": "0002093227", + "AMVOY": "0002085236", + "AVEX": "0002096300", + "INHI": "0001997950", + "APXC": "0002093856", + "GST": "0002064551", + "DCFBS": "0001630745", + "GRVT": "0002078037", + "DAVI": "0002039072", + "LTGR": "0002104177", + "AIIR": "0002097725", + "VRXA": "0002079109", + "HAMA": "0002067016", + "WLII": "0002083946", + "GVSE": "0002017541", + "WNHK": "0001503658", + "MECPF": "0001945166", + "METRY": "0002073643", + "SWOL": "0002054459", + "RENGY": "0002092252", + "SHILY": "0002111790", + "TSLVF": "0001852753", + "ZSHLY": "0002088776", + "YKCLY": "0002107946", + "KERCY": "0002107989", + "SGIHY": "0002027330", + "SECZ": "0002094496", + "FXA": "0001353614", + "OHAC": "0002090787", + "SOLC": "0002041869", + "AMTU": "0002078570", + "ALOG": "0002083031", + "OGC": "0001487326", + "FXC": "0001353612", + "JOSS": "0002067746", + "GXRP": "0002037427", + "EVON": "0002075036", + "ARSTY": "0002044984", + "ICR-PA": "0001690012", + "NRYCF": "0002022469", + "DPDSY": "0002094201", + "PGIM": "0001923622", + "FRLCY": "0002065932", + "GOW": "0002097702", + "PNIG": "0002089778", + "EVVO": "0002080803", + "ISRLF": "0001915328", + "KOKO": "0002045907", + "AAS": "0002010218", + "TSUI": "0002061626", + "AVG": "0002019042", + "DTDT": "0002047713", + "BAVA": "0002086017", + "EZBC": "0001992870", + "BLTG": "0002045873", + "MAIR": "0002098430", + "SBMW": "0002036060", + "CXII": "0002114227", + "GYGLF": "0002023275", + "BRUN": "0002090646", + "JXAMY": "0002065485", + "SUWA": "0002051146", + "GJT": "0001357660", + "SMPHY": "0002063413", + "THCLY": "0002064381", + "BKPOY": "0002075877", + "XE": "0002088896", + "BHAV": "0002097288", + "TDOG": "0002064314", + "ELCG": "0002039096", + "MCL": "0002064863", + "FDXF": "0002082247", + "QSOL": "0002074409", + "SVIV": "0002098242", + "MZYX": "0002097376", + "FGO": "0002004385", + "INNP": "0001889791", + "KHOBF": "0002084698", + "BRBF": "0001976870", + "APEX": "0002069858", + "TOXR": "0002028835", + "IAUM": "0001759124", + "ALMR": "0002104204", + "HONA": "0002089271", + "BAO": "0002049184", + "HGT": "0002065655", + "QHUOY": "0001781193", + "APUR": "0002093524", + "PALO": "0002101562", + "CTBB": "0000068622", + "PRNSY": "0002098329", + "ODRS": "0001610718", + "POCH": "0002085836", + "ALGRF": "0001703292", + "CDN": "0002078905", + "LBZZ": "0001736734", + "GJO": "0001340909", + "TRAD": "0002085485", + "CTAA": "0002094073", + "GFTL": "0002062748", + "YIFE": "0002084038", + "SIVR": "0001450922", + "NCIQ": "0002031069", + "IACO": "0002091176", + "EDVLY": "0002020414", + "GGTKY": "0002059690", + "APMC": "0002101393", + "PAXG": "0002076561", + "ORIB": "0001854183", + "DMNT": "0001996450", + "BTFT": "0002046216", + "XRP": "0002039525", + "SKAI": "0002103029", + "CLSO": "0002085932", + "LPSL": "0002085796", + "SOEZ": "0002057388", + "RADB": "0001986694", + "GGRPY": "0002075474", + "SLBT": "0002070534", + "BTCW": "0001850391", + "LSHGY": "0002063675", + "SNEVY": "0002089488", + "WENC": "0002104260", + "HNPHY": "0002073669", + "EMS": "0002047036", + "MEDG": "0002022097", + "RACC": "0002118032", + "CAII": "0002115404", + "MMXGY": "0002109556", + "LPCHY": "0002023870", + "SMFSY": "0002048270", + "GFTTY": "0002023719", + "SMERY": "0001830056", + "RONE": "0002078721", + "LBRJ": "0001999119", + "FBTC": "0001852317", + "PRGY": "0001997698", + "LABT": "0002079272", + "AVAT": "0002092446", + "DYNTQ": "0000720875", + "OPITQ": "0001456772", + "VTEK": "0002013100", + "FFGG": "0002102972", + "BUHPY": "0001547870", + "GJR": "0001353226", + "GJP": "0001343491", + "GJS": "0001356284", + "MROSY": "0001516535", + "TMTS": "0002097364", + "MREGY": "0002063417", + "RVI": "0002085091", + "QLEP": "0002102155", + "NHPAP": "0001561032", + "SUMA": "0002105838", + "FSSL": "0002065812", + "TCLXY": "0002073804", + "GRLMF": "0002055938", + "SSTR": "0002067602", + "TKVA": "0002084032", + "CBPHF": "0001856491", + "ALEH": "0001806905", + "BLDC": "0002097508", + "SIBO": "0002043392", + "CHSCP": "0000823277", + "ILPLF": "0002012855", + "WDSP": "0001813744", + "NHFLF": "0001075822", + "AOJE": "0002048803", + "ODOT": "0001857629", + "HZRBY": "0002060217", + "BSOL": "0002045872", + "CUPPF": "0002021989", + "GDGIF": "0002027037", + "NEOA": "0002036444", + "GRCPY": "0002063671", + "AFNX": "0002087035", + "ADBT": "0002084227", + "XFLH": "0002088103", + "SCRNY": "0001544379", + "YGSHY": "0002053843", + "AFNDY": "0002101973", + "APAT": "0002087437", + "NXNT": "0001976663", + "TDST": "0002075888", + "AFA": "0002054964", + "KKSIY": "0002033019", + "GJH": "0001286405", + "SVIX": "0001793497", + "BITB": "0001763415", + "FGDL": "0001858258", + "AAAU": "0001708646", + "SCTAY": "0002032517", + "USDE": "0002080215", + "XNDU": "0002097163", + "EXYN": "0001960355", + "HIFI": "0002065707", + "IDPEY": "0002062803", + "SBCLY": "0002087852", + "GFTFF": "0002103596", + "PICS": "0001841644", + "SICOF": "0002117702", + "OBBCY": "0002088339", + "MPJPY": "0002100603", + "CLNK": "0002082889", + "IBIT": "0001980994", + "IPFX": "0002102041", + "SPED": "0002047859", + "BGHL": "0002069821", + "DEFI": "0001985840", + "ARXS": "0002093536", + "NEUT": "0002065741", + "BOT": "0002081119", + "OBNB": "0001916101", + "MANA": "0001852023", + "GBAT": "0001852040", + "PLYX": "0002075320", + "BITW": "0001723788", + "OBTC": "0001767057", + "GLDM": "0001618181", + "TDGGF": "0001972589", + "NOPFF": "0001991188", + "SGOL": "0001450923", + "ARKB": "0001869699", + "GLTR": "0001483386", + "QVCD": "0001254699", + "TPTA": "0001674356", + "JBK": "0001284143", + "USCI": "0001479247", + "KEEL": "0001812477", + "TSM": "0001046179", + "FETH": "0002000046", + "HYRD": "0002095038", + "ANJFY": "0002098397", + "AIOK": "0002095591", + "TTEI": "0002053475", + "BORAY": "0002097461", + "SAPUY": "0002072563", + "DNCLY": "0002065660", + "MTLMY": "0002091028", + "CRAUY": "0002094687", + "RSMIY": "0002086869", + "GSOL": "0001896677", + "GLNK": "0001852025", + "NHLTY": "0002060863", + "PDYTY": "0002032887", + "XSIAX": "0001124959", + "UNL": "0001405513", + "CSC": "0002068711", + "CLBZ": "0002050338", + "RIKU": "0002058976", + "ETI-P": "0001427437", + "BTCO": "0001855781", + "MGNO": "0002033615", + "QRED": "0002085177", + "OPTU": "0001702780", + "OUNZ": "0001546652", + "TETH": "0001992508", + "ILLU": "0002101135", + "AIAI": "0002096362", + "TCRG": "0001879270", + "PLTM": "0001690842", + "CTX": "0002096385", + "BPRE": "0001551047", + "LHI": "0002035313", + "ECST": "0002058007", + "MTVE": "0001646681", + "XYJG": "0002084388", + "VAII": "0002052096", + "GACW": "0001872421", + "IPB": "0001267332", + "PYT": "0001294808", + "EZPZ": "0002033807", + "KTN": "0001283337", + "BNO": "0001472494", + "PALL": "0001459862", + "UGA": "0001396878", + "OAK-PA": "0001403528", + "KTH": "0001283464", + "USL": "0001405528", + "PPLT": "0001460235", + "OXYWS": "0000797468", + "IPSAY": "0001582820", + "PASTY": "0001789135", + "CPPBY": "0001551468", + "PMHMY": "0002030632", + "DGCOF": "0001809267", + "UDN": "0001383149", + "JNGDY": "0002109559", + "BAR": "0001690437", + "HODL": "0001838028", + "GEHDF": "0001291313", + "PDSRX": "0001756404", + "DSRNY": "0001544088", + "UUP": "0001383151", + "MADL": "0001052354", + "GLEI": "0001871890", + "ETHA": "0002000638", + "AMPM": "0002049323", + "YSWY": "0001859836", + "TRAX": "0002091349", + "KLRA": "0002096997", + "GDEL": "0002020089", + "FSOL": "0002063380", + "YLY": "0002053115", + "SGPIY": "0002099326", + "SVICY": "0002074157", + "CBSTQ": "0001776738", + "MXUBY": "0002061911", + "OYES": "0002055187", + "ELC": "0001348952", + "PBRRY": "0002034467", + "SUIS": "0002060703", + "SWBKY": "0002098324", + "FNIGY": "0002073638", + "GLVPY": "0002089499", + "TPZEY": "0002073655", + "PWRL": "0002052053", + "BXRLY": "0002056450", + "ATHNY": "0002019367", + "EMI": "0001838003", + "FRFAF": "0001894942", + "ZJGIY": "0002093654", + "ATLCP": "0001464343", + "QMLS": "0002084026", + "BIREY": "0002073268", + "TREO": "0002041208", + "GSNR": "0002025000", + "GAVA": "0002035053", + "DNJF": "0002062397", + "CVCPY": "0002120046", + "GONYF": "0002081438", + "OBOCY": "0002094691", + "KPL": "0002000208", + "GDNT": "0002066926", + "CSCCY": "0002075918", + "SPGNY": "0002042556", + "PCPGY": "0002053411", + "TMKVY": "0002073901", + "LKYLY": "0002091585", + "VAVX": "0002060717", + "MLIZY": "0002080003", + "CCIL": "0002083945", + "JSTT": "0002073819", + "VBREY": "0001000377", + "MNTGY": "0002123346", + "GHRTF": "0002045434", + "TMGX": "0001991879", + "VSGRY": "0002075141", + "FRTRY": "0002098710", + "RECCY": "0002070570", + "DETX": "0001919776", + "GLIV": "0001852024", + "OBNK": "0002042444", + "STCK": "0002024996", + "GXLM": "0001761325", + "ETHE": "0001725210", + "ACAA": "0002096900", + "NPIXY": "0002072389", + "ZGJLY": "0002087840", + "SBAQ": "0002073545", + "AESP": "0002082526", + "MOGMF": "0002011589", + "MDDTY": "0002038958", + "AKCLY": "0002087856", + "VIRMF": "0002074745", + "CMPLY": "0002117197", + "MRCA": "0002083119", + "SCBXY": "0002066600", + "FHFFY": "0002082876", + "LILW": "0002065821", + "PRSKY": "0002071912", + "OTAI": "0002094076", + "RMIX": "0002094433", + "BMOK": "0002071607", + "CTWO": "0001958928", + "ETH": "0002020455", + "USDW": "0001977837", + "ZCSH": "0001720265", + "HZEN": "0001748945", + "MYX": "0002080087", + "CADV": "0002066899", + "IVHI": "0001009919", + "ITXP": "0002025878", + "MKTR": "0002070261", + "EUEV": "0002048740", + "KMYGY": "0002003770", + "GBNXY": "0002071913", + "HRBAY": "0002088827", + "SNHIY": "0002098326", + "PFSTY": "0002120422", + "UNID": "0002077697", + "MTMTY": "0002090231", + "OBULF": "0001927026", + "CCEYF": "0001992604", + "LSBA": "0002075589", + "PWRU": "0002087162", + "BTC": "0002015034", + "GTAO": "0002029297", + "GDOG": "0002055510", + "TMCR": "0002087398", + "NRUC": "0000070502", + "LATA": "0002076427", + "MARH": "0002087064", + "GOOG": "0001652044", + "USB-PA": "0000036104", + "BRK-A": "0001067983", + "ASMLF": "0000937966", + "TSMWF": "0001046179", + "BABAF": "0001577552", + "JPM-PC": "0000019617", + "PCCYF": "0001108329", + "JPM-PD": "0000019617", + "BML-PG": "0000070858", + "NVSEF": "0001114448", + "RYDAF": "0001306965", + "BML-PH": "0000070858", + "BML-PL": "0000070858", + "BAC-PB": "0000070858", + "TOYOF": "0001094517", + "CILJF": "0001268896", + "BAC-PK": "0000070858", + "BML-PJ": "0000070858", + "BAC-PE": "0000070858", + "MBFJF": "0000067088", + "SAPGF": "0001000184", + "HBCYF": "0001089113", + "WFC-PY": "0000072971", + "BHPLF": "0000811809", + "WFC-PL": "0000072971", + "SNEJF": "0000313838", + "BCDRF": "0000891478", + "NONOF": "0000353278", + "ABLZF": "0001091587", + "ABBNY": "0001091587", + "EADSF": "0001378580", + "TBB": "0000732717", + "SNYNF": "0001121404", + "UNLYF": "0000217410", + "BUDFF": "0001668717", + "BTAFF": "0001303523", + "WFC-PC": "0000072971", + "DTEGF": "0000946770", + "GLAXF": "0001131399", + "BPAQF": "0000313807", + "RTPPF": "0000863064", + "SMFNF": "0001022837", + "IDEXF": "0001438656", + "BYDDF": "0001445162", + "NCRRP": "0000070866", + "CMXHF": "0001274152", + "AIQUF": "0001161167", + "BAESF": "0000895564", + "SNPMF": "0001123658", + "MBGAF": "0001067318", + "NETTF": "0001110646", + "NTTYY": "0000769594", + "USB-PH": "0000036104", + "EBBNF": "0000895728", + "CTA-PB": "0000030554", + "USB-PP": "0000036104", + "PPRUF": "0001445465", + "AMXOF": "0001129137", + "GS-PA": "0000886982", + "GS-PD": "0000886982", + "MS-PK": "0000895421", + "MS-PA": "0000895421", + "PBR-A": "0001119639", + "KDDIF": "0001106215", + "MS-PI": "0000895421", + "STOHF": "0001140625", + "MS-PF": "0000895421", + "MS-PE": "0000895421", + "OXY": "0000797468", + "RLXXF": "0000929869", + "DUK-PA": "0001326160", + "FMCCT": "0001026214", + "BAMXF": "0001446250", + "BAIDF": "0001329099", + "DGEAF": "0000835403", + "EIPAF": "0001002242", + "CCZ": "0001166691", + "BYMOF": "0001446250", + "WEBNF": "0000719245", + "IFNNF": "0001107457", + "MZHOF": "0001335730", + "HTHIF": "0000047710", + "NGGTF": "0001004315", + "SCHW-PD": "0000316709", + "TKPHF": "0001395064", + "DKILF": "0001446519", + "BECEF": "0000718940", + "SPG-PJ": "0001063761", + "BSQKZ": "0001512673", + "NOKBF": "0000924613", + "CTA-PA": "0000030554", + "TNCAF": "0001232384", + "INGVF": "0001039765", + "MET-PA": "0001099219", + "TRPCF": "0001269238", + "ITOCF": "0000355363", + "MET-PE": "0001099219", + "LLDTF": "0001160106", + "BBVXF": "0000842180", + "HLNCF": "0001900304", + "TCANF": "0001232384", + "PSA-PH": "0001393311", + "JDCMF": "0001549802", + "HNDAF": "0000715153", + "PLDGP": "0001045609", + "SVNDF": "0001359519", + "BAMGF": "0001001085", + "PINXF": "0001569964", + "TCKRF": "0000886986", + "CRARF": "0001279967", + "HEI-A": "0000046619", + "ENAKF": "0001136808", + "RBSPF": "0000844150", + "ERIXF": "0000717826", + "PUKPF": "0001116578", + "ALL-PB": "0000899051", + "WOPEF": "0000844551", + "FNCTF": "0001038143", + "PSA-PK": "0001393311", + "ALL-PH": "0000899051", + "LEN-B": "0000920760", + "CIXPF": "0001535628", + "BCLYF": "0000312069", + "RSMDF": "0000943819", + "CODGF": "0001012037", + "LAAOF": "0001791706", + "ORXCF": "0001070304", + "TEFOF": "0000814052", + "VODPF": "0000839923", + "BBDO": "0001160330", + "GNMSF": "0001434265", + "HRNNF": "0001712356", + "ANNSF": "0001700171", + "DLR-PK": "0001297996", + "FOX": "0001754301", + "CAJPY": "0000016988", + "STMEF": "0000932787", + "HKHHF": "0001142231", + "AMSYF": "0001243429", + "SAXPF": "0001436778", + "FCNCB": "0000798941", + "RYAOF": "0001038683", + "MKC-V": "0000063754", + "TNRSF": "0001190723", + "RSTRF": "0001618755", + "SOJC": "0000092122", + "CAJFF": "0000016988", + "HMRZF": "0001396282", + "FWONK": "0001560385", + "DLR-PJ": "0001297996", + "COCSF": "0000910631", + "ICHGF": "0000858446", + "TELNF": "0001126113", + "RCIAF": "0000733099", + "XPNGF": "0001810997", + "Z": "0001617640", + "STT-PG": "0000093751", + "KYOCF": "0000057083", + "KYOCY": "0000057083", + "EJPRF": "0001093028", + "FWONB": "0001560385", + "HIG-PG": "0000874766", + "FITBI": "0000035527", + "POAHF": "0001450346", + "NRSCF": "0001163653", + "JHIUF": "0001159152", + "SPXSF": "0001518542", + "RYLPF": "0000313216", + "AMCCF": "0001748790", + "SURDF": "0001450159", + "BIO-B": "0000012208", + "NWS": "0001564708", + "CHKIF": "0001041668", + "ADTTF": "0001158838", + "FNMAS": "0000310522", + "KEY-PK": "0000091576", + "FSNUF": "0000904868", + "TEVJF": "0000818686", + "SSMXF": "0001517231", + "CRERF": "0001078642", + "KEY-PJ": "0000091576", + "FNMAJ": "0000310522", + "SGIOF": "0001281721", + "FRFFF": "0000915191", + "PTPIF": "0001547873", + "NLY-PG": "0001043219", + "APO-PA": "0001858681", + "NLY-PF": "0001043219", + "KEY-PI": "0000091576", + "NIOIF": "0001736541", + "FNGD": "0000927971", + "GFIOF": "0001172724", + "FNMAH": "0000310522", + "NCSYF": "0001003935", + "RKLIF": "0000930157", + "SVYSF": "0000930826", + "GELYF": "0001474968", + "NMPGY": "0001333172", + "WSO-B": "0000105016", + "FMCQF": "0001333141", + "MAA-PI": "0000912595", + "LBRDB": "0001611983", + "RF-PC": "0001281761", + "BF-B": "0000014693", + "SNNUF": "0000845982", + "LBRDK": "0001611983", + "BZLFF": "0001072397", + "ALMMF": "0001161611", + "ERRAF": "0001127248", + "ACGLO": "0000947484", + "PIRBF": "0001437441", + "UHAL-B": "0000004457", + "SBYSF": "0001786909", + "TAP-A": "0000024545", + "DQJCF": "0001446597", + "PBNNF": "0001504122", + "WPPGF": "0000806968", + "PRYMF": "0001437672", + "GPAEF": "0001347557", + "MNBEF": "0001034983", + "KIKOF": "0001446656", + "AEGOF": "0000769218", + "CUKPF": "0001125259", + "FREJO": "0001026214", + "YAMHF": "0001447100", + "GLIBB": "0002057463", + "NDEKF": "0000353991", + "ASRMF": "0001123452", + "CIG-C": "0001157557", + "JGSHF": "0001567172", + "LBTYB": "0001570585", + "UEPCN": "0000100826", + "CXMSF": "0001076378", + "SAPIF": "0002072563", + "DINRF": "0001544379", + "PSORF": "0000938323", + "RZB": "0000898174", + "AGNCN": "0001423689", + "AGNCM": "0001423689", + "UEPEP": "0000100826", + "UEPEO": "0000100826", + "PSNYW": "0001884082", + "SASOF": "0000314590", + "VNORP": "0000899689", + "CWEN-A": "0001567683", + "AMH-PH": "0001562401", + "OSCUF": "0001600520", + "NWOEF": "0001372920", + "CLUS": "0001346287", + "VNO-PL": "0000899689", + "UEPCP": "0000100826", + "AMH-PG": "0001562401", + "FRT-PC": "0000034903", + "VNO-PM": "0000899689", + "GS-PC": "0000886982", + "ATH-PA": "0001527469", + "UEPEN": "0000100826", + "OCANF": "0001487326", + "BLBLF": "0001723690", + "VOYA-PB": "0001535929", + "XZJCF": "0001562805", + "GIFLF": "0001438569", + "KOSCF": "0001668501", + "PADEF": "0001489079", + "GIFOF": "0001438569", + "MSUXF": "0001710864", + "ATDRF": "0001647435", + "FMCKI": "0001026214", + "YMHAY": "0001447100", + "DSECF": "0001481045", + "CMSA": "0000811156", + "UEPEM": "0000100826", + "SLG-PI": "0001040971", + "RNR-PF": "0000913144", + "KIM-PM": "0000879101", + "FMCCI": "0001026214", + "BCUCF": "0001581285", + "KIM-PL": "0000879101", + "KAKKF": "0001447126", + "BMRPF": "0001671235", + "LIFX": "0001581760", + "GIKLY": "0001438569", + "PCG-PA": "0001004980", + "OS": "0001889956", + "SFGRF": "0002084022", + "HACBY": "0000793742", + "ALTB": "0001642365", + "RUSHB": "0001012019", + "PCG-PB": "0001004980", + "UNMA": "0000005513", + "OAK-PB": "0001403528", + "SLFPF": "0001370418", + "RTMVF": "0001516536", + "MITUF": "0001446420", + "BLFBY": "0001506721", + "BPOPO": "0000763901", + "HGMCF": "0001023514", + "SSRGF": "0000921638", + "ZLDPF": "0002068427", + "JSM": "0001593538", + "PHTCF": "0000078150", + "PCG-PE": "0001004980", + "EPR-PG": "0001045450", + "PPENF": "0001469395", + "PCG-PD": "0001004980", + "PCG-PC": "0001004980", + "FNMFN": "0000310522", + "PCG-PH": "0001004980", + "GAB-PG": "0000794685", + "PCG-PG": "0001004980", + "GAERF": "0001378239", + "AXS-PE": "0001214816", + "DTW": "0000936340", + "SPTJF": "0000908732", + "AKO-B": "0000925261", + "PCG-PI": "0001004980", + "LBTYK": "0001570585", + "DISPF": "0001671750", + "TCMFF": "0000932470", + "SLMBP": "0001032033", + "GEF-B": "0000043920", + "DLAKF": "0001049724", + "SF-PB": "0000720672", + "REXR-PB": "0001571283", + "TWO-PC": "0001465740", + "PBI-PB": "0000078814", + "BHFAL": "0001685040", + "TYTMF": "0001447101", + "MOG-B": "0000067887", + "VLYPP": "0000714310", + "CIM-PD": "0001409493", + "CIM-PB": "0001409493", + "RYKKF": "0001592049", + "TWO-PB": "0001465740", + "TWO-PA": "0001465740", + "WRB-PE": "0000011544", + "CIM-PC": "0001409493", + "SOHGY": "0001536787", + "HOVNP": "0000357294", + "WBS-PF": "0000801337", + "VLYPO": "0000714310", + "BATRK": "0001958140", + "RLJ-PA": "0001511337", + "PEB-PF": "0001474098", + "PEB-PE": "0001474098", + "BBU": "0001654795", + "CIM-PA": "0001409493", + "PEGRF": "0001455633", + "TY-P": "0000099614", + "ASB-PE": "0000007789", + "BELFB": "0000729580", + "BHFAP": "0001685040", + "PTXAF": "0001545057", + "HMDCF": "0001648257", + "FMCCG": "0001026214", + "MFA-PB": "0001055160", + "FNMAM": "0000310522", + "AILLI": "0000018654", + "UA": "0001336917", + "TRTN-PA": "0001660734", + "NSA-PA": "0001618563", + "BATRB": "0001958140", + "WELPP": "0000107815", + "AILLM": "0000018654", + "AILLN": "0000018654", + "CDGLF": "0001448611", + "FNMAN": "0000310522", + "ATROB": "0000008063", + "SOCGP": "0000092108", + "SRG-PA": "0001628063", + "TROLB": "0000098677", + "AILIM": "0000018654", + "FMCCJ": "0001026214", + "FNMAI": "0000310522", + "NHNKF": "0001543726", + "CODQL": "0001770561", + "WBHC": "0000885275", + "GLPGF": "0001421876", + "TBNGY": "0001489088", + "AILLO": "0000018654", + "LXP-PC": "0000910108", + "FNMAT": "0000310522", + "AILIN": "0000018654", + "FNMAK": "0000310522", + "CENTA": "0000887733", + "IFCNF": "0002035057", + "FNMAL": "0000310522", + "FNMFM": "0000310522", + "IVR-PC": "0001437071", + "AILLP": "0000018654", + "WLYB": "0000107140", + "FNMAO": "0000310522", + "AHL-PE": "0001267395", + "FNMAG": "0000310522", + "FNMFO": "0000310522", + "NGL-PB": "0001504461", + "ARZTF": "0001423210", + "AGM-A": "0000845877", + "LILAK": "0001712184", + "GDV-PH": "0001260729", + "FISK": "0001553079", + "GRPFF": "0000912892", + "EVOTF": "0001412558", + "NGL-PC": "0001504461", + "BFS-PD": "0000907254", + "FMCCL": "0001026214", + "OGCP": "0001553079", + "FMCKL": "0001026214", + "LTGHF": "0001569963", + "PMT-PA": "0001464423", + "PMT-PB": "0001464423", + "GNL-PA": "0001526113", + "BXMX": "0001298699", + "SBOEF": "0001578955", + "LILAB": "0001712184", + "HCXY": "0001280784", + "GAB-PH": "0000794685", + "FMCCS": "0001026214", + "MHLA": "0001412100", + "FMCCO": "0001026214", + "AHL-PD": "0001267395", + "BITF": "0001812477", + "CODI-PB": "0001345126", + "GLDD": "0001372020", + "FMCKN": "0001026214", + "FREJN": "0001026214", + "CMGMF": "0001503154", + "FMCCN": "0001026214", + "FMCKO": "0001026214", + "SENEA": "0000088948", + "GLOP-PB": "0001598655", + "FMCKJ": "0001026214", + "FMCKM": "0001026214", + "GLOP-PC": "0001598655", + "FREGP": "0001026214", + "GLOP-PA": "0001598655", + "FMCCH": "0001026214", + "FMCCK": "0001026214", + "BH": "0001726173", + "HL-PB": "0000719413", + "FMCCP": "0001026214", + "FMCCM": "0001026214", + "FMCKP": "0001026214", + "GRAF-UN": "0001897463", + "FXCNF": "0001164009", + "CODI-PA": "0001345126", + "HCACU": "0002079013", + "GAM-PB": "0000040417", + "INN-PE": "0001497645", + "ATLC": "0001464343", + "IIPR-PA": "0001677576", + "GTN-A": "0000043196", + "MEOBF": "0001345099", + "DRDGF": "0001023512", + "DGICB": "0000800457", + "CMRE-PB": "0001503584", + "CMRE-PD": "0001503584", + "HOVVB": "0000357294", + "CMRE-PC": "0001503584", + "GDRZF": "0001072725", + "AGM-PD": "0000845877", + "HLTC": "0001561032", + "HVT-A": "0000216085", + "GGT-PE": "0000921671", + "MAKOF": "0001784930", + "KELYB": "0000055135", + "DIAX": "0001608742", + "GGN-PB": "0001313510", + "FFWM": "0001413837", + "BRSYF": "0001505065", + "UMH-PD": "0000752642", + "AIRTP": "0000353184", + "OXLCM": "0001495222", + "MTGRF": "0001537543", + "ECCX": "0001604174", + "MITT-PA": "0001514281", + "NEWTI": "0001587987", + "PTCHF": "0001782999", + "OXLCO": "0001495222", + "CRD-B": "0000025475", + "NCV-PA": "0001214935", + "MITT-PB": "0001514281", + "AVHHL": "0001762303", + "VSOGF": "0001762506", + "ERLFF": "0001271554", + "ONTF": "0001110611", + "ARTNB": "0000863110", + "CKDXF": "0001815620", + "CNTHP": "0000023426", + "IHRTB": "0001400891", + "CNLPL": "0000023426", + "GUT-PC": "0001080720", + "VCIC": "0002025396", + "NCZ-PA": "0001227857", + "DFPH": "0001799191", + "DSX-PB": "0001318885", + "CNTHO": "0000023426", + "RVRF": "0001641601", + "MTMV": "0001393044", + "RLFTY": "0001854078", + "CHMI-PB": "0001571776", + "GSCCF": "0001896084", + "BHR-PB": "0001574085", + "PRRUF": "0001506184", + "BLFY": "0001846017", + "CNTHN": "0000023426", + "SLNCF": "0001479615", + "APLMW": "0001944885", + "CNLHP": "0000023426", + "DVS": "0001542028", + "ARCXF": "0001243429", + "CNLTP": "0000023426", + "CNLTL": "0000023426", + "IPHYF": "0001598599", + "BHR-PD": "0001574085", + "CNPWM": "0000023426", + "PRTHU": "0001653558", + "CHMI-PA": "0001571776", + "CNLHO": "0000023426", + "CNPWP": "0000023426", + "LANDP": "0001495240", + "CNLPM": "0000023426", + "CNLTN": "0000023426", + "ENO": "0000071508", + "CDR-PC": "0000761648", + "CNLHN": "0000023426", + "BNIGF": "0001851651", + "IVEVF": "0001756594", + "SB-PD": "0001434754", + "ECXJ": "0001823635", + "CDR-PB": "0000761648", + "UBFO": "0001137547", + "SB-PC": "0001434754", + "EBRCZ": "0001347123", + "DLNG-PA": "0001578453", + "WONDF": "0001882839", + "NVNXF": "0001859795", + "CHPGF": "0001394189", + "LUCN": "0001726079", + "TTSH": "0001552800", + "SINC": "0001532595", + "BBXIB": "0001814974", + "CRTD": "0001357671", + "AOAO": "0002042320", + "RAASY": "0001804583", + "OCGSF": "0000942149", + "RDIB": "0000716634", + "ECF-PA": "0000793040", + "AHT-PD": "0001232582", + "AHT-PF": "0001232582", + "AHT-PG": "0001232582", + "SOHOO": "0001301236", + "AHT-PH": "0001232582", + "SFDL": "0000818677", + "AHT-PI": "0001232582", + "BCV-PA": "0000009521", + "BCTF": "0001668340", + "OFED": "0001501078", + "ENDI": "0001908984", + "RGBPP": "0001589150", + "GLU-PB": "0001282957", + "PELI": "0002037431", + "ATEK": "0001882198", + "RLFTF": "0001854078", + "CPTP": "0000202947", + "IXAQF": "0001852019", + "BKSC": "0001007273", + "GSL-PB": "0001430725", + "KBSR": "0001482430", + "CULL": "0001845799", + "TKLS": "0001429393", + "FUUFF": "0001703118", + "CMCAF": "0001865248", + "JOCM": "0001907425", + "GGROU": "0001489874", + "CBRRF": "0001845149", + "FBIOP": "0001429260", + "SOHON": "0001301236", + "HSTC": "0000797564", + "GTMAY": "0001163560", + "HCIL": "0001086303", + "ASCBF": "0001876716", + "FSHPU": "0001850059", + "STRC": "0001050446", + "ENTX": "0001638097", + "PROCF": "0001863362", + "BCOW": "0001847360", + "ILLR": "0001769624", + "TRLC": "0001550453", + "GRFXF": "0001816723", + "NBY": "0001389545", + "MDNAF": "0001807983", + "CIZN": "0001075706", + "ARRKF": "0001855743", + "VICP": "0001468639", + "NZEOF": "0001445654", + "SGTM": "0001895251", + "NSRCF": "0001302084", + "JETBF": "0001846084", + "BBXIA": "0001814974", + "UONEK": "0001041657", + "VTYB": "0001509302", + "RMHI": "0001452804", + "AVLNF": "0001362898", + "WINV": "0001854463", + "MLMC": "0001099234", + "CCTSF": "0001865861", + "WSKEF": "0001738699", + "GFASY": "0001389207", + "EAXR": "0000832370", + "GBNY": "0001823365", + "BIOE": "0001723059", + "ANPCF": "0001620678", + "CTGL": "0001498067", + "PTN": "0000911216", + "AATC": "0000943034", + "ANEB": "0001815974", + "OMCC": "0001000045", + "ILLMF": "0001861233", + "LTSV": "0001619312", + "CLCS": "0001569340", + "HSTI": "0001365388", + "SCYYF": "0001408146", + "GWLL": "0001800373", + "OSBK": "0001076691", + "XTXXF": "0001891512", + "GRFXY": "0001816723", + "WVVIP": "0000838875", + "LTCH": "0001826000", + "HLLK": "0001331421", + "VWFB": "0001913838", + "TBHC": "0001056285", + "MRZLF": "0001301854", + "ZIVO": "0001101026", + "BZRD": "0001765826", + "AFGC": "0001042046", + "UOKA": "0001741534", + "TBMC": "0001934945", + "BRCNF": "0001158399", + "WHLM": "0001013706", + "FALC": "0000922521", + "SFES": "0000086115", + "BGAVD": "0001500620", + "BQST": "0001568628", + "FNCH": "0001733257", + "CBSTF": "0001776738", + "HOOK": "0001760542", + "WHLRD": "0001527541", + "GLBZ": "0000890066", + "KNDYF": "0001703292", + "HMMR": "0001539680", + "SALM": "0001050606", + "PRNAF": "0001131343", + "MNTCF": "0002123346", + "TVE": "0001376986", + "MCLE": "0001827855", + "ULY": "0001603652", + "BNSOF": "0000846546", + "TVC": "0001376986", + "CMBM": "0001738177", + "AGLY": "0001673504", + "SITS": "0001468978", + "PNPL": "0001654672", + "EVTK": "0001816554", + "SWISF": "0001771755", + "PMDI": "0000806517", + "PMEDF": "0001868079", + "APHD": "0001490054", + "ASPU": "0001487198", + "TAIT": "0000942126", + "OBULD": "0001927026", + "CJAX": "0001763925", + "FEOVF": "0000936801", + "CYCA": "0001383088", + "MGTI": "0001001601", + "SILEF": "0001545224", + "CARV": "0001016178", + "SPEV": "0000764630", + "NEXCF": "0001737270", + "WNFT": "0001528188", + "FLYYQ": "0001498710", + "FULO": "0001092570", + "SCGY": "0001276531", + "NGHI": "0001574676", + "VQSSF": "0001777765", + "GLUC": "0001420108", + "GBCS": "0000727346", + "EXDW": "0001634293", + "EESH": "0001138867", + "BRRN": "0001397795", + "MVCO": "0000924095", + "SFUNY": "0001294404", + "YQAI": "0001976923", + "ILXP": "0001115864", + "BBBXF": "0001548958", + "LCHD": "0001715433", + "FGCO": "0001377167", + "EGLXF": "0001854233", + "SUIC": "0001394108", + "NXMH": "0001811530", + "RSCF": "0001103090", + "EGTYF": "0001629632", + "VISL": "0001565228", + "ACRL": "0001584618", + "UCLE": "0001543623", + "TGCB": "0001815632", + "NMGX": "0000891417", + "MTTCF": "0001828098", + "GRST": "0000792935", + "NUVI": "0001410708", + "WDLF": "0001281984", + "FZMD": "0000319016", + "BWMG": "0001166708", + "DTGI": "0001014052", + "CANN": "0001477009", + "VCNX": "0001205922", + "RDAR": "0001384365", + "QH": "0001781193", + "ECIA": "0000930775", + "UCASU": "0001723517", + "CETXP": "0001435064", + "GPLL": "0001883083", + "KNOS": "0001108248", + "HHHEF": "0000825171", + "VMNT": "0001605057", + "JFBR": "0001885408", + "IWAL": "0001498372", + "AXIM": "0001514946", + "TPHS": "0000724742", + "JRSS": "0001597892", + "EBZT": "0001730869", + "MYCB": "0001556801", + "MAJI": "0001492448", + "SSHT": "0001975222", + "BYOC": "0001386049", + "SNNC": "0001313938", + "ITRM": "0001659323", + "GOGR": "0001378866", + "CLSDQ": "0001539029", + "VYRE": "0001127007", + "RNGC": "0001434740", + "SYIN": "0001292490", + "TNBI": "0001452011", + "INKW": "0001585380", + "SRMX": "0000841533", + "AGNPF": "0001642178", + "CARM": "0001485003", + "WHLRP": "0001527541", + "BKTH": "0001144392", + "XTKG": "0001754323", + "SFWJ": "0001919847", + "SPQS": "0000803097", + "BRLL": "0001631463", + "MGHL": "0001162283", + "SSKN": "0001051514", + "CPWR": "0000827099", + "MOBBW": "0001898643", + "PHBI": "0001435181", + "PCYN": "0000812306", + "PLSH": "0001552189", + "FVTI": "0001626745", + "KITL": "0001608092", + "GMZP": "0001973160", + "HBUV": "0001639068", + "GSPI": "0001461708", + "CDSG": "0000946112", + "NTRR": "0001512886", + "VERO": "0001409269", + "ESSI": "0001490873", + "BSLK": "0001841125", + "NINEQ": "0001532286", + "BLPG": "0001416697", + "MDEX": "0001318268", + "ADMG": "0001171008", + "BEGI": "0001483646", + "INNI": "0001098482", + "KACLF": "0001865468", + "KOAN": "0000897078", + "ZPTA": "0001843714", + "EHVVF": "0001653606", + "ASII": "0001464865", + "CRDV": "0001084551", + "APSI": "0001553264", + "TPICQ": "0001455684", + "RTON": "0001580262", + "MMMW": "0001117228", + "MASN": "0001486452", + "SHGI": "0001874138", + "GZIC": "0001286648", + "GXXM": "0001681556", + "EDGM": "0001652958", + "OXBRW": "0001584831", + "BACK": "0001729944", + "USDP": "0001610682", + "GMBL": "0001451448", + "FRQN": "0001624517", + "GWSO": "0001430300", + "EMED": "0001715819", + "DPUI": "0001791929", + "ENDV": "0001528172", + "GIPL": "0001837774", + "AITXD": "0001498148", + "SONX": "0001407973", + "SCPX": "0001476963", + "DWAY": "0001394638", + "ACBM": "0001622996", + "SNPW": "0001343465", + "DSGT": "0001413909", + "DLTI": "0001420368", + "SONG": "0001671132", + "COSG": "0001706509", + "CICC": "0001534254", + "AHII": "0001545236", + "ELOX": "0001035354", + "IMCI": "0000884650", + "BAC-PL": "0000070858", + "BAC-PM": "0000070858", + "MER-PK": "0000070858", + "BAC-PN": "0000070858", + "BAC-PO": "0000070858", + "BAC-PP": "0000070858", + "BAC-PQ": "0000070858", + "BAC-PS": "0000070858", + "BACRP": "0000070858", + "INBKZ": "0001562463", + "APACU": "0002043630", + "APACR": "0002043630", + "DAICW": "0002033770", + "VFSWW": "0001913510", + "BODYW": "0001826889", + "UVIX": "0001793497", + "WSUPW": "0001819516", + "ATHS": "0001527469", + "ATH-PB": "0001527469", + "ATH-PD": "0001527469", + "ATH-PE": "0001527469", + "HPAIW": "0002001699", + "AERTW": "0001853044", + "LEGO-WT": "0002087450", + "LEGO-UN": "0002087450", + "BBAI-WT": "0001836981", + "DMIIR": "0002040475", + "DMIIU": "0002040475", + "NPACW": "0002048948", + "NPACU": "0002048948", + "ITHAU": "0002080985", + "ITHAW": "0002080985", + "YSHLF": "0002053843", + "KOKSF": "0002033019", + "GTERR": "0002043766", + "GTERW": "0002043766", + "GTERU": "0002043766", + "LPBBW": "0002023676", + "LPBBU": "0002023676", + "RANGR": "0002035644", + "RANGU": "0002035644", + "ALISU": "0002026767", + "ALISR": "0002026767", + "QLUNF": "0001951378", + "NEOVW": "0001748137", + "AUROW": "0001828108", + "ASPCU": "0001890361", + "ASPCR": "0001890361", + "WPAC-RI": "0002081536", + "WPAC-UN": "0002081536", + "OPP-PC": "0001678130", + "OPP-PA": "0001678130", + "OPP-PB": "0001678130", + "FTW-WT": "0002083125", + "NPEHF": "0001985406", + "MOBXW": "0001855467", + "SBEVW": "0001553788", + "NHS-RI": "0001487610", + "MLCIL": "0002051820", + "SSSSL": "0001509470", + "XFLH-UN": "0002088103", + "XFLH-RI": "0002088103", + "HAVAU": "0002042460", + "HAVAR": "0002042460", + "BYNOU": "0001801417", + "BYNOW": "0001801417", + "TAVIU": "0002020385", + "KRAQW": "0002082119", + "KRAQU": "0002082119", + "RDACR": "0002018145", + "RDACU": "0002018145", + "TAVIR": "0002020385", + "THQQF": "0001969796", + "STKTF": "0002032517", + "MCGAW": "0002064658", + "MCGAU": "0002064658", + "GROVW": "0001841761", + "FLDDW": "0001889123", + "SHFSW": "0001854963", + "NIVFW": "0001981662", + "TSLTF": "0001144800", + "TACPF": "0001144800", + "TRNTF": "0001144800", + "ADSEW": "0001879248", + "SVACU": "0002074850", + "SVACW": "0002074850", + "RZLVW": "0001920294", + "BEPH": "0001533232", + "BEPI": "0001533232", + "BEP-PA": "0001533232", + "BEPJ": "0001533232", + "XSLLU": "0002088807", + "XSLLW": "0002088807", + "SSACR": "0002081300", + "SSACW": "0002081300", + "SSACU": "0002081300", + "IPFXU": "0002102041", + "CMIIU": "0002088805", + "CMIIW": "0002088805", + "AFJKU": "0001979005", + "AFJKR": "0001979005", + "SCIIR": "0002076739", + "SCIIU": "0002076739", + "ANKM": "0001781629", + "MTPLF": "0002100603", + "SBKLF": "0002087852", + "OBIBF": "0002088339", + "IDPUF": "0002062803", + "MINR": "0001854816", + "TMCWW": "0001798562", + "URSB": "0002084261", + "ZENVF": "0001836934", + "FCELB": "0000886128", + "KIDZW": "0002022308", + "TCPA": "0000099070", + "CTSWF": "0001865861", + "CTSUF": "0001865861", + "MESHU": "0002081468", + "MESHW": "0002081468", + "RDPTF": "0001949257", + "BLUWU": "0002050501", + "BLUWW": "0002050501", + "HCACR": "0002079013", + "YHNAR": "0002020987", + "YHNAU": "0002020987", + "ARCIW": "0002083910", + "ARCIU": "0002083910", + "XCBEU": "0002083493", + "XCBEW": "0002083493", + "GROY-WT": "0001834026", + "SNNRF": "0002021938", + "STWI": "0001999261", + "CMSC": "0000811156", + "CMSD": "0000811156", + "CMS-PC": "0000811156", + "CELG-RI": "0000014272", + "SF-PC": "0000720672", + "SFB": "0000720672", + "ELVGD": "0001741489", + "SF-PD": "0000720672", + "CDROW": "0001866782", + "MLACU": "0002029492", + "MLACR": "0002029492", + "MTEKW": "0001872964", + "ENGNW": "0001980845", + "VIASP": "0001606268", + "NGCGD": "0001061040", + "PPLC": "0000922224", + "BPPFF": "0000313807", + "COEPW": "0001759186", + "BSLKW": "0001841125", + "MAPSW": "0001779474", + "SAIHW": "0001847075", + "GREEL": "0001844971", + "ABXL": "0001814287", + "TDS-PU": "0001051512", + "TDS-PV": "0001051512", + "RDCT": "0001376804", + "NBRWF": "0001163739", + "AMPX-WT": "0001899287", + "VRMWW": "0001580864", + "BBBY-WT": "0001130713", + "CDZIP": "0000727273", + "HNNAZ": "0001145255", + "AIZN": "0001267238", + "EQH-PA": "0001333986", + "EQH-PC": "0001333986", + "BANC-PF": "0001169770", + "BTGRF": "0001546538", + "BTLWF": "0001546538", + "SFDMF": "0001493507", + "DGP": "0001159508", + "DGZ": "0001159508", + "DZZ": "0001159508", + "ADZCF": "0001159508", + "DEENF": "0001159508", + "OLOXF": "0001159508", + "RCKTW": "0001281895", + "GNT-PA": "0001438893", + "ZNKUF": "0001705455", + "KPLTW": "0001785424", + "LDTDF": "0001981462", + "HLLY-WT": "0001822928", + "LNXSF": "0001311307", + "VACHU": "0002006815", + "VACHW": "0002006815", + "LCCCU": "0002049248", + "LCCCR": "0002049248", + "SBIGW": "0001801602", + "AIMDW": "0001014763", + "RF-PE": "0001281761", + "RF-PF": "0001281761", + "TVAIR": "0001872228", + "TVAIU": "0001872228", + "PCAPW": "0002056634", + "PCAPU": "0002056634", + "GPATU": "0001834526", + "GPATW": "0001834526", + "MHNC": "0001412100", + "NOWGD": "0001761911", + "BAKR": "0001904616", + "TE-WT": "0001992243", + "HYNLY": "0001712356", + "BMPA": "0001130781", + "HUMAW": "0001818382", + "SAABF": "0001770114", + "DNABW": "0001830214", + "SDAWW": "0001936804", + "DAZSF": "0001896511", + "OSRHW": "0001840425", + "SPWRW": "0001838987", + "WINVR": "0001854463", + "WINVU": "0001854463", + "WINVW": "0001854463", + "BBLGW": "0001419554", + "TMUSZ": "0001283699", + "TMUSI": "0001283699", + "TMUSL": "0001283699", + "GLDW": "0001618181", + "IHICF": "0001567526", + "ASCIX": "0001716885", + "OWLTW": "0001816708", + "GDSTR": "0001858007", + "GDSTU": "0001858007", + "GDSTW": "0001858007", + "REVBW": "0001810560", + "ASBPW": "0001847345", + "NIXXW": "0001462223", + "GMBLP": "0001451448", + "GMBLZ": "0001451448", + "DX-PC": "0000826675", + "LTAFX": "0001496254", + "LTCFX": "0001496254", + "ABAKF": "0000790500", + "BURUW": "0001814215", + "HPP-PC": "0001482512", + "BK-PK": "0001390777", + "JPM-PJ": "0000019617", + "AMJB": "0000019617", + "JPM-PK": "0000019617", + "JPM-PL": "0000019617", + "JPM-PM": "0000019617", + "VYLD": "0000019617", + "MFICL": "0001278752", + "ACR-PC": "0001332551", + "ACR-PD": "0001332551", + "CTO-PA": "0000023795", + "PFXNZ": "0001490349", + "MGR": "0001004434", + "MGRB": "0001004434", + "MGRD": "0001004434", + "MGRE": "0001004434", + "MSOGF": "0001815846", + "ACGLN": "0000947484", + "GSCE": "0000886982", + "QVCC": "0001254699", + "APCXW": "0001070050", + "PMTU": "0001464423", + "PMTW": "0001464423", + "PMTV": "0001464423", + "PMT-PC": "0001464423", + "BCEFF": "0000718940", + "BCEPF": "0000718940", + "BCEXF": "0000718940", + "BCAEF": "0000718940", + "BCENF": "0000718940", + "BCEIF": "0000718940", + "BCPPF": "0000718940", + "EPDU": "0001061219", + "CTTRF": "0001520504", + "UUGWF": "0001440130", + "PSQH-WT": "0001847064", + "SNPTF": "0001601992", + "ISADY": "0001608401", + "ISFFF": "0001608401", + "TWOD": "0001465740", + "PRENW": "0001876431", + "LFT-PA": "0001547546", + "VTTGF": "0001729514", + "GAB-PK": "0000794685", + "GAB-RI": "0000794685", + "ASRRF": "0001719117", + "PAAPU": "0001070423", + "TOGIW": "0001349706", + "GLU-PA": "0001282957", + "BPOPM": "0000763901", + "LFMDP": "0000948320", + "OSSFF": "0001437545", + "FLG-PU": "0000910073", + "FLG-PA": "0000910073", + "CPER": "0001479247", + "NLY-PI": "0001043219", + "NLY-PJ": "0001043219", + "HACBF": "0000793742", + "LOIMF": "0001454147", + "SOJD": "0000092122", + "SOJE": "0000092122", + "SOMN": "0000092122", + "SOJF": "0000092122", + "PTIXW": "0001022899", + "HTZWW": "0001657853", + "RWT-PA": "0000930236", + "RWTN": "0000930236", + "RWTP": "0000930236", + "RWTQ": "0000930236", + "RWTO": "0000930236", + "BXCAP": "0001372612", + "AEBMY": "0001174511", + "AEBMF": "0001174511", + "WGSWW": "0001818331", + "XRXDW": "0001770450", + "NGHLF": "0002060863", + "HQWWW": "0002088256", + "LTCHW": "0001826000", + "LSEB": "0001888740", + "TRSO": "0001758699", + "JELLF": "0002089509", + "DNACF": "0002065660", + "NPWR-WT": "0001845437", + "LAAI": "0001594968", + "SBBTF": "0001451561", + "FHN-PC": "0000036966", + "FHN-PE": "0000036966", + "FHN-PF": "0000036966", + "FHN-PH": "0000036966", + "RLMLF": "0002086869", + "CRYAF": "0002094687", + "MTMCF": "0002091028", + "BKLPF": "0001884130", + "CHWRF": "0001751162", + "HNSDF": "0001856488", + "KIM-PN": "0000879101", + "SQFTP": "0001080657", + "SQFTW": "0001080657", + "KPHMW": "0001372514", + "GGT-PG": "0000921671", + "MFA-PC": "0001055160", + "MFAN": "0001055160", + "MFAO": "0001055160", + "VSECU": "0000102752", + "RHEPZ": "0001004724", + "RHEPA": "0001004724", + "RHEPB": "0001004724", + "REXR-PC": "0001571283", + "MCHPP": "0000827054", + "RITM-PA": "0001556593", + "RITM-PB": "0001556593", + "RITM-PF": "0001556593", + "RITM-PE": "0001556593", + "RITM-PC": "0001556593", + "RITM-PD": "0001556593", + "ADAMI": "0001273685", + "ADAMN": "0001273685", + "ADAMG": "0001273685", + "ADAMM": "0001273685", + "ADAMH": "0001273685", + "ADAML": "0001273685", + "ADAMZ": "0001273685", + "ADAMO": "0001273685", + "BARKW": "0001819574", + "DRMAW": "0001853816", + "TDDWW": "0000098222", + "TDGMW": "0000098222", + "BESS-WT": "0001066764", + "ARR-PC": "0001428205", + "PSEC-PA": "0001287032", + "ILLRW": "0001769624", + "MET-PF": "0001099219", + "GENVR": "0000849399", + "GGBY": "0001616736", + "VNO-PN": "0000899689", + "VNO-PO": "0000899689", + "CCID": "0001517767", + "NCLTF": "0001801729", + "GDV-PK": "0001260729", + "ARES-PB": "0001176948", + "CMLSQ": "0001058623", + "XOMAO": "0000791908", + "XOMAP": "0000791908", + "ISMCF": "0001332174", + "WFC-PD": "0000072971", + "WAL-PA": "0001212545", + "WFC-PZ": "0000072971", + "WFCNP": "0000072971", + "WFC-PA": "0000072971", + "DLR-PL": "0001297996", + "USB-PQ": "0000036104", + "C-PN": "0000831001", + "C-PR": "0000831001", + "USB-PR": "0000036104", + "USB-PS": "0000036104", + "SWZCF": "0001069336", + "SMTGF": "0001516684", + "RENXF": "0001811115", + "KKRT": "0001404912", + "KKR-PD": "0001404912", + "KKRS": "0001404912", + "SLNHP": "0000064463", + "ALL-PI": "0000899051", + "ALL-PJ": "0000899051", + "SOARW": "0001853070", + "SAJ": "0001377936", + "TLGWF": "0001879814", + "TLGUF": "0001879814", + "SAT": "0001377936", + "SAY": "0001377936", + "SAZ": "0001377936", + "SAV": "0001377936", + "QTIWW": "0001844505", + "INVUP": "0000862651", + "TGOPF": "0001078716", + "CUENW": "0001424657", + "NRXPW": "0001719406", + "NXPLW": "0001058307", + "MNESP": "0000066570", + "FATPQ": "0001705012", + "FABTQ": "0001705012", + "SABSW": "0001833214", + "PBATF": "0001489088", + "CAHPF": "0001686009", + "WOLTF": "0000861967", + "CITAF": "0001317295", + "GCTS-WT": "0001851961", + "PREJF": "0000911421", + "HPHTF": "0001600928", + "LLOBF": "0001160106", + "TALKW": "0001803901", + "NMFCZ": "0001496099", + "ACONW": "0001635077", + "CICB": "0001534254", + "BKKT-WT": "0001820302", + "MITT-PC": "0001514281", + "RUMBW": "0001830081", + "HOLOW": "0001841209", + "MITN": "0001514281", + "MITP": "0001514281", + "CINGW": "0001862150", + "UZE": "0000821130", + "UZF": "0000821130", + "UZD": "0000821130", + "SKLTF": "0001487139", + "ABR-PD": "0001253986", + "ABR-PE": "0001253986", + "ABR-PF": "0001253986", + "CLDT-PA": "0001476045", + "ENZND": "0000727510", + "ANABV": "0001370053", + "ORANY": "0001038143", + "STSSW": "0001737995", + "ZNOGW": "0001131312", + "CYJBF": "0001436741", + "WHFCL": "0001552198", + "BCKIF": "0001516323", + "NXPGF": "0001455632", + "RILYZ": "0001464790", + "RILYG": "0001464790", + "RILYK": "0001464790", + "RILYL": "0001464790", + "RILYN": "0001464790", + "RILYP": "0001464790", + "RILYT": "0001464790", + "DFUKF": "0001805526", + "DFDVW": "0001805526", + "BOH-PA": "0000046195", + "BOH-PB": "0000046195", + "TCBIO": "0001077428", + "LGNDZ": "0000886163", + "LGNXZ": "0000886163", + "LGNYZ": "0000886163", + "LGNZZ": "0000886163", + "MBNKO": "0001000209", + "NMPWP": "0001004315", + "NEWEN": "0001004315", + "NMKCP": "0001004315", + "NMKBP": "0001004315", + "OXY-WT": "0000797468", + "CPNNF": "0001551468", + "CTPUF": "0001551468", + "FRBP": "0001825248", + "IPSOF": "0001582820", + "WEBJF": "0001778788", + "HTHL": "0001170839", + "BTBDW": "0001718224", + "MIMTF": "0001460447", + "BUSEP": "0000314489", + "SEATW": "0001856031", + "AERGP": "0000879911", + "AMPGZ": "0001518461", + "AMPGR": "0001518461", + "LSRCF": "0001822989", + "HIPOW": "0001828105", + "PASTF": "0001789135", + "TEN-PE": "0001166663", + "TEN-PF": "0001166663", + "SRTAW": "0001779128", + "DNOPF": "0001796026", + "NCHEF": "0001570299", + "EMCWF": "0001869601", + "EMCRF": "0001869601", + "EMCUF": "0001869601", + "HYAC-UN": "0001970509", + "HYAC-WT": "0001970509", + "PMVCW": "0001807765", + "OPFI-WT": "0001818502", + "ZTOEF": "0001677250", + "MNYWW": "0001974044", + "FORFF": "0001666175", + "FTRSF": "0001666175", + "FRTJF": "0001666175", + "FINCF": "0001666175", + "FRTSF": "0001666175", + "FTPSF": "0001666175", + "GIGGU": "0002023730", + "GIGGW": "0002023730", + "DFNSW": "0001787518", + "HYMCW": "0001718405", + "NWSZF": "0001449664", + "PDSKX": "0001756404", + "PRIAF": "0001819175", + "WALDW": "0001840199", + "CTLPP": "0000896429", + "MCOMW": "0001788841", + "SOCGM": "0000092108", + "OFSSH": "0001487918", + "OFSSO": "0001487918", + "TELFY": "0000814052", + "SLDPW": "0001844862", + "ZARE": "0001327978", + "T-PA": "0000732717", + "T-PC": "0000732717", + "CNO-PA": "0001224608", + "SCLXW": "0001820190", + "NWSLL": "0001564708", + "SCHW-PJ": "0000316709", + "GL-PD": "0000320335", + "GRBK-PA": "0001373670", + "XOSWW": "0001819493", + "FFAIW": "0001805521", + "VSEEW": "0001864531", + "RSNHF": "0001447391", + "AFGD": "0001042046", + "AFGE": "0001042046", + "AFGB": "0001042046", + "UHGWW": "0001830188", + "ETHMW": "0002028699", + "ETHMU": "0002028699", + "GFAIW": "0001804469", + "OZKAP": "0001569650", + "AGQ": "0001415311", + "BOIL": "0001415311", + "EUO": "0001415311", + "GLL": "0001415311", + "KOLD": "0001415311", + "YCL": "0001415311", + "YCS": "0001415311", + "ZSL": "0001415311", + "UGL": "0001415311", + "ULE": "0001415311", + "UVXY": "0001415311", + "VIXM": "0001415311", + "VIXY": "0001415311", + "SCO": "0001415311", + "SVXY": "0001415311", + "UCO": "0001415311", + "PRIF-PD": "0001554625", + "PRIF-PJ": "0001554625", + "PRIF-PK": "0001554625", + "PRIF-PL": "0001554625", + "BFH-PA": "0001101215", + "CIMP": "0001409493", + "CIMN": "0001409493", + "CIMO": "0001409493", + "LNWO": "0000750004", + "LAWIL": "0000750004", + "FIISO": "0000862831", + "DCOMP": "0000846617", + "DCOMG": "0000846617", + "FIISP": "0000862831", + "YRAIF": "0001279956", + "ORCL-PD": "0001341439", + "GRAF-WT": "0001897463", + "BEAGU": "0001852207", + "BEAGR": "0001852207", + "GIGGF": "0001336364", + "BAFBF": "0001506721", + "BTDPF": "0001516324", + "HSCSW": "0001468492", + "APADR": "0001956439", + "APADU": "0001956439", + "SOHGF": "0001536787", + "CRACR": "0002070887", + "CRACW": "0002070887", + "CRACU": "0002070887", + "WSTNU": "0002076192", + "WSTNR": "0002076192", + "EP-PC": "0001506307", + "LTRYW": "0001673481", + "LEGT-WT": "0002002038", + "LEGT-UN": "0002002038", + "ALFUW": "0002010930", + "ALFUU": "0002010930", + "WLACU": "0002032379", + "WLACW": "0002032379", + "OYSEU": "0002042182", + "OYSER": "0002042182", + "IRHOR": "0002051985", + "IRHOU": "0002051985", + "ENSCW": "0001716947", + "XAEIU": "0001023458", + "NPPXF": "0000769594", + "AACIU": "0002092897", + "AACIW": "0002092897", + "FUSEW": "0002033383", + "KTTAW": "0001841330", + "SRZNW": "0001824893", + "SLND-WT": "0001883814", + "TSPH": "0001823593", + "TRTX-PC": "0001630472", + "SATLW": "0001874315", + "ZCARW": "0001854275", + "UCFIW": "0001901203", + "PIIIW": "0001832511", + "IPCXU": "0002012318", + "IPCXR": "0002012318", + "CCNEP": "0000736772", + "HGASW": "0001817232", + "MBUMF": "0001534281", + "TOIIW": "0001799191", + "PNDZF": "0001505880", + "BYDIF": "0001447956", + "FKURF": "0002043424", + "CFOR": "0001293818", + "HCIIP": "0001400810", + "KMPB": "0000860748", + "SPE-PC": "0000897802", + "FIGP": "0001846702", + "HVIIU": "0001846416", + "HVIIR": "0001846416", + "EGHAR": "0002052547", + "EGHAU": "0002052547", + "INVLW": "0002001557", + "OBAWU": "0002034313", + "OBAWW": "0002034313", + "TLSIW": "0001826667", + "CILFY": "0001268896", + "NE-WTA": "0001895262", + "NE-WT": "0001895262", + "BERZ": "0000927971", + "KITTW": "0001849820", + "NOEMW": "0001956648", + "NOEMU": "0001956648", + "NOEMR": "0001956648", + "FNGO": "0000927971", + "FNGS": "0000927971", + "FNGU": "0000927971", + "GDXD": "0000927971", + "DULL": "0000927971", + "FLYD": "0000927971", + "FLYU": "0000927971", + "BIAFW": "0001712762", + "BNKD": "0000927971", + "BNKU": "0000927971", + "BULZ": "0000927971", + "JETU": "0000927971", + "JETD": "0000927971", + "CARD": "0000927971", + "CARU": "0000927971", + "SHNY": "0000927971", + "WTID": "0000927971", + "WTIU": "0000927971", + "GDXU": "0000927971", + "NRGD": "0000927971", + "NRGU": "0000927971", + "OILD": "0000927971", + "OILU": "0000927971", + "OTGAU": "0002077010", + "OTGAW": "0002077010", + "ILLUU": "0002101135", + "BHLLD": "0001407583", + "SORNW": "0002086263", + "SORNU": "0002086263", + "TACHW": "0002009183", + "TACHU": "0002009183", + "VNMEU": "0002055879", + "BAYAU": "0001969475", + "BAYAR": "0001969475", + "VNMEW": "0002055879", + "AILIO": "0000018654", + "AILIP": "0000018654", + "AENTW": "0001823584", + "KORGW": "0001855457", + "VEEAW": "0001840317", + "SMSOF": "0001560968", + "NTRSO": "0000073124", + "CPTKW": "0001827899", + "CNDIF": "0001045520", + "BA-PA": "0000012927", + "LUCYW": "0001808377", + "TOMYF": "0001826779", + "CLSKW": "0000827876", + "ASUUF": "0001876716", + "ASCRF": "0001876716", + "ASCWF": "0001876716", + "SENEM": "0000088948", + "SENEL": "0000088948", + "NBRGU": "0001918414", + "NBRGR": "0001918414", + "JWSUF": "0001831359", + "JWSWF": "0001831359", + "COOTW": "0001959994", + "BRRWW": "0002076163", + "CSTUF": "0001834032", + "CSTWF": "0001834032", + "LIDRW": "0001818644", + "BEATW": "0001779372", + "ZEOWW": "0001865506", + "FOXOW": "0001812360", + "JBHIF": "0001643198", + "INPOF": "0001848826", + "NXG-RW": "0001506488", + "CEHCF": "0001668393", + "NZEOY": "0001445654", + "RIV-PA": "0001501072", + "LKSPR": "0002043508", + "LKSPU": "0002043508", + "RNGTU": "0002078653", + "RNGTW": "0002078653", + "RGPX": "0001357878", + "GOODN": "0001234006", + "GOODO": "0001234006", + "PEB-PG": "0001474098", + "PEB-PH": "0001474098", + "BC-PC": "0000014930", + "GRKZF": "0001437462", + "TYHOF": "0002018139", + "IVDAW": "0001397183", + "ORGNW": "0001802457", + "KDKRW": "0001853138", + "HWLDF": "0001483994", + "TNONW": "0001560293", + "CNDAU": "0001851959", + "CNDAW": "0001851959", + "PLMUF": "0001845550", + "PLMWF": "0001845550", + "KGCRF": "0000701818", + "RAJAF": "0001885680", + "REGCO": "0000910606", + "REGCP": "0000910606", + "XELLL": "0000072903", + "OCSAW": "0001953530", + "AEFC": "0000769218", + "POWWP": "0001015383", + "SOUNW": "0001840856", + "MSPRW": "0001802450", + "MSPRZ": "0001802450", + "SCPQW": "0002083143", + "SCPQU": "0002083143", + "BDTB": "0002041531", + "NEMCL": "0001164727", + "ANG-PD": "0001039828", + "GME-WT": "0001326380", + "PAASF": "0000771992", + "PNMXO": "0000081023", + "MNLCF": "0001086888", + "MNUPF": "0001086888", + "MNQFF": "0001086888", + "MNUFF": "0001086888", + "MS-PL": "0000895421", + "GPMT-PA": "0001703644", + "SWDR": "0001711929", + "GCGJ": "0001765048", + "VAL-WT": "0000314808", + "MS-PQ": "0000895421", + "MS-PO": "0000895421", + "MS-PP": "0000895421", + "CEROW": "0001870404", + "EVGOW": "0001821159", + "STNDF": "0001087711", + "SNTUF": "0001087711", + "QVCGP": "0001355096", + "QVCGB": "0001355096", + "ATMP": "0000312070", + "BWVTF": "0000312070", + "DJP": "0000312070", + "GBUG": "0000312070", + "GRN": "0000312070", + "VXX": "0000312070", + "VXZ": "0000312070", + "JJETF": "0000312070", + "TAPR": "0000312070", + "NXDT-PA": "0001356115", + "BULLW": "0001866364", + "YCY-UN": "0002075336", + "YCY-WT": "0002075336", + "VHCPW": "0002086264", + "VHCPU": "0002086264", + "IGACU": "0002075068", + "IGACR": "0002075068", + "KFIIR": "0002029976", + "KFIIU": "0002029976", + "SPKLU": "0001884046", + "SPKLW": "0001884046", + "CUBWW": "0002015955", + "CUBWU": "0002015955", + "GPTGF": "0002075474", + "FRMEP": "0000712534", + "ZIONP": "0000109380", + "BIPH": "0001406234", + "BIPI": "0001406234", + "BIP-PA": "0001406234", + "BRIPF": "0001406234", + "BIPJ": "0001406234", + "BIP-PB": "0001406234", + "BEBE-WT": "0002079933", + "BEBE-UN": "0002079933", + "CWLXF": "0000831609", + "TRTN-PB": "0001660734", + "SMNRW": "0001913577", + "AISPW": "0001842566", + "MBAVU": "0002016072", + "MBAVW": "0002016072", + "TRTN-PC": "0001660734", + "TRTN-PD": "0001660734", + "TRTN-PE": "0001660734", + "TRTN-PF": "0001660734", + "TRTN-PG": "0001660734", + "BDMDW": "0001982444", + "AXINU": "0002057030", + "AXINR": "0002057030", + "TDBCP": "0000947263", + "CTAAU": "0002094073", + "TRAD-UN": "0002085485", + "IMAA": "0001980295", + "PDPA": "0001998043", + "EDVGF": "0002020414", + "IACOU": "0002091176", + "IACOW": "0002091176", + "ESHAR": "0001918661", + "CHPGU": "0002024460", + "CHPGR": "0002024460", + "MNSBP": "0001693577", + "ACAT": "0001781726", + "ONCHW": "0002054272", + "ONCHU": "0002054272", + "ZAPWF": "0001955104", + "CHECW": "0002047177", + "CHECU": "0002047177", + "COPL-WT": "0002045473", + "COPL-UN": "0002045473", + "CORZW": "0001839341", + "CORZZ": "0001839341", + "CORZR": "0001839341", + "ALUB-UN": "0002041493", + "ALUB-WT": "0002041493", + "CLRRF": "0001903392", + "CLRUF": "0001903392", + "CLRWF": "0001903392", + "ONFOW": "0001825452", + "ONFOP": "0001825452", + "IPEXR": "0002028355", + "IPEXU": "0002028355", + "BCSS-UN": "0002064355", + "BCSS-WT": "0002064355", + "GEGGL": "0001831096", + "GIBOW": "0002034520", + "ALB-PA": "0000915913", + "FEAV": "0001888654", + "BZAIW": "0001871638", + "FLYX-WT": "0001843973", + "FOUR-PA": "0001794669", + "CFG-PE": "0000759944", + "CFG-PH": "0000759944", + "CFG-PI": "0000759944", + "FCNCO": "0000798941", + "FCNCP": "0000798941", + "FCNCN": "0000798941", + "NASC": "0001509957", + "VIVKD": "0001450704", + "SVNHF": "0002089488", + "LSHGF": "0002063675", + "AMUB": "0001114446", + "BDCX": "0001114446", + "BDCZ": "0001114446", + "CEFD": "0001114446", + "USML": "0001114446", + "UCIB": "0001114446", + "MVRL": "0001114446", + "PFFL": "0001114446", + "QULL": "0001114446", + "SCDL": "0001114446", + "SMHB": "0001114446", + "IWML": "0001114446", + "MLPB": "0001114446", + "MLPR": "0001114446", + "MTUL": "0001114446", + "HDLB": "0001114446", + "IFED": "0001114446", + "IWDL": "0001114446", + "IWFL": "0001114446", + "WELPM": "0000107815", + "AQNB": "0001174169", + "AGQPF": "0001174169", + "SCE-PG": "0000092103", + "SCE-PL": "0000092103", + "SCE-PN": "0000092103", + "SCE-PM": "0000092103", + "FPHOY": "0001490078", + "FRSPF": "0001490078", + "FGNXP": "0001591890", + "HNSPF": "0002073669", + "NAMMW": "0002026514", + "SVCCW": "0002033593", + "SVCCU": "0002033593", + "INACR": "0002063816", + "INACU": "0002063816", + "IBIDF": "0001654508", + "SMEGF": "0001830056", + "LARAX": "0001753712", + "PERF-WT": "0001899830", + "FTAIM": "0001590364", + "FTAIN": "0001590364", + "FACTU": "0002028935", + "FACTW": "0002028935", + "LACHF": "0002023870", + "SMFRF": "0002048270", + "BSMLP": "0001621434", + "MNMXF": "0002109556", + "TYNPF": "0002019040", + "ADYYF": "0001788707", + "PSKRF": "0001789444", + "FCRX": "0001633336", + "WEIBF": "0001595761", + "PVOZ": "0001824204", + "SLFIF": "0001097362", + "SUNFF": "0001097362", + "SLFQF": "0001097362", + "PFH": "0001137774", + "PRH": "0001137774", + "PRS": "0001137774", + "MCAGR": "0001859035", + "MCAGU": "0001859035", + "CFNHS": "0001874979", + "CTYFS": "0001874979", + "CTFTS": "0001874979", + "CTFDS": "0001874979", + "CTFPS": "0001874979", + "CTYDS": "0001874979", + "CFLAS": "0001874979", + "CTFMS": "0001874979", + "VTBAS": "0001984345", + "CANE": "0001471824", + "CORN": "0001471824", + "SOYB": "0001471824", + "TAGS": "0001471824", + "WEAT": "0001471824", + "XAGEW": "0001842939", + "BWBBP": "0001341317", + "CFR-PB": "0000039263", + "SPHIF": "0001995306", + "COBA": "0001727255", + "LLYVK": "0002078416", + "LLYVB": "0002078416", + "VMCWF": "0001892747", + "VMCUF": "0001892747", + "JACS-UN": "0002039058", + "JACS-RI": "0002039058", + "NFTM": "0001345865", + "PONOU": "0002108164", + "BIXIU": "0002082542", + "BIXIW": "0002082542", + "ALOVW": "0002083989", + "ALOVU": "0002083989", + "PALOU": "0002101562", + "NSA-PB": "0001618563", + "CTDD": "0000068622", + "PSPX": "0001765651", + "VLDXW": "0001825079", + "OPTXW": "0001866816", + "NVACW": "0001859807", + "OCCIN": "0001716951", + "OCCIM": "0001716951", + "OCCIO": "0001716951", + "GRTUF": "0001564538", + "BRLSW": "0001852973", + "MLECW": "0001937737", + "GAFC": "0001989788", + "IXQUF": "0001852019", + "IXQWF": "0001852019", + "INNPF": "0001889791", + "MGTEW": "0001965052", + "LAFAU": "0002079106", + "LAFAR": "0002079106", + "ATIIU": "0002028516", + "ATIIW": "0002028516", + "RFAIU": "0002012807", + "RFAIR": "0002012807", + "AMLIF": "0001699880", + "TPGXL": "0001880661", + "AHL-PF": "0001267395", + "NAKAW": "0001946573", + "RBOTW": "0001812173", + "MDAIW": "0001833498", + "SKYH-WT": "0001823587", + "ECXWW": "0001861974", + "PRXK": "0001692345", + "PRXA": "0001692345", + "FNCHQ": "0001733257", + "FSTWF": "0002014254", + "RWAYL": "0001653384", + "RWAYI": "0001653384", + "MTB-PJ": "0000036270", + "MTB-PH": "0000036270", + "MTB-PK": "0000036270", + "TXEMF": "0000909112", + "MKLYU": "0002067592", + "MKLYR": "0002067592", + "RNR-PG": "0000913144", + "MZYX-UN": "0002097376", + "TVACU": "0002033991", + "TVACW": "0002033991", + "SVIVU": "0002098242", + "SVIVW": "0002098242", + "NVAWW": "0001852551", + "NVAAF": "0001852551", + "INFQ-WT": "0002007825", + "IRAB-WT": "0002077785", + "IRAB-UN": "0002077785", + "SSEAU": "0002059165", + "SSEAR": "0002059165", + "KBONW": "0002088749", + "KBONU": "0002088749", + "ZPTAW": "0001843714", + "DUKB": "0001326160", + "CCGWW": "0001965473", + "KEY-PL": "0000091576", + "GIXXR": "0002098712", + "GIXXU": "0002098712", + "EMISR": "0002075816", + "PCG-PX": "0001004980", + "ATCHW": "0001963088", + "QFNHF": "0001741530", + "NMHIW": "0001947861", + "JXADF": "0002065485", + "SPHXF": "0002063413", + "MEIUF": "0001699967", + "SBCWW": "0001930313", + "ONBPO": "0000707179", + "ONBPP": "0000707179", + "BKPKF": "0002075877", + "GLP-PB": "0001323468", + "LVWR-WT": "0001898795", + "OPADW": "0001825024", + "VENAF": "0001800392", + "UYSCR": "0002036973", + "UYSCU": "0002036973", + "APXTU": "0002079253", + "APXTW": "0002079253", + "PACHW": "0002040381", + "PACHU": "0002040381", + "BLZRW": "0002075310", + "BLZRU": "0002075310", + "GDEVW": "0001848739", + "ABLVW": "0001957489", + "ALPWF": "0002025774", + "KTWOR": "0002086524", + "KTWOU": "0002086524", + "BHAVU": "0002097288", + "FIGXW": "0002059033", + "FIGXU": "0002059033", + "HSPUF": "0001946021", + "HSPWF": "0001946021", + "DMAAU": "0002028614", + "DMAAR": "0002028614", + "BWNB": "0001630805", + "BW-PA": "0001630805", + "GPUS-PD": "0000896493", + "TFSA": "0001577134", + "IVBXF": "0001774163", + "BGLWW": "0002019435", + "ALSUF": "0001865111", + "ALSTF": "0001865111", + "ALSWF": "0001865111", + "YBZN": "0001885514", + "ICUCW": "0001831868", + "MVSTW": "0001760689", + "FBRT-PE": "0001562528", + "BSTT": "0001662972", + "SGST": "0001852575", + "BRKRP": "0001109354", + "METCI": "0001687187", + "METCB": "0001687187", + "METCZ": "0001687187", + "CUBTD": "0001400271", + "CLDWW": "0001855485", + "FNFPA": "0001065823", + "CRGOW": "0001927719", + "BKSY-WT": "0001753539", + "DSX-WT": "0001318885", + "NXGLW": "0001468929", + "AREBW": "0001648087", + "DHCNI": "0001075415", + "DHCNL": "0001075415", + "IBACR": "0001998781", + "KCHVU": "0002053799", + "GLCP": "0001830696", + "KCHVR": "0002053799", + "LPAAU": "0002015502", + "LPAAW": "0002015502", + "HSPTU": "0002032950", + "HSPTR": "0002032950", + "PMCUF": "0002013003", + "NSKFF": "0001535759", + "BUGDF": "0001547870", + "BUHPF": "0001547870", + "BUHHF": "0001547870", + "BTMWW": "0001901799", + "HCTPF": "0001580226", + "AUB-PA": "0000883948", + "HBANZ": "0000049196", + "HBANM": "0000049196", + "HBANP": "0000049196", + "HWCPZ": "0000750577", + "HBANL": "0000049196", + "RCD": "0001527590", + "RCB": "0001527590", + "RC-PC": "0001527590", + "RC-PE": "0001527590", + "NHPBP": "0001561032", + "SUMAU": "0002105838", + "KUKEY": "0001809158", + "VGASW": "0001841425", + "PDYNW": "0001826681", + "GECCH": "0001675033", + "GECCG": "0001675033", + "GECCO": "0001675033", + "GECCI": "0001675033", + "BKHAU": "0002000775", + "BKHAR": "0002000775", + "KRSP-WT": "0002074872", + "KRSP-UN": "0002074872", + "AEAQU": "0002083689", + "AEAQW": "0002083689", + "DSACU": "0002082149", + "DSACW": "0002082149", + "CBRGF": "0001845149", + "CBGGF": "0001845149", + "RTACW": "0002035173", + "RTACU": "0002035173", + "TCLHF": "0002073804", + "ACP-PA": "0001503290", + "GMWKF": "0002062522", + "TNMWF": "0002013186", + "ESMR": "0001995920", + "WRDIF": "0001867729", + "FVNNU": "0002010653", + "FVNNR": "0002010653", + "BTSGU": "0001865782", + "BNAIW": "0001838163", + "GDHLF": "0001526125", + "LVROF": "0001945711", + "LVRWF": "0001945711", + "SKILW": "0001774675", + "CHARR": "0002024459", + "CHARU": "0002024459", + "PLMKW": "0002030482", + "PLMKU": "0002030482", + "SPEGU": "0002028735", + "SPEGR": "0002028735", + "MDDNF": "0002063417", + "RVMDW": "0001628171", + "DTSQR": "0002017950", + "DTSQU": "0002017950", + "GIPRW": "0001651721", + "OABIW": "0001846253", + "TMTSU": "0002097364", + "TMTSW": "0002097364", + "TRINI": "0001786108", + "TRINZ": "0001786108", + "EBOSF": "0001533082", + "LENDX": "0001658645", + "WRLWF": "0001733968", + "WRLRF": "0001733968", + "WLGMF": "0001733968", + "MLSPF": "0001516535", + "IMSRW": "0002019804", + "FBYDW": "0001937987", + "MPLXP": "0001552000", + "ZHIHF": "0001835724", + "SIMAW": "0002014982", + "SIMAU": "0002014982", + "CLBR-UN": "0002091024", + "CLBR-WT": "0002091024", + "CXAIW": "0001820875", + "SWKHL": "0001089907", + "AACBR": "0002034334", + "AACBU": "0002034334", + "TCMEF": "0001744676", + "GAINN": "0001321741", + "GAINZ": "0001321741", + "GAING": "0001321741", + "GAINI": "0001321741", + "AGNCL": "0001423689", + "AGNCO": "0001423689", + "AGNCP": "0001423689", + "AGNCZ": "0001423689", + "CHSCL": "0000823277", + "CHSCM": "0000823277", + "CHSCN": "0000823277", + "CHSCO": "0000823277", + "SHO-PH": "0001295810", + "SHO-PI": "0001295810", + "IHETW": "0001400891", + "PCTBP": "0001830033", + "PCTTU": "0001830033", + "PCTTW": "0001830033", + "ASB-PF": "0000007789", + "ASBA": "0000007789", + "NEWTP": "0001587987", + "NEWTG": "0001587987", + "NEWTO": "0001587987", + "NEWTH": "0001587987", + "ANSCU": "0001854149", + "ANSCW": "0001854149", + "FULTP": "0000700564", + "XXAAU": "0000931755", + "NEE-PN": "0000753308", + "NEE-PW": "0000753308", + "NEE-PT": "0000753308", + "NEE-PU": "0000753308", + "NEE-PV": "0000753308", + "NEE-PS": "0000753308", + "TBNRL": "0001997652", + "FITBO": "0000035527", + "FITBP": "0000035527", + "FITBM": "0000035527", + "SREA": "0001032208", + "SNIRF": "0001329213", + "ONMDW": "0001849380", + "AHRT-PA": "0001569187", + "JSPRW": "0001788028", + "XAKJ": "0001128252", + "DSYWW": "0001999297", + "PTCCY": "0001108329", + "GLDI": "0001053092", + "SLVO": "0001053092", + "USOI": "0001053092", + "LNZAW": "0001843724", + "ERNAW": "0000748592", + "CSCIF": "0001113423", + "EONR-WT": "0001842556", + "LCFYW": "0001875547", + "NNFSF": "0001834267", + "PINE-PA": "0001786117", + "DBVTF": "0001613780", + "VRBCF": "0002029969", + "BAMKF": "0001001085", + "BKAMF": "0001001085", + "BKFAF": "0001001085", + "BKFPF": "0001001085", + "FGBIP": "0001408534", + "BKFOF": "0001001085", + "BRPSF": "0001001085", + "BRFCF": "0001001085", + "BKPA": "0001001085", + "BNH": "0001001085", + "BNJ": "0001001085", + "BROXF": "0001001085", + "BXDIF": "0001001085", + "BRCFF": "0001001085", + "BKFDF": "0001001085", + "WBKCY": "0000719245", + "FVGPY": "0001691445", + "FSHPR": "0001850059", + "EVEX-WT": "0001823652", + "RMSGW": "0001983324", + "ATEKU": "0001882198", + "ATEKW": "0001882198", + "HRZRF": "0002060217", + "SOUL-RI": "0002025608", + "SOUL-UN": "0002025608", + "MBINL": "0001629019", + "MBINM": "0001629019", + "MBINN": "0001629019", + "SCAGW": "0002000366", + "RMCOW": "0001843656", + "PLSAY": "0001884082", + "PSEWF": "0001833835", + "SIGIP": "0000230557", + "RMTHF": "0000876779", + "BPYPM": "0001545772", + "BPYPN": "0001545772", + "BPYPO": "0001545772", + "CAPTW": "0001967478", + "ICRL": "0001690012", + "ICRP": "0001690012", + "KMFG": "0001935033", + "RPT-PC": "0001614806", + "MDV-PA": "0001645873", + "LOMWF": "0001509397", + "SHLAF": "0001655190", + "SHLRF": "0001655190", + "WCPRF": "0001472879", + "NICHX": "0001736510", + "AGM-PE": "0000845877", + "AGM-PF": "0000845877", + "AGM-PG": "0000845877", + "AGM-PH": "0000845877", + "GCLWW": "0002002045", + "DFSCW": "0001889823", + "EVTWF": "0001867102", + "UNTCW": "0000798949", + "SDMHF": "0001794363", + "KOYNW": "0002068454", + "KOYNU": "0002068454", + "DPCDF": "0002094201", + "FLNCF": "0002065932", + "CRANR": "0002081358", + "CRANU": "0002081358", + "BEIGF": "0001651308", + "ABPWW": "0001893219", + "LSBWF": "0001946399", + "LANV-WT": "0001922097", + "DPLMF": "0001529906", + "EYGPF": "0001562294", + "EYUUF": "0001562294", + "AIBRF": "0001728918", + "MPNGF": "0001754088", + "KRNGF": "0001494191", + "CDTTW": "0001896212", + "PL-WT": "0001836833", + "LBRDP": "0001611983", + "MNTSW": "0001781162", + "LWACU": "0002061379", + "LWACW": "0002061379", + "FGSN": "0001934850", + "FGN": "0001934850", + "RNWWW": "0001848763", + "GRRRW": "0001903145", + "TETWF": "0001900679", + "TETUF": "0001900679", + "OPENW": "0001801169", + "OPENL": "0001801169", + "OPENZ": "0001801169", + "TMSOF": "0001075124", + "MBVIW": "0002073928", + "MBVIU": "0002073928", + "RSVRW": "0001824403", + "ADC-PA": "0000917251", + "ISLUF": "0001915328", + "ISLWF": "0001915328", + "PETVW": "0001512922", + "ASAIY": "0001834048", + "KREF-PA": "0001631596", + "CCIXU": "0002006291", + "CCIXW": "0002006291", + "COF-PI": "0000927628", + "COF-PJ": "0000927628", + "COF-PK": "0000927628", + "COF-PL": "0000927628", + "COF-PN": "0000927628", + "FNMAP": "0000310522", + "MONRF": "0001605755", + "OWSCX": "0001748680", + "BETRW": "0001835856", + "PYAIF": "0001969302", + "CAPNU": "0002024203", + "CAPNR": "0002024203", + "AIIOW": "0001932737", + "SGIPF": "0002027330", + "DRDBU": "0002032528", + "DRDBW": "0002032528", + "LBRA": "0001599407", + "OACCU": "0002029769", + "FGIIU": "0002090452", + "FGIIW": "0002090452", + "OACCW": "0002029769", + "BHFAM": "0001685040", + "BHFAN": "0001685040", + "BHFAO": "0001685040", + "NVNIW": "0001965143", + "MMTXU": "0002077033", + "MMTXW": "0002077033", + "VACI-WT": "0002080023", + "QUMSU": "0002070900", + "QUMSR": "0002070900", + "VACI-UN": "0002080023", + "BRLLD": "0001631463", + "ZKPU": "0002087447", + "ZKPW": "0002087447", + "LPCVW": "0002083728", + "LPCVU": "0002083728", + "NRSAX": "0001663712", + "FREJP": "0001026214", + "FMCKK": "0001026214", + "ACHR-WT": "0001824502", + "BFS-PE": "0000907254", + "PHXE-P": "0001818643", + "RNGOF": "0002092252", + "KELRF": "0002107989", + "YMTKF": "0002107946", + "STTPF": "0002018852", + "TKMEF": "0002044863", + "ZSHOF": "0002088776", + "DLMAF": "0002073893", + "OKMN": "0001848334", + "ACQC": "0001860484", + "MPTI-RI": "0001902314", + "WELWF": "0001877557", + "WELUF": "0001877557", + "PAII-UN": "0002069238", + "PAII-WT": "0002069238", + "BNCWW": "0001482541", + "ALDFU": "0002031561", + "ALDFW": "0002031561", + "CRBD": "0001889539", + "LWSCF": "0002073972", + "CELUW": "0001752828", + "JNGHF": "0002071868", + "KYFGF": "0002042187", + "KXHCF": "0002053383", + "ONWRF": "0002059986", + "ASBRF": "0002055337", + "SPME": "0001930147", + "SPMA": "0001930147", + "TVGNW": "0001860871", + "BCTXL": "0001610820", + "BCTXZ": "0001610820", + "KYIVW": "0002062440", + "SHFH": "0002032609", + "QADRU": "0002083217", + "MSEXP": "0000066004", + "DAAQW": "0002052162", + "DAAQU": "0002052162", + "XRPNW": "0002044009", + "XRPNU": "0002044009", + "AMVIF": "0002085236", + "MSOKF": "0002087844", + "TOKCF": "0002066601", + "MBGCF": "0002079706", + "BGTCF": "0002098425", + "GGPSF": "0002087843", + "YMATF": "0002108185", + "STRD": "0001050446", + "STRF": "0001050446", + "STRK": "0001050446", + "IONQ-WT": "0001824920", + "CNVEF": "0001475260", + "BENFW": "0001775734", + "SDSTW": "0001831979", + "DBRG-PH": "0001679688", + "DBRG-PI": "0001679688", + "DBRG-PJ": "0001679688", + "APXCF": "0002093856", + "RDZNW": "0001868640", + "SEPSF": "0001969766", + "AOMD": "0001766478", + "AOMN": "0001766478", + "CDIOW": "0001870144", + "BGMSP": "0001130166", + "RDAGU": "0002055459", + "RDAGW": "0002055459", + "WLIIU": "0002083946", + "WLIIW": "0002083946", + "SAAQU": "0002091222", + "SAAQW": "0002091222", + "USGOW": "0001947244", + "POLEU": "0002025341", + "POLEW": "0002025341", + "FGMCU": "0001906364", + "FGMCR": "0001906364", + "DNMXU": "0002081125", + "DNMXW": "0002081125", + "MSSWF": "0001882464", + "MSSUF": "0001882464", + "RIBBU": "0002035016", + "PMTRU": "0002061473", + "PMTRW": "0002061473", + "RIBBR": "0002035016", + "LTMGF": "0002041918", + "EDBLW": "0001809750", + "WLSS": "0001887912", + "AWTRF": "0002092258", + "LPUGF": "0002068440", + "EURBF": "0002106126", + "LIMNW": "0001971387", + "BZFDW": "0001828972", + "VWAVW": "0002038439", + "JOBY-WT": "0001819848", + "FOACW": "0001828937", + "PTORW": "0002093912", + "PTORU": "0002093912", + "MYSEW": "0001648960", + "XBPEW": "0001839530", + "GGROW": "0001886190", + "DUTBF": "0002085208", + "HFRO-PA": "0001710680", + "HFRO-PB": "0001710680", + "SCSKF": "0002063116", + "BBCQU": "0002088295", + "BBCQW": "0002088295", + "IGTAR": "0001866838", + "IGTAU": "0001866838", + "IGTAW": "0001866838", + "PW-PA": "0001532619", + "FUFUW": "0001921158", + "BCGWW": "0001953984", + "MACT": "0001957783", + "AKPPS": "0001923734", + "TANAF": "0001941189", + "WTFCN": "0001015328", + "SUNXF": "0002048958", + "MSBIP": "0001466026", + "ANGHW": "0001871983", + "EURKR": "0002000410", + "EURKU": "0002000410", + "SSTPW": "0001805833", + "BCARW": "0002065779", + "BCARU": "0002065779", + "TDACU": "0001926599", + "TDACW": "0001926599", + "DUKRD": "0001638911", + "ARQQW": "0001859690", + "NTRBW": "0001676047", + "DAVEW": "0001841408", + "BPACU": "0002064177", + "BPACR": "0002064177", + "GIWWU": "0002080019", + "GIWWR": "0002080019", + "IPODW": "0002041047", + "IPODU": "0002041047", + "RAC-UN": "0002047497", + "RAC-WT": "0002047497", + "TWLVR": "0002052243", + "TWLVU": "0002052243", + "APOS": "0001858681", + "UAC-UN": "0002098669", + "UAC-WT": "0002098669", + "TRGSU": "0002098780", + "DBCAW": "0002095161", + "DBCAU": "0002095161", + "MRCIF": "0001752564", + "SHMZF": "0001648512", + "DGMDF": "0002034300", + "BYCBF": "0001706795", + "NNWWF": "0002073913", + "CNDHF": "0002091663", + "REEWF": "0001889112", + "REEUF": "0001889112", + "BRETF": "0002018463", + "SNROF": "0001584273", + "AFRIW": "0001903870", + "QSEAR": "0002047455", + "QSEAU": "0002047455", + "TFIN-P": "0001539638", + "IMAQR": "0001846235", + "IMAQU": "0001846235", + "IMAQW": "0001846235", + "CMCAU": "0001865248", + "CMCAW": "0001865248", + "MLAAW": "0002094265", + "MLAAU": "0002094265", + "SAC-UN": "0002082844", + "SAC-WT": "0002082844", + "HMELF": "0001853630", + "GRWLF": "0000850918", + "GRWTF": "0000850918", + "GWLPF": "0000850918", + "GRWFF": "0000850918", + "ESLAW": "0001844417", + "NHKGF": "0002087500", + "LGSP": "0001970129", + "PSBAF": "0002063685", + "NGSCF": "0002092248", + "QGAI": "0001663038", + "WTGUU": "0002053927", + "WTGUR": "0002053927", + "BSAAR": "0002051587", + "BSAAU": "0002051587", + "STSR": "0001698538", + "STLJF": "0002077242", + "TOETF": "0002089506", + "CPWPF": "0002071911", + "CPRHF": "0002071911", + "CPXWF": "0002071911", + "PCCOF": "0002089174", + "KATJF": "0002109545", + "JTGLF": "0001472033", + "ELEEF": "0002073615", + "EUDAW": "0001847846", + "NAMSW": "0001936258", + "TACOU": "0002033122", + "TACOW": "0002033122", + "FGRS": "0002064124", + "LOCLW": "0001840780", + "DRRKF": "0001705969", + "AACOU": "0002099906", + "THTG": "0002029303", + "DRTSW": "0001871321", + "RVSNW": "0001743905", + "EPR-PC": "0001045450", + "EPR-PE": "0001045450", + "ALTG-PA": "0001759824", + "ARTCW": "0002086545", + "ARTCU": "0002086545", + "IRS-WT": "0000933267", + "PSA-PI": "0001393311", + "PSA-PJ": "0001393311", + "PSA-PF": "0001393311", + "PSA-PG": "0001393311", + "NREF-PA": "0001786248", + "SQLLW": "0001605888", + "BGFR": "0001722556", + "PSA-PL": "0001393311", + "PSA-PM": "0001393311", + "PSA-PN": "0001393311", + "PSA-PO": "0001393311", + "PSA-PP": "0001393311", + "PSA-PQ": "0001393311", + "PSA-PR": "0001393311", + "PSA-PS": "0001393311", + "GLED-UN": "0002091484", + "COLAU": "0002028201", + "COLAR": "0002028201", + "SOCAW": "0002065948", + "SOCAU": "0002065948", + "LOTWW": "0001962746", + "DTSTW": "0001419951", + "FCRS-WT": "0002074697", + "FCRS-UN": "0002074697", + "IEAGR": "0002084396", + "IEAGU": "0002084396", + "CCLDO": "0001582982", + "SBXE-UN": "0002081909", + "SBXE-WT": "0002081909", + "WYTC": "0001560143", + "RAAQW": "0002052161", + "KVACW": "0001889983", + "RAAQU": "0002052161", + "KVACU": "0001889983", + "ECCC": "0001604174", + "ECC-PD": "0001604174", + "ECCU": "0001604174", + "ECCV": "0001604174", + "ECCW": "0001604174", + "PUIGF": "0002029472", + "HSIGF": "0001861737", + "MGHTF": "0002062807", + "BWET": "0001610940", + "PAACU": "0002087446", + "PAACW": "0002087446", + "BDCIW": "0002042292", + "BDCIU": "0002042292", + "EVOXW": "0002077954", + "EVOXU": "0002077954", + "DYORW": "0002079292", + "DYORU": "0002079292", + "ZIVOW": "0001101026", + "LOKVW": "0002048951", + "LOKVU": "0002048951", + "ASPSZ": "0001462418", + "ASPSW": "0001462418", + "AAVXF": "0001956827", + "GRMLW": "0001907223", + "CSHRW": "0002087587", + "JXN-PA": "0001822993", + "LDXC": "0001985554", + "TOYWF": "0001985273", + "MICLF": "0002032399", + "AMBWQ": "0001937441", + "AMBIQ": "0001937441", + "GHBWF": "0001848731", + "MUZEW": "0002093484", + "MUZEU": "0002093484", + "NHICU": "0002043699", + "NHICW": "0002043699", + "SDHIU": "0002034037", + "SDHIR": "0002034037", + "SWCPF": "0002107960", + "MAWAF": "0002093667", + "ODERF": "0002108124", + "GFRWF": "0001966287", + "AIMUF": "0001903464", + "AIMWF": "0001903464", + "AQUNR": "0001861063", + "AQUNU": "0001861063", + "SATLF": "0001679920", + "ANNAW": "0001845123", + "PGACU": "0002030829", + "PGACR": "0002030829", + "MTAL-UN": "0002107724", + "RFAMR": "0002091712", + "RFAMU": "0002091712", + "IAUX-WT": "0001853962", + "GSTK": "0001917993", + "CPPTL": "0001837671", + "SACH-PA": "0001682220", + "SCCD": "0001682220", + "SCCE": "0001682220", + "SCCF": "0001682220", + "SCCG": "0001682220", + "HEMNF": "0001915760", + "NUAIW": "0002028336", + "SATA": "0001920406", + "APTN": "0001938571", + "SXTPW": "0001946563", + "RTEZ": "0001733861", + "NMPRY": "0001333172", + "NIOBW": "0001512228", + "VLN-WT": "0001863006", + "OXSQH": "0001259429", + "OXSQG": "0001259429", + "SHMLF": "0001166834", + "UMBFO": "0000101382", + "OPTHF": "0002027329", + "WBS-PG": "0000801337", + "RGTIW": "0001838359", + "MDCXW": "0001997296", + "ARBEW": "0001861841", + "TLPPF": "0002007191", + "ALURW": "0001964979", + "HTFC": "0001487428", + "EVAC-UN": "0002042902", + "EVAC-WT": "0002042902", + "HCMAU": "0002069856", + "HCMAW": "0002069856", + "NOTEW": "0001823466", + "HCICU": "0002099093", + "HCICR": "0002099093", + "FOXXW": "0002013807", + "LABFF": "0002029970", + "PEW-WT": "0002051380", + "EFSCP": "0001025835", + "OIOWW": "0001957538", + "STRRP": "0001210708", + "NUCLW": "0002089283", + "HNIT": "0001994373", + "GSRFU": "0002072404", + "GSRFR": "0002072404", + "MEVOW": "0002087361", + "MEVOU": "0002087361", + "TLNCU": "0002073340", + "TLNCW": "0002073340", + "PRBZF": "0001503812", + "GTENW": "0001986817", + "GTENU": "0001986817", + "MOVAA": "0000072573", + "SBXD-UN": "0002015947", + "SBXD-WT": "0002015947", + "RLNDF": "0001924064", + "RPDL": "0001910975", + "CODI-PC": "0001345126", + "AMPWF": "0001845097", + "ET-PI": "0001276187", + "DDT": "0000028917", + "CCIIW": "0002064683", + "CCIIU": "0002064683", + "INN-PF": "0001497645", + "EFC-PB": "0001411342", + "EFC-PC": "0001411342", + "EFC-PD": "0001411342", + "JFBRW": "0001885408", + "INVZW": "0001835654", + "SLXNW": "0002022416", + "PBMWW": "0001985062", + "ACGP": "0001642122", + "AEAEU": "0001852016", + "AEAEW": "0001852016", + "PRCWF": "0001863362", + "NEXRW": "0001885408", + "NRSNW": "0001875091", + "QSIAW": "0001816431", + "LNC-PD": "0000059558", + "YDESW": "0002011674", + "AUIWF": "0001568183", + "TGE-WT": "0002053456", + "ALCYU": "0001901336", + "ALCYW": "0001901336", + "MGCOF": "0002039784", + "SHMDW": "0001987240", + "ALEGF": "0002046098", + "OXLCN": "0001495222", + "BLNH": "0002029586", + "KWMWW": "0002000756", + "ZOOZW": "0001992818", + "OXLCL": "0001495222", + "OXLCI": "0001495222", + "OXLCP": "0001495222", + "OXLCZ": "0001495222", + "OXLCG": "0001495222", + "MKDWW": "0001991332", + "SEAL-PA": "0001308106", + "SEAL-PB": "0001308106", + "WHLRL": "0001527541", + "IINNW": "0001837493", + "SMXWW": "0001940674", + "DTK": "0000936340", + "DTG": "0000936340", + "DTB": "0000936340", + "KPET-UN": "0002095297", + "HACQW": "0002089982", + "HACQU": "0002089982", + "JENA-UN": "0002060337", + "JENA-RI": "0002060337", + "BWIV-UN": "0002082847", + "ALBC": "0001834868", + "TCEYF": "0001232384", + "TCENF": "0001232384", + "TCNCF": "0001232384", + "TRPRF": "0001232384", + "TRPPF": "0001232384", + "TRPEF": "0001232384", + "EBGEF": "0000895728", + "EBRGF": "0000895728", + "EBRZF": "0000895728", + "PRHIZ": "0001502292", + "ENBFF": "0000895728", + "AZLUY": "0001432364", + "AZUXY": "0001432364", + "AZSAY": "0001432364", + "GDLG": "0001848672", + "BFRIW": "0001858685", + "OZVN": "0001751707", + "AIRJW": "0001855474", + "EBBGF": "0000895728", + "ENBNF": "0000895728", + "ENFFF": "0000895728", + "ENBHF": "0000895728", + "ENBMF": "0000895728", + "ENBOF": "0000895728", + "ENBSF": "0000895728", + "ENBGF": "0000895728", + "ENBRF": "0000895728", + "ENNPF": "0000895728", + "GPACU": "0002085408", + "GPACW": "0002085408", + "BBAAY": "0001577552", + "CCXIU": "0002074973", + "CCXIW": "0002074973", + "TRAXV": "0002091349", + "ABVEW": "0001979484", + "WNRS": "0001587603", + "HVMCW": "0002070602", + "HVMCU": "0002070602", + "BIVIW": "0001580149", + "MGSD": "0002003750", + "GLTK": "0001938338", + "MRNOW": "0001988776", + "WBXWF": "0001866501", + "HUBCW": "0001905660", + "HUBCZ": "0001905660", + "THRC": "0001409253", + "HSCT": "0001721056", + "QETAR": "0001978528", + "QETAU": "0001978528", + "MLCMF": "0000912958", + "SES-WT": "0001819142", + "WENNW": "0002057043", + "WENNU": "0002057043", + "DFLIW": "0001847986", + "AVSBS": "0002032732", + "AVPKS": "0002032732", + "AEHGS": "0002032732", + "ALOIS": "0002032732", + "FERAR": "0002025401", + "FERAU": "0002025401", + "CRAQR": "0002058359", + "CRAQU": "0002058359", + "NWAX-UN": "0002074878", + "NWAX-WT": "0002074878", + "LZM-WT": "0001958217", + "LMMY": "0001939937", + "TICAW": "0002032966", + "MXUGF": "0002061911", + "CRMLW": "0001951089", + "CRTMF": "0001951089", + "SVAUF": "0002074157", + "STHRF": "0002068441", + "TRWD": "0001916558", + "IMPPP": "0001876581", + "SYF-PA": "0001601712", + "SYF-PB": "0001601712", + "NCPLW": "0001414767", + "TBLAW": "0001840502", + "PGYWW": "0001883085", + "PNFP-PB": "0002082866", + "PNFP-PC": "0002082866", + "PNFP-PA": "0002082866", + "WSBCO": "0000203596", + "BNZIW": "0001826011", + "DHTI": "0000725394", + "TPZEF": "0002073655", + "ASTLW": "0001860805", + "GLIBK": "0002057463", + "FINGF": "0002073638", + "SWBGF": "0002098324", + "GLVHF": "0002089499", + "SBFMW": "0001402328", + "AMODW": "0001862463", + "BIREF": "0002073268", + "CVCCF": "0002120046", + "MOBQW": "0001084267", + "SYAXF": "0001739016", + "GSMT": "0001940243", + "ALMP": "0001956237", + "MIBE": "0001872066", + "COCHW": "0001840877", + "MSAIW": "0001863990", + "CGABL": "0001527166", + "AXIA-PC": "0001439124", + "AXIA-P": "0001439124", + "WLDSW": "0001887673", + "FILG": "0001852039", + "UEPCO": "0000100826", + "ATHNF": "0002019367", + "WEXPF": "0000842622", + "ATLCL": "0001464343", + "ATLCZ": "0001464343", + "ZJNGF": "0002093654", + "DJTWW": "0001849635", + "RKWBF": "0001969729", + "RKWAF": "0001969729", + "RCWBY": "0001969729", + "GNL-PB": "0001526113", + "GNL-PE": "0001526113", + "GNL-PD": "0001526113", + "CNOBP": "0000712771", + "REECF": "0002070570", + "SRBEF": "0002075141", + "INPAP": "0000051434", + "CTATF": "0002070829", + "AGMWF": "0002022059", + "CGCTU": "0002049662", + "CGCTW": "0002049662", + "SKPJF": "0001447108", + "RAINW": "0002028293", + "LOB-PA": "0001462120", + "PCPPF": "0002053411", + "SPGDF": "0002042556", + "OBCKF": "0002094691", + "CSCCF": "0002075918", + "WAFDP": "0000936528", + "LKYRF": "0002091585", + "CMCLF": "0001447960", + "TNEYF": "0002073901", + "GMTH": "0002000762", + "VCICU": "0002025396", + "VCICW": "0002025396", + "KCLHF": "0001795589", + "RYLBF": "0001000275", + "TFC-PI": "0000092230", + "TFC-PO": "0000092230", + "TFC-PR": "0000092230", + "MTLPF": "0002090231", + "RNKGF": "0002093907", + "BIII-WT": "0002087087", + "BIII-UN": "0002087087", + "FMACU": "0002099232", + "BACCR": "0002059654", + "BACCU": "0002059654", + "OIMAW": "0002088325", + "OIMAU": "0002088325", + "EVLVW": "0001805385", + "OPTEY": "0001815620", + "CDAWF": "0001851909", + "CDAUF": "0001851909", + "AIIA-RI": "0002073553", + "AIIA-UN": "0002073553", + "CAQUU": "0002100125", + "CAQUW": "0002100125", + "NMPAU": "0002054876", + "NMPAR": "0002054876", + "LATAU": "0002076427", + "LATAW": "0002076427", + "NTWOW": "0002028027", + "NTWOU": "0002028027", + "WRB-PF": "0000011544", + "WRB-PG": "0000011544", + "WRB-PH": "0000011544", + "SWVLW": "0001875609", + "CNCKW": "0001913847", + "NOVTU": "0001076930", + "GBNXF": "0002071913", + "AVVOF": "0002082141", + "LANDO": "0001495240", + "TRMLF": "0002071881", + "PFSEF": "0002120422", + "HRIBF": "0002088827", + "LFACW": "0002084563", + "LFACU": "0002084563", + "BLRKW": "0002081532", + "BLRKU": "0002081532", + "ADDTF": "0001766868", + "SVUWF": "0001973368", + "GRABW": "0001855612", + "F-PB": "0000037996", + "F-PC": "0000037996", + "F-PD": "0000037996", + "QXO-PB": "0001236275", + "EMRJF": "0001127248", + "EMICF": "0001127248", + "ORIQW": "0002044523", + "ORIQU": "0002044523", + "EICA": "0001754836", + "EICC": "0001754836", + "ELCPF": "0001039610", + "VDTA": "0002033264", + "OSDVF": "0001431852", + "ODVWZ": "0001431852", + "RDGAD": "0000812152", + "TDWDR": "0002076616", + "TDWDU": "0002076616", + "NNAVW": "0001865631", + "NXNVW": "0001865631", + "PPLOF": "0001546066", + "PBPRF": "0001546066", + "PBNAF": "0001546066", + "PMBPF": "0001546066", + "PMMBF": "0001546066", + "PPLAF": "0001546066", + "ADACU": "0002083002", + "ADACW": "0002083002", + "VLYPN": "0000714310", + "FMSTW": "0001935418", + "WHR-PA": "0000106640", + "PREKF": "0002071912", + "PARXF": "0002073620", + "TNDEF": "0002075349", + "OBIIF": "0002077146", + "TMTNF": "0002072098", + "WIPKF": "0002074059", + "GDERF": "0002021390", + "VHAIW": "0001880431", + "VHABW": "0001880431", + "GWH-WT": "0001819438", + "XRN-PA": "0001533615", + "XRN-PB": "0001533615", + "NSARO": "0000013372", + "NSARP": "0000013372", + "NOFCF": "0002108180", + "SCXBF": "0002066600", + "SWAGW": "0001872525", + "MACIW": "0002016221", + "MACIU": "0002016221", + "EXOSF": "0002109666", + "SCAFF": "0001713675", + "SRJN": "0001126956", + "AIKCF": "0002087856", + "BLHWF": "0002109234", + "MANDF": "0002038958", + "SPIWF": "0002083221", + "NTCS": "0001933359", + "ACAAU": "0002096900", + "PMFAX": "0001723701", + "NPIFF": "0002072389", + "NPICF": "0002072389", + "ZJLMF": "0002087840", + "SVAQU": "0002085659", + "SVAQW": "0002085659", + "GSHRU": "0002044635", + "GSHRW": "0002044635", + "ALVOW": "0001898416", + "SGBAF": "0001347408", + "BAERW": "0001941536", + "CYCUW": "0001868419", + "GROO": "0001499275", + "HPE-PC": "0001645590", + "LIANY": "0001831283", + "CTRVP": "0001583771", + "FGIWW": "0001864943", + "SZZLU": "0002030663", + "SZZLR": "0002030663", + "GFSAY": "0001389207", + "BFRGW": "0001829247", + "SVREW": "0001894693", + "LDDFD": "0001919776", + "CUBB": "0001488813", + "BANFP": "0000760498", + "RZC": "0000898174", + "OYCG": "0001994582", + "HOVRW": "0001930021", + "MYPSW": "0001823878" +} \ No newline at end of file diff --git a/config/runtime/collect_data_state.json b/config/runtime/collect_data_state.json new file mode 100644 index 0000000..ed762fb --- /dev/null +++ b/config/runtime/collect_data_state.json @@ -0,0 +1,10 @@ +{ + "last_run_keys": { + "gpr_monthly": "2026-04", + "macro_trading_daily": "2026-04-21", + "news_daily": "2026-04-21", + "options_daily": "2026-04-21", + "sec_ingestion_weekly": "2026-W16", + "sec_processor_weekly": "2026-W16" + } +} \ No newline at end of file diff --git a/config/runtime/sec_processed_registry.json b/config/runtime/sec_processed_registry.json new file mode 100644 index 0000000..f32dbcc --- /dev/null +++ b/config/runtime/sec_processed_registry.json @@ -0,0 +1 @@ +["0001104659-26-041034", "0000796343-26-000083", "0000773840-26-000041", "0001225208-26-004200", "0000950103-26-005904", "0000006281-26-000039", "0000050863-26-000072", "0001311079-26-000002", "0001652044-26-000031", "0001193125-26-144028", "0000002488-26-000066", "0001193125-26-151343", "0001804954-26-000002", "0000829224-26-000064", "0000796343-26-000076", "0001730168-26-000034", "0001140361-26-013192", "0002006416-26-000003", "0001331845-26-000003", "0001730168-26-000032", "0001782135-26-000014", "0002058769-26-000003", "0000773840-26-000040", "0001201872-26-000008", "0001628280-26-023379", "0000950103-26-005766", "0000773840-26-000038", "0001184223-26-000002", "0001104659-26-040661", "0000796343-26-000089", "0002067677-26-000007", "0000773840-26-000034", "0001193125-26-140574", "0000796343-26-000081", "0001628280-26-023648", "0001193125-26-142372", "0000804328-26-000051", "0000950157-26-000465", "0001193125-26-151637", "0001628280-26-023704", "0000858877-26-000054", "0000773840-26-000033", "0000773840-26-000036", "0001140361-26-015421", "0000773840-26-000032", "0001104659-26-042880", "0001201490-26-000002", "0001535527-26-000013", "0001862209-26-000002", "0000858877-26-000052", "0001628280-26-023701", "0000789019-26-000070", "0000909832-26-000041", "0000773840-26-000042", "0001628280-26-023690", "0001516908-26-000016", "0000002488-26-000064", "0001225110-26-000006", "0001730168-26-000024", "0000804328-26-000049", "0000006281-26-000040", "0000796343-26-000078", "0001972928-26-000002", "0001018724-26-000010", "0000909832-26-000039", "0001628280-26-022956", "0000796343-26-000095", "0000804328-26-000048", "0000796343-26-000080", "0000773840-26-000037", "0001543133-26-000002", "0000813672-26-000040", "0001201490-26-000003", "0001310204-26-000014", "0001202443-26-000005", "0000006281-26-000041", "0001193125-26-151329", "0000796343-26-000091", "0001104659-26-038249", "0001104659-26-038682", "0001225208-26-004342", "0000829224-26-000066", "0000796343-26-000092", "0001730168-26-000030", "0001628280-26-023706", "0000006281-26-000037", "0001621597-26-000002", "0001882285-26-000007", "0001075531-26-000014", "0001140361-26-013190", "0000796343-26-000082", "0000773840-26-000035", "0001032834-26-000002", "0002044259-26-000007", "0001652044-26-000034", "0001201872-26-000006", "0000796343-26-000097", "0000796343-26-000077", "0000796343-26-000090", "0001936006-26-000012", "0000804328-26-000053", "0001225208-26-004518", "0001905272-26-000002", "0001193125-26-151366", "0000796343-26-000088", "0000796343-26-000079", "0001227733-26-000003", "0000050863-26-000069", "0001628280-26-025108", "0001065280-26-000134", "0001193125-26-151397", "0001852540-26-000002", "0001225208-26-004201", "0001628280-26-023646", "0001685760-26-000004", "0001140361-26-015420", "0001225208-26-004202", "0000773840-26-000039", "0001225208-26-004132", "0000950103-26-005654", "0000006281-26-000038", "0000858877-26-000048", "0000006281-26-000043", "0001772458-26-000002", "0001065280-26-000137", "0001730168-26-000026", "0001628280-26-023696", "0001193125-26-162189", "0001628280-26-023698", "0001665364-26-000005", "0000796343-26-000094", "0000006281-26-000042", "0001730168-26-000028", "0001140361-26-013191", "0000077476-26-000019", "0000875320-26-000157", "0001652149-26-000003", "0001104659-26-039613", "0001225208-26-004199", "0000097476-26-000094", "0001999371-26-007656", "0001225208-26-004203", "0001632063-26-000002", "0000796343-26-000093", "0000796343-26-000087", "0001075531-26-000012", "0001768266-26-000004"] \ No newline at end of file diff --git a/config/universe/_manifest.json b/config/universe/_manifest.json new file mode 100644 index 0000000..a5f1073 --- /dev/null +++ b/config/universe/_manifest.json @@ -0,0 +1,49 @@ +{ + "schema_version": "1.0", + "description": "Asset universe registry. Each entry maps a semantic role to a ticker-list file and declares downstream capabilities.", + "last_reviewed": "2026-04-22", + "roles": { + "equity.single_name": { + "file": "equity_single_name.json", + "description": "Single-name equities filed with SEC (subset of Nasdaq-100). Source of truth for SEC ingestion filers and equity options scraping.", + "asset_class": "equity", + "has_options": true, + "has_sec_filings": true, + "coverage_start": "2026-04-08", + "owner": "data-platform", + "notes": "Expansion beyond 48 tickers requires updating config/reference/ticker_to_cik.json via Scripts/tools/SEC_generate_cik_map.py." + }, + "etf.broad_market": { + "file": "etf_broad_market.json", + "description": "Broad-market equity index ETFs. Primary sentiment / beta benchmarks.", + "asset_class": "etf", + "has_options": true, + "has_sec_filings": false, + "coverage_start": "2025-10-01", + "owner": "data-platform" + }, + "etf.commodity": { + "file": "etf_commodity.json", + "description": "Commodity-backed ETFs used as safe-haven / inflation proxies.", + "asset_class": "etf", + "has_options": true, + "has_sec_filings": false, + "coverage_start": "2025-10-01", + "owner": "data-platform" + } + }, + "composite_roles": { + "etf.all": { + "union_of": ["etf.broad_market", "etf.commodity"], + "description": "All ETFs we track (broad market + commodity)." + }, + "options.scrape": { + "union_of": ["equity.single_name", "etf.broad_market", "etf.commodity"], + "description": "Full universe for yfinance options-chain scraping (single-names + ETFs)." + }, + "sec.filers": { + "union_of": ["equity.single_name"], + "description": "Tickers to be fed to the SEC EDGAR ingester (10-K/10-Q/8-K/Form-4). Alias for equity.single_name." + } + } +} diff --git a/config/universe/equity_single_name.json b/config/universe/equity_single_name.json new file mode 100644 index 0000000..5feea41 --- /dev/null +++ b/config/universe/equity_single_name.json @@ -0,0 +1 @@ +["AAPL", "MSFT", "NVDA", "AMZN", "META", "GOOGL", "TSLA", "AVGO", "COST", "PEP", "NFLX", "AMD", "CSCO", "TMUS", "ADBE", "QCOM", "TXN", "INTU", "AMGN", "ISRG", "HON", "CMCSA", "INTC", "AMAT", "IBM", "BKNG", "VRTX", "SBUX", "PANW", "MDLZ", "GILD", "REGN", "LRCX", "ADP", "ADI", "MU", "SNPS", "CDNS", "MELI", "CSX", "KLAC", "PYPL", "CRWD", "MAR", "ASML", "CTAS", "MNST", "NXPI"] diff --git a/config/universe/etf_broad_market.json b/config/universe/etf_broad_market.json new file mode 100644 index 0000000..c46d4cd --- /dev/null +++ b/config/universe/etf_broad_market.json @@ -0,0 +1 @@ +["SPY", "QQQ", "IWM"] diff --git a/config/universe/etf_commodity.json b/config/universe/etf_commodity.json new file mode 100644 index 0000000..3431f54 --- /dev/null +++ b/config/universe/etf_commodity.json @@ -0,0 +1 @@ +["GLD", "SLV"] diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml deleted file mode 100644 index fb2be6a..0000000 --- a/docker-compose.prod.yml +++ /dev/null @@ -1,79 +0,0 @@ -version: '3.8' - -services: - app: - build: . - container_name: financial_agent_app_prod - stdin_open: true - tty: true - environment: - - QDRANT_HOST=qdrant_vdb - - OLLAMA_HOST=http://ollama_llm:11434 - - OLLAMA_MODEL=options-expert - - YOUTUBE_API_KEY=AIzaSyD1hA6jbyKxj6x3m96FM87Dci_MBttsHBY - - YOUTUBE_CHANNEL_IDS=UCxiCqC3t-v4sM-i7-B7L_yg,UCK7tptUDHh-RYDsdxO1-5QQ,UCGy7SkBjcIAgTiwkXEtPnYg,UCUvvj5lwue7PspotMDjk5UA,UCn3rGS5AtyYJ1uNl4gS8qDg,UCb-yR6Q_E-qL8zF2NnE0UBA,UCT3EznhW_CNFcfOlyDNTLLw,UCtqYfJvM_5iH5n_e9R4F9_g,UCXq_QyB5g8F5_sBw-5B8-2Q,UCQ7_GMxQe4_S66w-oX9JvAg,UC0n9yiP-AD2DpuuYCDwlNxQ,UCZRlaA_QK7tE6P6B6L7P-8w,UCYXwqqzEyUOGWmFQc4JjQ_w,UCg3Z29Husv_W8oT61j82GqA,UC2X8F50H6R-4yI726J_z68Q,UC26jQ450yWz838N0H7T5Dkg,UCxX8R7nI93o2I93sYJg3JGA,UCU6X4B36jQxL1m9kKxK3x6A,UCX_R0gXv_W-hEw7fG7dJ0qQ,UCx6d_wY9eGzX7tFw8dY1l7g - - YOUTUBE_VIDEOS_PER_CHANNEL=3 - - FRED_API_KEY=${FRED_API_KEY} - - NEWS_API_KEY=${NEWS_API_KEY} - - REDDIT_CLIENT_ID=${REDDIT_CLIENT_ID} - - REDDIT_CLIENT_SECRET=${REDDIT_CLIENT_SECRET} - - REDDIT_USER_AGENT=${REDDIT_USER_AGENT} - - SEC_API_KEY=${SEC_API_KEY} - volumes: - - ./src:/app/src - - ./reports:/app/reports - - ./logs:/app/logs - depends_on: - - qdrant_vdb - - ollama_llm - networks: - - financial_net - restart: unless-stopped - healthcheck: - test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] - interval: 30s - timeout: 10s - retries: 3 - - qdrant_vdb: - image: qdrant/qdrant:v1.9.2 - container_name: qdrant_vdb_prod - ports: - - "6333:6333" - volumes: - - qdrant_data:/qdrant/storage - networks: - - financial_net - restart: unless-stopped - healthcheck: - test: ["CMD-SHELL", "nc -z localhost 6333 || exit 1"] - interval: 30s - timeout: 10s - retries: 3 - - ollama_llm: - image: ollama/ollama:latest - container_name: ollama_llm_prod - ports: - - "11434:11434" - volumes: - - ollama_data:/root/.ollama - networks: - - financial_net - restart: unless-stopped - stdin_open: true - tty: true - healthcheck: - test: ["CMD-SHELL", "nc -z localhost 11434 || exit 1"] - interval: 30s - timeout: 10s - retries: 3 - - -volumes: - qdrant_data: - ollama_data: - -networks: - financial_net: - driver: bridge diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 4866b25..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,50 +0,0 @@ -services: - app: - build: . - container_name: financial_agent_app - environment: - - QDRANT_HOST=qdrant_vdb - - OLLAMA_HOST=http://ollama_llm:11434 - - OLLAMA_MODEL=mistral:7b-instruct-q4_0 - - YOUTUBE_API_KEY=AIzaSyD1hA6jbyKxj6x3m96FM87Dci_MBttsHBY - - YOUTUBE_CHANNEL_IDS=UCBJycsmduvYEL83R_U4JriQ,UCq9RcdZ2YFxyC6q_Mz0S8xw,UCwLBOxZQ5e3m0h-9B5N6Qxg,UCtUId5WZ07w6bZg7m8z6m2g,UCnh4zO0A7bQKwQ6C2Jr3Hyw,UC5xDht2blPNWdVZ9M2Z9bBg,UCBJycsmduvYEL83R_U4JriQ,UCq9RcdZ2YFxyC6q_Mz0S8xw,UCwLBOxZQ5e3m0h-9B5N6Qxg,UCtUId5WZ07w6bZg7m8z6m2g - - YOUTUBE_VIDEOS_PER_CHANNEL=5 - volumes: - - ./src:/app/src - depends_on: - - qdrant_vdb - - ollama_llm - networks: - - financial_net - stdin_open: true - tty: true - - qdrant_vdb: - - image: qdrant/qdrant:v1.9.2 - - container_name: qdrant_vdb - ports: - - "6333:6333" - volumes: - - qdrant_data:/qdrant/storage - networks: - - financial_net - - ollama_llm: - image: ollama/ollama:latest - container_name: ollama_llm - ports: - - "11434:11434" - volumes: - - ollama_data:/root/.ollama - networks: - - financial_net - -volumes: - qdrant_data: - ollama_data: - -networks: - financial_net: - diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index d68d4e2..f460f90 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -1,132 +1,400 @@ -# options_bot Architecture Overview - -## Entry Point -- `src/main.py` - - CLI bootstrap and environment loading (`.env`). - - Constructs `AgentWorkflow` (connects to Qdrant and Ollama). - - Runs `run_data_pipeline(agent_workflow)` to collect multi-source data and store it. - - Interactive mode: user question → `agent_workflow.run()` → structured report output. - -## Orchestration Core -- `src/agent_system.py` - - Class `AgentWorkflow`: - - `_ensure_collection_exists()`: ensure Qdrant collection exists (dimension based on embedding size). - - `embed_and_store(documents)`: vectorize documents and upsert into Qdrant. - - `_retrieve_context(query, top_k)`: retrieve relevant context from Qdrant. - - `_run_agent(agent_name, prompt)`: call sub-agents via Ollama. - - `run(user_query)`: retrieve context + inject financial background (`financial_config`) + chain four agents (Analyst → Fact Checker → Adversarial Critic → Synthesizer) → produce `FinalReport` JSON. - - Dependencies: - - `data_models.FinalReport` - - `financial_config.get_financial_context`, `get_role_based_prompt` - - Qdrant / Ollama / fastembed - -## Data Models -- `src/data_models.py` - - `FinalReport` (Pydantic): defines the structured output (`summary`, `key_findings`, `counter_arguments`, `confidence_score`, `uncertainty_notes`). - -## Financial Domain Context -- `src/financial_config.py` - - Financial terminology, analysis frameworks, regulations, professional role prompts. - - `get_financial_context(query)`: assemble domain context by keywords. - - `get_role_based_prompt(role)`: return role prompts. - -## Data Collection Components (invoked by `main.run_data_pipeline`) -- `src/market_data_scraper.py` - - `scrape_market_data(tickers)`: market data → documents. -- `src/fred_scraper.py` - - `scrape_fred_data(series_ids)`: FRED macro data → documents. -- `src/news_scraper.py` - - `scrape_news_data(keywords, limit)`: news → documents. -- `src/reddit_scraper.py` - - `scrape_reddit_data(subreddits, keywords, limit_per_subreddit)`: Reddit posts → documents. -- `src/youtube_scraper.py` - - `load_channel_ids_from_file()`: read channel IDs (`src/tools/Youtube_channel_ID`). - - `get_channel_videos(channel_id, max_results)`: list videos via Data API (or RSS fallback) and include description. - - `get_transcript_with_fallback(video_id)` / `try_alternative_transcript_methods(video_id)`: `list_transcripts` + multilingual/translation + backoff. - - `process_transcript_data(...)`: cleaning, keyword and sentiment analysis, document assembly. - - `scrape_youtube_data(...)`: - - Prefilters by caption flag, skips live/upcoming - - Saves fallback doc (title + cleaned description + URL) when no transcript declared or fetch fails - - Aggregates all documents -- `src/sec_scraper.py` - - `get_sec_filings()`: SEC insider trading/filings → documents. - -## Utility Scripts -- `src/tools/fetch_youtube_channels.py` / `src/tools/update_compose_channels.py` - - Search/update candidate financial channels. -- `src/tools/generate_production_report.py` / `src/tools/create_options_expert.py` - - Production reports / options expert model creation (may call `yfinance_client`). - -- `src/yahoo_finance_scraper.py` - - Lists Yahoo Finance videos via RSS - - Fetches transcripts via `youtube_transcript_api` (same caption rules as YouTube) - - Saves fallback doc (title + cleaned description + URL) when no transcript or too short - -## External Clients & Runtime -- `src/yfinance_client.py`: yfinance and API helpers (mainly for tools). -- `docker-compose.prod.yml`: production stack (current). Services `qdrant_vdb`, `ollama_llm`; container names `*_prod`; `OLLAMA_MODEL=options-expert`. -- `modelfile`: Ollama model configuration. -- `requirements.txt`: Python dependencies. - -## High-Level Flow -1. Run: `python -m src.main` (or `python src/main.py`). -2. `main.py` → construct `AgentWorkflow`. -3. `run_data_pipeline(agent_workflow)` calls in order: - - `market_data_scraper.scrape_market_data` - - `fred_scraper.scrape_fred_data` - - `news_scraper.scrape_news_data` - - `reddit_scraper.scrape_reddit_data` - - `youtube_scraper.scrape_youtube_data` - - `yahoo_finance_scraper.scrape_yahoo_finance_transcripts` - - `sec_scraper.get_sec_filings` -4. `agent_workflow.embed_and_store(all_documents)` persists into Qdrant. -5. Interactive: `agent_workflow.run(user_query)` → retrieval + financial context + multi-agent reasoning → `FinalReport`. +# System Architecture — Automated Options Recommendation Bot + +_Last updated: 2026-04-22 — revision 2 (orchestration layer, lazy package +facades, unified observability, LLM pool)_ + +This document is the authoritative map of the bot. It describes **what +each package does**, **how the runtime fits together**, and **which +contracts the layers must honour**. Subordinate docs — linked in-line — +drill down into individual subsystems. + +- [docs/Orchestration.md](./Orchestration.md) — pipeline DAG, CLI, runtime state +- [docs/Observability.md](./Observability.md) — unified logs + audit paths +- [docs/LLM_Pool.md](./LLM_Pool.md) — Llama 70B warmup / keep-alive strategy +- [docs/Data_source_docs/](./Data_source_docs/) — Qdrant / Parquet schemas +- [docs/Query_retrieval_docs/](./Query_retrieval_docs/) — retrieval policy details +- [docs/test/2026-04-22/router_e2e_deep_analysis.md](./test/2026-04-22/router_e2e_deep_analysis.md) — audit report driving the current hardening + +--- + +## 1. System Topology + +```mermaid +flowchart LR + subgraph CLI ["python -m Scripts (orchestration/cli.py)"] + C1[ingest] --> C2[daemon] + C2 --> C3[status] + C3 --> C4[query] + C4 --> C5[warmup] + end + + subgraph ORCH ["orchestration/ (pipeline + run_state)"] + OR[RunState\nconfig/runtime/collect_data_state.json] + OS[Stage / ScriptStage / CallableStage] + OP[Pipeline DAG] + end + + subgraph DATA ["data_collection/ (scrapers + processors)"] + D1[yfinance_options_history] + D2[macro_data_pipeline] + D3[news_scraper] + D4[GPR_index] + D5[sec_ingestion] + D6[sec_processor] + end + + subgraph STORAGE ["Persistence"] + P1[(Parquet\nSilver)] + P2[(Qdrant\nGold)] + end + + subgraph RET ["retrieval/ (MasterRetriever)"] + R1[QueryTransformer] + R2[FinancialHybridRetriever] + R3[SilverSQLTool] + R4[time_adapter] + end + + subgraph AG ["agents/ (LangGraph nodes)"] + A1[Router] + A2[Analyst] + A3[Checker] + A4[Critic] + A5[Finalizer] + end + + subgraph CORE ["core/ (pure primitives)"] + K1[trading_calendar] + K2[financial_ontology] + K3[universe] + K4[llm_pool] + end + + OBS[observability/\nunified logs + run_id] + + CLI --> ORCH + ORCH --> DATA + DATA --> P1 + DATA --> P2 + CLI --> RET + RET --> P1 + RET --> P2 + RET --> AG + AG --> OBS + RET --> OBS + ORCH --> OBS + AG --> CORE + RET --> CORE + ORCH --> CORE + OR -. time anchor .-> R4 + OR -. time anchor .-> R3 +``` + +Five architectural invariants make the above diagram tractable at +runtime: + +1. **`core/` has zero external side-effects.** No network, no LLM + clients, no scrapers. Everything else may depend on `core/`. +2. **`Scripts/core/__init__.py` and `Scripts/retrieval/__init__.py`** + are PEP-562 lazy façades — importing the package does not drag + LangChain / Ollama / pydantic until a lazy attribute is touched. +3. **`RunState` is the single source of truth for time anchors.** + Scrapers advance `config/runtime/collect_data_state.json`; agents + read from it. No layer computes "yesterday" from wall-clock time. +4. **Logs route through `Scripts.observability.audit`.** Every module + writes to `logs/runs/{YYYY-MM-DD}/{run_id}/…` via `audit_path()`. +5. **LLM clients come from `Scripts.core.llm_pool`.** Agents request + `get_ollama("analyst")` / `get_ollama("checker")` rather than + instantiating `ChatOllama` directly. See [LLM_Pool.md](./LLM_Pool.md). + +--- + +## 2. Package Inventory + +### 2.1 `Scripts/core/` — Pure Primitives Layer + +| Module | Responsibility | +| --- | --- | +| `trading_calendar.py` | Business-day arithmetic (`is_business_day`, `previous_business_day`, `n_business_days_back`). Hard-coded US market holidays through 2027; zero external dependencies. | +| `financial_ontology.py` | Allow-lists, regex tables and metric→column maps consumed by `query_transform`, `sql_tools` and `router`. | +| `financial_config.py` | Static Modelfile system-prompt generation for the fine-tuned `options-expert` model. | +| `universe.py` | Loader for `config/universe/*.json` (equities / ETFs / pipelines). Cached JSON I/O only. | +| `prompt_templates.py`, `intent_router_prompt_templates.py` | Prompt strings shared between `query_transform` and the router intent few-shot. | +| `few_shot_config.py`, `few_shot_intent.py` | Curated few-shot examples for structured extraction and routing. | +| `llm_pool.py` | Process-wide model singleton cache + warmup. See [LLM_Pool.md](./LLM_Pool.md). | + +The package `__init__.py` implements PEP-562 lazy loading: importing +the sub-module triggers its actual load and memoises the result in +module globals. + +### 2.2 `Scripts/orchestration/` — Pipeline + CLI + +| Module | Responsibility | +| --- | --- | +| `run_state.py` | `RunState` handle, `Cadence` enum, `run_key` arithmetic, `DATASET_ANCHOR_KEYS` map. Atomic writes, tolerant reads. | +| `stages.py` | `Stage` base, `ScriptStage` (subprocess adapter, zero-migration for legacy scrapers), `CallableStage` (in-process for new stages). | +| `pipeline.py` | `Pipeline` topological runner; `build_default_pipeline()` factory assembling the 6 existing data jobs. | +| `cli.py` | argparse entry point: `ingest` / `daemon` / `status` / `query` / `warmup`. | + +See [Orchestration.md](./Orchestration.md) for the DAG, the idempotency +contract, and CLI usage. + +### 2.3 `Scripts/observability/` — Unified Logs + +| Module | Responsibility | +| --- | --- | +| `audit.py` | `start_run(tag)`, `current_run_id()`, `audit_path(module, anchor, filename=)`, `configure_root_logger()`, `get_audit_logger()`. | + +See [Observability.md](./Observability.md) for the directory layout and +the migration recipe for legacy loggers. + +### 2.4 `Scripts/retrieval/` — Gold + Silver Retrievers + +| Module | Responsibility | +| --- | --- | +| `schema.py` | Pydantic data types — `QueryIntent`, `MetadataExtraction`, `TimeWindow`, `SourceType`, `RetrievedChunk`, `SQLResult`. Dependency-free at import time. | +| `query_transform.py` | Two-stage LLM query transformer (structured extract + HyDE). | +| `qdrant_retriever.py` | `FinancialHybridRetriever` — Qdrant hybrid search (dense + sparse + metadata pre-filter). | +| `sql_tools.py` | `SilverSQLTool` — Parquet-backed Silver queries with Dynamic Time Anchor. | +| `time_adapter.py` | `TimePredicate` + `compile_predicate()` — converts logical `TimeWindow` + `TimeGranularity` into per-source epoch ranges. Business-day-aware for DAILY sources. | +| `master_retriever.py` | `MasterRetriever` — orchestrates query transform → parallel Gold / Silver retrieval → macro injection. | + +`Scripts/retrieval/__init__.py` eagerly re-exports the Pydantic data +types (used everywhere, no heavyweight deps) and lazily exposes the +LLM-backed classes. Agents that want to bypass the façade for +minimum-latency cold-starts import directly from the leaf module +(`from Scripts.retrieval.master_retriever import MasterRetriever`). + +### 2.5 `Scripts/agents/` — LangGraph Nodes + +| Module | Responsibility | +| --- | --- | +| `state.py` | `AgentState` TypedDict — the LangGraph shared state (including `iv_regime_pinned`, `time_range.source_predicates`). | +| `router.py` | Graph construction + master_retrieval_node + control-flow. | +| `analyst.py` | Generates `draft_report`; pins `iv_regime` on first pass for determinism across revisions. | +| `checker.py` | Deterministic regex audit + LLM veracity check; sentinel whitelist; rescue re-queries with rehydrated `TimePredicate`. | +| `critic.py` | Adversarial critique (bull/bear). | +| `finalizer.py` | Renders the final report; enforces deterministic `report_date` and reconciles `SourceCitation.source_type` against the deterministic `evidence_pool`. | +| `prompts.py` | All prompt templates for the graph. | + +Package `__init__.py` is intentionally import-empty — each agent pulls +heavy LangChain types, so consumers reach agents by leaf module path. + +### 2.6 `Scripts/data_collection/` — Scrapers + Processors + +| Path | Cadence | RunState key | +| --- | --- | --- | +| `scrapers/yfinance_options_history.py` | DAILY | `options_daily` | +| `scrapers/macro_data_pipeline.py` | TRADING_DAILY | `macro_trading_daily` | +| `scrapers/news_scraper.py` | DAILY | `news_daily` | +| `scrapers/GPR_index.py` | MONTHLY | `gpr_monthly` | +| `scrapers/sec_ingestion.py` | WEEKLY | `sec_ingestion_weekly` | +| `processors/sec_processor.py` | WEEKLY (dep on ingestion) | `sec_processor_weekly` | +| `collect_data.py` | Legacy daemon — now a thin wrapper over `RunState` for back-compat. | + +### 2.7 `Scripts/vector_store/` — Qdrant Client + Ingestion + +`connection.py` exposes `get_qdrant_client()` and `get_embedding_model()`. +`ingestion.py` defines `QdrantIngestor` which upserts the three Gold +collections (`sec_filings`, `news_documents`, `gpr_index`) from their +respective Silver Parquet / JSONL sources. --- -## LLM Fine-Tuning and the Options Expert Model - -This project creates a specialized options/futures-options expert model `options-expert` by generating a Modelfile and using Ollama's create API. - -### Files & Services -- `src/tools/create_options_expert.py` - - Generates the Modelfile, fetches training data from Qdrant, calls Ollama to create the model, then smoke-tests it. - - Depends on: - - Qdrant (collection `financial_signals`) - - Ollama (port 11434) -- `modelfile` - - Generated by `create_modelfile()` within `create_options_expert.py`. - - Encodes system prompt (options expertise) and inference parameters (temperature, top_p, num_ctx, etc.). -- `docker-compose.prod.yml` - - Sets `OLLAMA_MODEL=options-expert` in the app service for runtime usage. - -### Training Data Source -- During the data pipeline, `AgentWorkflow.embed_and_store()` writes multi-source documents into Qdrant `financial_signals`. -- `fetch_training_data()` in `create_options_expert.py` reads payloads from that collection to form training material. - -### Model Creation Flow (via script) -1. Read training data from Qdrant. -2. Generate `modelfile` at repo root. -3. Call Ollama create API (`/api/create`) with name `options-expert`. -4. Verify with `/api/generate`. - -### Common Commands (prod stack) -- Create model inside the app container (script uses Ollama API): -```bash -docker exec -it financial_agent_app_prod python src/tools/create_options_expert.py +## 3. Runtime Workflows + +### 3.1 Data Ingestion (one-shot or daemon) + +```text +$ python -m Scripts ingest [--only STAGE ...] [--force] [--dry-run] ``` -- Manual Modelfile-based creation inside Ollama container (alternative): -```bash -# Generate Modelfile if not already present -docker exec financial_agent_app_prod python src/tools/create_options_expert.py -# Copy Modelfile to host, then into Ollama container -docker cp financial_agent_app_prod:/app/modelfile ./modelfile -docker cp ./modelfile ollama_llm_prod:/modelfile -# Create and test in Ollama container -docker exec -it ollama_llm_prod ollama create options-expert -f /modelfile -docker exec -it ollama_llm_prod ollama run options-expert +```mermaid +sequenceDiagram + participant CLI as cli.py::_cmd_ingest + participant PIPE as Pipeline + participant STAGE as ScriptStage + participant RS as RunState (collect_data_state.json) + + CLI->>PIPE: run_once(only=None, force=False) + PIPE->>PIPE: topo_sort stages (gpr → macro/news/opts → sec_ing → sec_proc) + loop each stage + PIPE->>RS: is_up_to_date(job, cadence, now) ? + alt up-to-date + RS-->>PIPE: True + PIPE->>CLI: StageResult(status="skipped") + else needs run + PIPE->>STAGE: subprocess.run(python scrapers/*.py) + STAGE-->>PIPE: rc == 0 + PIPE->>RS: mark_job_complete(job, cadence, now) [atomic write] + PIPE->>CLI: StageResult(status="ok") + end + end +``` + +All state transitions are atomic — a Ctrl+C mid-write cannot corrupt +the file that agents depend on for time anchoring (Section 4). + +### 3.2 Inference Query (RAG) + +```text +$ python -m Scripts query --warmup "yesterday's AAPL IV skew?" ``` -### Notes -- You are currently running the prod stack (container names `*_prod`). To switch to a dev stack, bring down prod with `docker compose -f docker-compose.prod.yml down`, start the dev compose, and align hostnames/model names in scripts and env vars. +```mermaid +sequenceDiagram + participant CLI as cli.py::_cmd_query + participant POOL as llm_pool + participant G as router.build_graph() + participant MR as MasterRetriever + participant RS as RunState + participant TA as time_adapter + participant AGENTS as Analyst/Checker/Critic/Finalizer + + CLI->>POOL: warmup_sync(roles=["query_extract","analyst"]) + POOL-->>CLI: models pinned in GPU + CLI->>G: build_graph().invoke({"original_query": Q}) + G->>MR: retrieve(Q) + MR->>RS: latest_anchor_date("options") → date(2026,4,21) + MR->>TA: compile_predicate(SourceType.OPTIONS, TimeWindow.YESTERDAY, anchor) + TA-->>MR: TimePredicate(start=..., end=...) [business-day aware] + MR->>MR: Gold + Silver retrieval (async parallel) + MR-->>G: final_context{retrieved_chunks, silver_context, time_range.source_predicates} + G->>AGENTS: analyst → checker → critic → finalizer + AGENTS->>RS: read iv_regime_pinned, anchor_date (determinism) + AGENTS-->>CLI: FinalReport +``` + +Three determinism guarantees built into this flow: + +- `time_range.source_predicates` is **serialised into `AgentState`** so + that the Checker's rescue re-queries hit the same Parquet slice the + original retrieval used. No more `start_date` drift between revisions. +- `iv_regime` is **pinned** after the Analyst's first computation and + reused across revisions — strategy recommendations stop oscillating. +- `report_date` is **forced** to `state["time_range"]["anchor_date"]` + in the Finalizer — the LLM never gets to invent a date. + +--- + +## 4. Contracts + +### 4.1 Time-Anchor Contract (single source of truth) + +`config/runtime/collect_data_state.json`: + +```json +{ + "last_run_keys": { + "options_daily": "2026-04-21", + "macro_trading_daily": "2026-04-21", + "news_daily": "2026-04-21", + "gpr_monthly": "2026-04", + "sec_ingestion_weekly": "2026-W16", + "sec_processor_weekly": "2026-W16" + }, + "updated_at": "2026-04-22T15:09:02" +} +``` + +- **Writers**: orchestration `Pipeline` (atomic). No other module writes. +- **Readers**: + - `RunState.latest_anchor_date(dataset)` — agent layer. + - `RunState.is_up_to_date(job, cadence)` — pipeline layer. +- **Invariant**: `latest_anchor_date` **never** returns a date in the + future of ``date.today()`` unless a deliberate backfill wrote one. + It **may** return a weekend date (e.g. Saturday manual backfill), + which `time_adapter` then snaps to the previous trading day for + DAILY sources. + +### 4.2 Logs Contract + +- **Run-scoped** (default for new code): `logs/runs/{YYYY-MM-DD}/{run_id}/{module}/{module}.log|jsonl` +- **Flat** (back-compat for offline tools): `logs/{module}/{YYYY-MM-DD}/` +- Use `Scripts.observability.audit_path(module, anchor, filename=)` + — never hand-build log paths. + +### 4.3 LLM Contract + +- Agents call `Scripts.core.llm_pool.get_ollama("analyst")`, + `get_ollama("checker")`, etc. — never `ChatOllama(...)` directly. +- Role configuration lives in `llm_pool.ROLE_TABLE`; env overrides + (`OLLAMA_CUSTOM_MODEL_NAME`, `OLLAMA_ROUTER_MODEL`, `OLLAMA_KEEP_ALIVE`) + reshape production without code changes. +- Warmup is opt-in at the CLI edge (`--warmup`) or as a standalone + subcommand (`python -m Scripts warmup --roles analyst router`). +- Retrieval-side models (dense / sparse / reranker) are **not** served + by the pool — they are HuggingFace / `fastembed` artefacts managed by + `Scripts/vector_store/connection.py`. See §5.2 and + `docs/Query_retrieval_docs/Retrieval_Architecture_and_Strategy.md`. + +--- + +## 5. Model Registry + +The system runs exactly five externally-hosted models. The table below +is the **single source of truth** — `llm_pool.py`, the retriever, and +the ingestion pipeline all resolve to these artefacts. + +### 5.1 Ollama-served LLMs (runtime) + +| Ollama tag | Origin | Env var | Consumers | +| --- | --- | --- | --- | +| `options-expert-v1:latest` | fine-tune `FROM Llama-3.3-70B-Instruct-Q4_K_M.gguf` (see `modelfile`) | `OLLAMA_CUSTOM_MODEL_NAME` | Analyst, Checker, Critic, Finalizer, `QueryTransformer` (extractor + HyDE) | +| `llama3:latest` | vanilla Meta Llama-3 8B | `OLLAMA_ROUTER_MODEL` | `MasterRetriever.router_llm` (intent), `news_scraper` sentiment, `sec_processor` form parser | + +> `OLLAMA_BASE_MODEL` (`llama3.3:70b`) is used only by +> `Scripts/models/create_options_expert.py` to rebuild the fine-tune. +> It is **not** an agent-facing runtime model. + +### 5.2 Retrieval models (HuggingFace / fastembed) + +| Purpose | Artefact | Env var | Home | +| --- | --- | --- | --- | +| Dense embedding | `BAAI/bge-base-en-v1.5` | `EMBEDDING_MODEL_NAME` | `Scripts/vector_store/connection.py::get_embedding_model` | +| Sparse (SPLADE) | `prithivida/Splade_PP_en_v1` | `SPARSE_MODEL_NAME` | `Scripts/retrieval/qdrant_retriever.py` | +| Cross-encoder reranker | `BAAI/bge-reranker-v2-m3` | `RERANKER_MODEL_NAME` | `Scripts/retrieval/qdrant_retriever.py` | + +--- + +## 6. Environment Variables + +| Variable | Default | Consumer | +| --- | --- | --- | +| `OLLAMA_BASE_URL` / `OLLAMA_HOST` | `http://localhost:11434` | `llm_pool` | +| `OLLAMA_KEEP_ALIVE` | `30m` | `llm_pool` — pins 70B in GPU | +| `OLLAMA_CUSTOM_MODEL_NAME` | `options-expert-v1:latest` | Expert tier (agents + `QueryTransformer`) | +| `OLLAMA_ROUTER_MODEL` | `llama3:latest` | Router tier (`MasterRetriever`) | +| `OLLAMA_INGESTION_MODEL` | falls back to `OLLAMA_ROUTER_MODEL` | Ingestion-time sentiment / SEC parser | +| `EMBEDDING_MODEL_NAME` | `BAAI/bge-base-en-v1.5` | Dense retrieval | +| `SPARSE_MODEL_NAME` | `prithivida/Splade_PP_en_v1` | Sparse retrieval | +| `RERANKER_MODEL_NAME` | `BAAI/bge-reranker-v2-m3` | Cross-encoder rerank | +| `QDRANT_HOST` / `QDRANT_URL` | `http://localhost:6333` | `vector_store` | +| `QDRANT_API_KEY` | unset | `vector_store` (cloud) | + +--- + +## 7. Operational Runbook (excerpt) + +| Task | Command | +| --- | --- | +| Check ingest freshness | `python -m Scripts status` | +| Run due ingests | `python -m Scripts ingest` | +| Force SEC re-processing | `python -m Scripts ingest --only sec_processor_weekly --force` | +| Start daemon with LLM warm | `python -m Scripts daemon --warmup` | +| Warm LLM only | `python -m Scripts warmup --roles analyst router` | +| Ask a question | `python -m Scripts query --warmup "..."` | +| Tail today's orchestrator log | `Get-Content -Wait logs/runs/$(Get-Date -Format yyyy-MM-dd)/*/orchestrator.log` | + +--- + +## 8. Change Log of Architectural Invariants + +| Date | Change | Rationale | +| --- | --- | --- | +| 2026-04-22 | Introduced `Scripts/orchestration/` | Collapse ad-hoc ingest scripts + agent CLIs behind one entry point. | +| 2026-04-22 | `config/runtime/collect_data_state.json` elevated to "single time-anchor source" | Eliminates wall-clock drift between scrapers and agents. | +| 2026-04-22 | `Scripts/core/__init__.py` and `Scripts/retrieval/__init__.py` turned lazy | Imports no longer pull LangChain/Ollama into the CLI's fast paths. | +| 2026-04-22 | `Scripts.core.llm_pool` | Enables Llama 70B warmup + singleton caching. | +| 2026-04-22 | `Scripts.observability.audit` | Unifies logs under `logs/runs/{date}/{run_id}/`. | +| 2026-04-22 | `TimePredicate` serialised into `AgentState` | Checker's rescue re-queries use the same time window as initial retrieval — fixes `latest_atm_iv` oscillation. | diff --git a/docs/Data_source_docs/Data_source_summary.md b/docs/Data_source_docs/Data_source_summary.md new file mode 100644 index 0000000..cb4efbf --- /dev/null +++ b/docs/Data_source_docs/Data_source_summary.md @@ -0,0 +1,261 @@ +# Data Source Architecture and Registry — Institutional Reference + +This document is the unified source-of-truth for the project data platform. It consolidates the former storage-layout guide and the source registry into one operational reference covering source origin, cadence, medallion placement, storage contracts, downstream consumers, and retrieval implications. + +--- + +## I. Executive Design Mandate + +The data platform is designed around a strict principle: + +- **Bronze** preserves traceability. +- **Silver** preserves deterministic numeric truth. +- **Gold** preserves retrieval-ready semantic compression. +- **Agent Context** provides stable prompt-time convenience, but never overrides structured truth. + +This separation is critical to the architecture because the system serves two fundamentally different workloads: + +- **Quantitative path:** exact numeric analytics over Parquet. +- **Qualitative path:** hybrid semantic retrieval over Qdrant. + +--- + +## II. Enterprise Data Architecture + +```text +External Sources +├─ Yahoo Finance (options, indices, ETFs) +├─ FRED (macro series) +├─ GDELT / web article capture +├─ SEC EDGAR +└─ GPR academic series + │ + ▼ +Data/1_Bronze_Raw +├─ Raw scrape output, parsed filing artifacts, replay/debug evidence +└─ Objective: lineage, traceability, recoverability + │ + ▼ +Data/2_Silver_Processed +├─ Structured Parquet for options, macro history, GPR history +└─ Objective: deterministic analytics and numeric source-of-truth + │ + ▼ +Data/3_Gold_Semantic +├─ Qdrant-ready JSONL +├─ semantic narratives / summaries +└─ Objective: retrieval-ready artifacts for agent reasoning + │ + ▼ +Data/Agent_Context +└─ stable latest snapshot for prompt injection only +``` + +--- + +## III. Data Production Workflow + +```mermaid +flowchart TD + A[External APIs and files] --> B[Bronze ingestion] + B --> C[Silver normalization and enrichment] + C --> D{Downstream use} + D -->|Deterministic analytics| E[Silver SQL / Pandas / Checker truth-set] + D -->|Semantic retrieval| F[Gold semantic artifacts] + F --> G[Qdrant ingestion] + C --> H[Agent_Context latest snapshot] + H --> I[LLM-readable context injection] +``` + +--- + +## IV. Medallion Storage Topology + +### 1. Canonical storage tree + +```text +Data/ +├── 1_Bronze_Raw/ +│ ├── SEC_Parsed_JSON/ +│ │ └── {YYYY-MM-DD}/ +│ │ ├── {TICKER}.jsonl +│ │ └── _SUMMARY.json +│ ├── News_Scrapes/ +│ │ └── {YYYY-MM-DD}/ +│ │ ├── Raw/raw_gdelt_{topic}.jsonl +│ │ └── Full_text/full_text_{topic}.jsonl +│ └── GPR_index/ +│ └── {YYYY-MM-DD}/gpr_preview.csv +│ +├── 2_Silver_Processed/ +│ ├── Options_Market_Data/ +│ │ └── {YYYY-MM-DD}/{SYMBOL}_options_{YYYY-MM-DD}.parquet +│ ├── Macro_History/ +│ │ └── {YYYY-MM-DD}/macro_snapshot_{YYYY-MM-DD}.parquet +│ └── GPR_index/ +│ └── gpr_monthly_enriched.parquet +│ +├── 3_Gold_Semantic/ +│ ├── SEC_Insider_Trades/ +│ │ └── {YYYY-MM-DD}/qdrant_ready.jsonl +│ ├── News_Qdrant/ +│ │ └── {YYYY-MM-DD}/qdrant_{topic}_processed.jsonl +│ ├── Macro_Narratives/ +│ │ └── {YYYY-MM-DD}/macro_context_{YYYY-MM-DD}.md +│ └── GPR_index/ +│ ├── {YYYY-MM-DD}/gpr_narrative_corpus.md +│ └── {YYYY-MM-DD}/qdrant_gpr_input.jsonl +│ +└── Agent_Context/ + └── latest_macro_context.md +``` + +### 2. Layer responsibilities + +| Layer | Primary purpose | Typical format | Used by | +|:---|:---|:---|:---| +| `1_Bronze_Raw` | Raw evidence retention and replay | JSONL / CSV / parsed source artifacts | Operators, debugging, reprocessing | +| `2_Silver_Processed` | Deterministic analytical truth | Parquet | SQL tools, Checker, quant logic | +| `3_Gold_Semantic` | Retrieval-ready semantic artifacts | JSONL / Markdown | Qdrant ingestion, hybrid RAG | +| `Agent_Context` | Stable prompt-time convenience snapshot | Markdown | LLM prompt assembly | + +--- + +## V. Pipeline Registry + +| Source | Ingestion Script | Provides | Cadence | +|:---|:---|:---|:---| +| **Options chains** | `scrapers/yfinance_options_history.py` | Per-contract IV, volume, OI, moneyness, spreads, liquidity flags for SPY / QQQ / IWM / GLD / SLV | Daily 07:20 | +| **Macro & market** | `scrapers/macro_data_pipeline.py` | Same-day market levels, daily changes, FRED macro series, MoM / YoY macro deltas | Trading days 06:30 | +| **GPR Index** | `scrapers/GPR_index.py` | Monthly geopolitical risk level, momentum, percentile, semantic narratives | Monthly 06:05 | +| **News** | `scrapers/news_scraper.py` | Topic-partitioned article capture, full text, semantic enrichment, tone and volatility implication | Daily 07:00 | +| **SEC ingestion** | `scrapers/sec_ingestion.py` | Bronze-layer Form 4 / 8-K parsed filings | Weekly Sunday 08:00 | +| **SEC processing** | `processors/sec_processor.py` | Gold-layer enriched summaries, tone scores, Qdrant-ready SEC payloads | Weekly Sunday 09:00 | + +Primary scheduler entrypoint: `Scripts/data_collection/collect_data.py` +Current orchestration CLI: `python -m Scripts ingest`, `daemon`, `status` + +--- + +## VI. Source Profiles + +### 1. Options Market Data + +| Item | Detail | +|:---|:---| +| **System of record** | Yahoo Finance via `yfinance` | +| **Primary script** | `Scripts/data_collection/scrapers/yfinance_options_history.py` | +| **Coverage** | SPY, QQQ, IWM, GLD, SLV | +| **Silver contract** | Strike, expiration, call/put, bid, ask, last price, volume, open interest, implied volatility, in-the-money flag | +| **Derived fields** | `dte`, `moneyness_pct`, `spread_pct`, `is_liquid` | +| **Storage layer** | Silver only | +| **Primary consumers** | `sql_tools.py`, Analyst / Checker quantitative validation | + +### 2. Macro and Market Data + +| Item | Detail | +|:---|:---| +| **Systems of record** | Yahoo Finance + FRED | +| **Primary script** | `Scripts/data_collection/scrapers/macro_data_pipeline.py` | +| **Series coverage** | `^GSPC`, `^IXIC`, `^VIX`, `DX-Y.NYB`, `GLD`, `SLV`, `FEDFUNDS`, `CPIAUCSL`, `UNRATE` | +| **Silver contract** | `retrieval_date`, `observation_date`, `symbol`, `asset_class`, `value`, `unit`, `frequency`, `daily_change_pct`, `mom_change_pct`, `yoy_change_pct` | +| **Gold-side derivative** | Markdown macro narrative snapshot | +| **Agent convenience output** | `Data/Agent_Context/latest_macro_context.md` | +| **Architectural rule** | Numeric truth lives in Silver `Macro_History`, not in markdown prompt context | + +### 3. Geopolitical Risk Index + +| Item | Detail | +|:---|:---| +| **System of record** | Iacoviello GPR Index | +| **Primary script** | `Scripts/data_collection/scrapers/GPR_index.py` | +| **Silver contract** | `gpr`, percentile, MoM, YoY, moving averages | +| **Gold contract** | `qdrant_gpr_input.jsonl` + narrative markdown | +| **Cadence** | Monthly | +| **Primary consumers** | Silver geopolitical handlers, Gold retrieval, macro regime synthesis | + +### 4. News and Sentiment + +| Item | Detail | +|:---|:---| +| **Systems of record** | GDELT 2.0 + web full-text extraction | +| **Primary script** | `Scripts/data_collection/scrapers/news_scraper.py` | +| **Bronze contract** | Raw GDELT captures + full-text article fetches | +| **Gold contract** | Topic-partitioned semantic JSONL for Qdrant | +| **Enrichment** | `llm_tone_score`, entities, impacted assets, volatility implication | +| **Primary consumers** | Qdrant retriever, Analyst, Critic | + +### 5. SEC Regulatory Filings + +| Item | Detail | +|:---|:---| +| **System of record** | SEC EDGAR REST API | +| **Primary scripts** | `sec_ingestion.py` -> `sec_processor.py` | +| **Bronze contract** | Parsed Form 4 and 8-K artifacts | +| **Gold contract** | `qdrant_ready.jsonl` | +| **Enrichment** | Rule-based insider tone, action direction, LLM-generated Form 8-K semantic summaries | +| **Primary consumers** | Qdrant retriever, insider-flow analysis, risk challenge | + +--- + +## VII. Processing Status Matrix + +| Data source | Bronze | Silver | Gold | LLM / enrichment mode | Qdrant | +|:---|:---:|:---:|:---:|:---|:---:| +| SEC Form 4 / 8-K | Yes | No | Yes | Form 4 rules; 8-K semantic enrichment | Yes | +| News / GDELT | Yes | No | Yes | LLM refinement and semantic labels | Yes | +| Macro / Market | No | Yes | Yes | Template-built markdown; Silver remains numeric truth | No by default | +| GPR Index | Yes (preview) | Yes | Yes | Rule-generated narrative and deterministic JSONL | Yes | +| Options market data | No | Yes | No | No LLM dependency | No | + +--- + +## VIII. Runtime State and Dynamic Anchors + +`config/runtime/collect_data_state.json` records the last successful ingestion key per source family. Retrieval-time date logic uses these anchors rather than wall-clock `CURRENT_DATE`, which is essential for weekends, holidays, and backfills. + +| State key | Primary downstream consumer | +|:---|:---| +| `options_daily` | Options handlers in `sql_tools.py` | +| `macro_trading_daily` | Macro handlers in `sql_tools.py` | +| `gpr_monthly` | GPR handlers in `sql_tools.py` | +| `news_daily` | News freshness logic and orchestration visibility | +| `sec_daily` | Vector ingestion source-date alignment | + +--- + +## IX. Architectural Control Notes + +- `Data/Agent_Context/latest_macro_context.md` is a **convenience projection**, not the numeric system of record. +- Gold Qdrant ingestion auto-discovers **Gold JSONL** artifacts; Markdown narratives are not ingested by default. +- `Macro_Narratives/*.md` improves prompt readability, but deterministic validation should bind to Silver values. +- For time filtering and cadence alignment, use the time-contract documents together with retrieval docs rather than inferring rules from file names alone. + +--- + +## X. Detailed Technical Dossiers + +Use this document as the master index, then drill down into the specialized source dossiers: + +- Options data details: [`docs/Data_source_docs/options_historial_data.md`](options_historial_data.md) +- Macro / market data details: [`docs/Data_source_docs/macro_market_data.md`](macro_market_data.md) +- News ingestion details: [`docs/Data_source_docs/market_news_data.md`](market_news_data.md) +- SEC filing pipeline details: [`docs/Data_source_docs/SEC_data.md`](SEC_data.md) +- GPR source details: [`docs/Data_source_docs/GPR_Index.md`](GPR_Index.md) +- Time key and cadence contract: [`docs/Data_source_docs/Time_Schema_Audit.md`](Time_Schema_Audit.md) + +--- + +## XI. Consolidated Dependencies + +```bash +pip install requests pandas numpy pyarrow yfinance fredapi python-dotenv \ + beautifulsoup4 markdownify langchain-ollama newspaper3k duckduckgo-search \ + fastembed qdrant-client pydantic rich nltk duckdb +``` + +**Required services and credentials:** +- **Ollama** for local semantic enrichment and agent inference. +- **Qdrant** for Gold semantic retrieval. +- **FRED API key** via `FRED_API_KEY`. +- **SEC User-Agent** via `SEC_USER_AGENT`. diff --git a/docs/Data_source_docs/GPR_Index.md b/docs/Data_source_docs/GPR_Index.md new file mode 100644 index 0000000..632229f --- /dev/null +++ b/docs/Data_source_docs/GPR_Index.md @@ -0,0 +1,100 @@ +# Geopolitical Risk (GPR) Index — `GPR_index.py` + +## 1. What this source provides (for downstream analysis) + +- **Monthly global GPR level** from the Iacoviello academic series, usable as a macro stress / safe-haven demand driver alongside precious metals and volatility narratives. +- **Enriched series:** month-over-month and year-over-year change, 3-month moving average, full-sample percentile rank. +- **RAG outputs:** per-month markdown narratives and deterministic Qdrant JSONL payloads so retrieval stays idempotent across reruns. + +--- + +## 2. Architecture and strategy workflow + +### Step 1 — Extraction (fault-tolerant download) + +1. Download the latest GPR `.xls` file directly from Matteo Iacoviello's academic repository. +2. Retry on failure (up to 3 attempts with 10-second delays) for network drops or site outages. +3. Parse legacy date formats (e.g., `1985M01`) into standard Python datetime objects. + +### Step 2 — Transformation and statistical enrichment + +1. Operate on the *entire* historical dataset so long-window metrics stay correct. +2. Compute: + - **MoM %** (Month-over-Month change) + - **YoY %** (Year-over-Year change) + - **3-Month Moving Average** (trend smoothing) + - **Historical Percentile** (ranks the current threat level against all historical data) + +### Step 3 — Natural language generation (NLG) + +1. Uses conditional logic based on MoM momentum to generate dynamic RAG-friendly markdown. For example, a >10% jump generates a "significant escalation" narrative, while a <-10% drop generates a "cooling off" narrative. +2. Hardcodes trading context into the text (e.g., explicitly mentioning the historical correlation between GPR spikes and Gold/Silver price action). + +### Step 4 — Idempotent archival (load preparation) + +1. **Truncation:** Keep post-2020 rows only so older regimes do not dominate the vector space. +2. **Deterministic UUIDs:** Qdrant document IDs use `uuid5` from a fixed string (e.g., `GPR_2024_04`) so reruns overwrite the same logical documents without duplicates. + +--- + +## 3. Pipeline strategy (inputs, outputs, frequency) + +| Item | Detail | +| :--- | :--- | +| **Input** | Remote URL only: `https://www.matteoiacoviello.com/gpr_files/data_gpr_export.xls` (no local input file). | +| **Outputs** | See table below. | +| **Update frequency** | **Monthly** per `collect_data.py` (06:05). Each successful run refreshes the full post-2020 slice in Parquet and Gold files. | + +### Output paths (repo root relative) + +| Layer | Path | +| :--- | :--- | +| Bronze (preview CSV, last 24 rows) | `Data/1_Bronze_Raw/GPR_index/{YYYY-MM-DD}/gpr_preview.csv` | +| Silver (canonical Parquet) | `Data/2_Silver_Processed/GPR_index/gpr_monthly_enriched.parquet` | +| Gold (narrative + Qdrant) | `Data/3_Gold_Semantic/GPR_index/{YYYY-MM-DD}/gpr_narrative_corpus.md`, `qdrant_gpr_input.jsonl` | +| Logs | `logs/{YYYY-MM-DD}/gpr_downloader.log` | + +--- + +## 4. Data shapes and metadata + +### Parquet: `gpr_monthly_enriched.parquet` (post-2020 only) + +| Column | Type (logical) | Description | +| :--- | :--- | :--- | +| `month` | string | Original series month key | +| `gpr` | float | Raw GPR index | +| `date` | datetime | Parsed month-end style date | +| `gpr_mom_pct` | float | Month-over-month % change | +| `gpr_yoy_pct` | float | Year-over-year % change | +| `gpr_3m_ma` | float | 3-month rolling mean | +| `gpr_percentile` | float | Percentile rank (0–100) vs full history | + +### JSONL: `qdrant_gpr_input.jsonl` (top-level) + +| Field | Description | Type | +| :--- | :--- | :--- | +| `id` | A deterministic UUID v5 (e.g., hashed from "GPR_2024_04"). | String | +| `text` | The full, multi-paragraph markdown narrative detailing the month's metrics, historical context, and asset impact. | String | +| `metadata` | A nested dictionary for exact payload filtering in the vector database. | Object | + +### `metadata` object structure + +| Key | Description | Type | +| :--- | :--- | :--- | +| `topic` | Hardcoded routing tag (`"macro_geopolitics_risk"`). | String | +| `title` | Human-readable title (e.g., `"GPR Index Update 2024-04"`). | String | +| `publish_date` | Formatted string of the observation month (`"YYYY-MM-DD"`). | String | +| `publish_timestamp` | Integer Unix epoch for fast time-series filtering in Qdrant. | Integer | +| `gpr_score` | The raw Geopolitical Risk index float value. | Float | +| `gpr_percentile` | The calculated historical percentile (0-100) of the current score. | Float | + +--- + +## 5. Dependencies + +```bash +pip install requests pandas pyarrow xlrd +``` + +`xlrd` supports legacy `.xls` reads used by `pd.read_excel` on the downloaded file. diff --git a/docs/Data_source_docs/SEC_data.md b/docs/Data_source_docs/SEC_data.md new file mode 100644 index 0000000..de9a5aa --- /dev/null +++ b/docs/Data_source_docs/SEC_data.md @@ -0,0 +1,164 @@ +# SEC Regulatory Filings — Ingestion & Processing Pipeline + +## 1. Goal + +Ingest Form 4 (insider transactions) and Form 8-K (material corporate events) from SEC EDGAR, enrich them with rule-based and LLM-generated signals, and produce idempotent Qdrant-ready payloads for Gold-layer retrieval. The processed output is the exclusive source of insider-activity signals surfaced by the `QdrantRetriever` during agent analysis. + +--- + +## 2. Architecture + +The pipeline runs in two sequential phases: **Bronze ingestion** (raw scraping) and **Gold processing** (enrichment + vector preparation). A shared accession-number registry enforces idempotency across both phases. + +``` +SEC EDGAR REST API + │ + ▼ +[Phase A] sec_ingestion.py + │ • CIK resolution from config/SEC_Ingestion/ticker_to_cik.json + │ • Form 4 (XML) → structured transaction rows + │ • Form 8-K (HTML) → markdownified, optionally item-chunked + │ • 7-day rolling window; exponential-backoff on HTTP 429 + │ + ▼ Data/1_Bronze_Raw/SEC_Parsed_JSON/{YYYY-MM-DD}/{TICKER}.jsonl + │ _SUMMARY.json + │ + ▼ +[Phase B] sec_processor.py + │ • Dedup via global_processed_registry.json + │ • Form 4 → rule-based tone score + C-suite / 10b5-1 adjustments + │ • Form 8-K → options-expert-v1 / llama3 LLM (JSON mode) summary + │ • ThreadPoolExecutor (max_workers=4) for LLM-bound concurrency + │ + ▼ Data/3_Gold_Semantic/SEC_Insider_Trades/{YYYY-MM-DD}/qdrant_ready.jsonl + config/SEC_Processing/global_processed_registry.json (updated) +``` + +--- + +## 3. Code Strategy & Workflow + +### Phase A — Ingestion (`sec_ingestion.py`) + +| Step | Strategy | +|:---|:---| +| **Ticker universe** | Loaded from `config/SEC_Ingestion/SEC_tickers.json`; mapped to CIK via `config/SEC_Ingestion/ticker_to_cik.json` | +| **EDGAR query** | `GET data.sec.gov/submissions/CIK{cik}.json` → filter `filingDate` within last 7 days for Form 4 and 8-K | +| **Form 4 parse** | Fetch document XML, extract `reportingOwner`, `role`, `nonDerivativeTransaction[]` (shares, prices, codes, 10b5-1 flags) | +| **8-K parse** | Fetch HTML, `BeautifulSoup` strip → `markdownify` → optional split by `Item X.XX` headers into chunks | +| **Rate resilience** | Exponential backoff on HTTP 429/503; 1 s floor between requests | +| **Output** | Append one JSON object per filing to `{TICKER}.jsonl`; write cross-ticker `_SUMMARY.json` | + +### Phase B — Processing (`sec_processor.py`) + +| Step | Strategy | +|:---|:---| +| **Dedup guard** | Load `global_processed_registry.json` as a set; skip any row whose `accession_no` is already present | +| **Form 4 scoring** | Net-value tone (positive = buy signal); 10b5-1 planned-sale discount (−1); C-suite multipliers (+2 buy / −2 sell); zero-dollar vesting → `ACQUIRE/VEST` | +| **8-K LLM** | `ChatOllama(model="options-expert-v1:latest", format="json")` → strict JSON with `summary`, `transaction_date`, `tone_score`, `topics` | +| **Concurrency** | `ThreadPoolExecutor(max_workers=4)` — each future processes one Bronze row | +| **Registry update** | Append `accession_no` to registry file after each successful Gold write | + +--- + +## 4. Output Data Schema & Paths + +### Storage Paths + +| Artifact | Path | +|:---|:---| +| **Bronze JSONL** | `Data/1_Bronze_Raw/SEC_Parsed_JSON/{YYYY-MM-DD}/{TICKER}.jsonl` | +| **Bronze summary** | `Data/1_Bronze_Raw/SEC_Parsed_JSON/{YYYY-MM-DD}/_SUMMARY.json` | +| **Gold JSONL** | `Data/3_Gold_Semantic/SEC_Insider_Trades/{YYYY-MM-DD}/qdrant_ready.jsonl` | +| **Registry** | `config/SEC_Processing/global_processed_registry.json` | +| **Ingestion log** | `logs/{YYYY-MM-DD}/SEC_Ingestion/ingestion_progress_{YYYY-MM-DD}.log` | + +### Bronze JSONL Schema (per line) + +| Field | Type | Description | +|:---|:---|:---| +| `metadata.ticker` | `string` | Stock symbol (e.g. `"AAPL"`) | +| `metadata.form_type` | `string` | `"4"` or `"8-K"` | +| `metadata.filed_at` | `string` | SEC filing date `YYYY-MM-DD` | +| `metadata.accession_no` | `string` | Unique SEC identifier | +| `metadata.url` | `string` | Primary document URL on EDGAR | +| `metadata.ingested_at` | `string` | ISO timestamp of ingestion write | +| `parsed_data` | `object` | Form 4: `reporting_owner`, `role`, `transactions[]`. 8-K: `is_chunked`, `item_chunks` or `full_markdown` | +| `raw_text` | `string` | Sentinel string (`"XML_PARSED_SUCCESSFULLY"`, `"8K_PARSED_INTO_MARKDOWN_CHUNKS"`, or error note) | + +### Gold `qdrant_ready.jsonl` Schema (per line) + +| Field | Type | Description | +|:---|:---|:---| +| `text` | `string` | Human-readable summary sentence (Form 4) or LLM-generated summary (8-K) | +| `metadata.ticker` | `string` | Stock symbol | +| `metadata.form_type` | `string` | `"4"` or `"8-K"` | +| `metadata.filed_at` | `string` | SEC filing date | +| `metadata.accession_no` | `string` | Dedup key | +| `metadata.url` | `string` | Source document link | +| `metadata.transaction_date` | `string` | Actual event date (Form 4 trade date; 8-K event date from LLM) | +| `metadata.tone_score` | `int` | −5 … +5 (rule-based for Form 4; LLM for 8-K) | +| `metadata.action_direction` | `string` | `"BUY"`, `"SELL"`, `"ACQUIRE/VEST"`, or `"NONE"` | +| `metadata.topics` | `array[string]` | E.g. `["Insider Trading", "Form 4"]` | +| `metadata.source_type` | `string` | `"sec"` (required by QdrantRetriever filter) | +| `metadata.unified_timestamp` | `float` | Unix-seconds epoch derived from `transaction_date` (enables numeric Qdrant Range filter) | +| `metadata.processed_at` | `string` | ISO 8601 timestamp of Gold write | + +> **Note on `unified_timestamp`**: Added post-2026-04-22 to support the `TimeAdapter` numeric Range binding. Legacy payloads without this field still have `filed_at` / `transaction_date` ISO strings for fallback matching. + +--- + +## 5. How to Test + +### Validate Bronze output + +```bash +python Scripts/data_collection/scrapers/sec_ingestion.py +# Expected: Data/1_Bronze_Raw/SEC_Parsed_JSON/{today}/{TICKER}.jsonl for each ticker +``` + +### Validate Gold processing + +```bash +python Scripts/data_collection/processors/sec_processor.py +# Expected: Data/3_Gold_Semantic/SEC_Insider_Trades/{today}/qdrant_ready.jsonl +``` + +### Inspect accession registry + +```python +import json +reg = json.load(open("config/SEC_Processing/global_processed_registry.json")) +print(f"Registry size: {len(reg)} accessions") +``` + +### Qdrant retrieval smoke test (post-ingestion) + +```bash +# Run after Qdrant_Ingestion.py has upserted the Gold JSONL +python -m Scripts.tests.test_master_retriever +# Query: "Any recent AAPL insider trades?" +# Expected: gold_chunks > 0, source_type="sec", form_type="4" +``` + +--- + +## 6. Dependencies + +| Library | Phase | Purpose | +|:---|:---|:---| +| `requests` | A | EDGAR HTTP calls | +| `beautifulsoup4` | A | HTML stripping for 8-K | +| `markdownify` | A | HTML → Markdown conversion | +| `python-dotenv` | A + B | `.env` loading (`SEC_USER_AGENT`) | +| `langchain-ollama` | B | LLM 8-K summarisation | + +```bash +# Phase A +pip install requests beautifulsoup4 markdownify python-dotenv + +# Phase B (plus local Ollama with options-expert-v1 or llama3) +pip install langchain-ollama python-dotenv +``` + +**Required environment variable:** `SEC_USER_AGENT` — e.g. `"CompanyName contact@email.com"` (SEC fair-access policy requires a valid identifier in every request header). diff --git a/docs/Data_source_docs/Time_Schema_Audit.md b/docs/Data_source_docs/Time_Schema_Audit.md new file mode 100644 index 0000000..84beef6 --- /dev/null +++ b/docs/Data_source_docs/Time_Schema_Audit.md @@ -0,0 +1,290 @@ +# Time Schema Audit — All Data Sources + +> **Authoritative reference for every time column / payload key in the lake.** +> Updated: 2026-04-24 · Owner: RAG architecture +> Companion module: `Scripts/retrieval/time_adapter.py` +> Companion audit log: `logs/retrieval//retriever_audit_trail.jsonl` (field `source_predicates`) + +--- + +## 0. Why this document exists + +A RAG system that mixes Qdrant (vector) and Parquet (SQL) cannot apply a single +`(start_ts, end_ts)` window to every query: each source stores time differently +and runs on a different cadence. Before this audit a "yesterday" query against +GPR returned `0` rows (monthly source, no daily data exists), and a "past week" +query against legacy SEC returned `0` hits (no numeric timestamp key in payload). + +The fix is a **per-source Time Alignment Adapter** (`time_adapter.py`) that +compiles one `TimePredicate` per source, applying source-specific widening +rules. This document is the source of truth for what keys exist, their units, +and the widening policy applied in production. + +--- + +## 1. Silver Layer (Parquet / DuckDB) + +### 1.1 Options Market Data + +| Attribute | Value | +|-------------------|-------| +| Path (glob) | `Data/2_Silver_Processed/Options_Market_Data//_options_.parquet` | +| Writer | `Scripts/data_collection/scrapers/yfinance_options_history.py` | +| Cadence | **Daily** (trading days only; weekends/holidays missing) | +| Primary time col | `snapshot_date` | +| Other time cols | `expiration` (contract expiry, not snapshot) | +| Physical type | `VARCHAR` (`YYYY-MM-DD`) | +| Timezone | US market close (approx `America/New_York`); stored naive | +| Cast for BETWEEN | `CAST(snapshot_date AS DATE) BETWEEN CAST(? AS DATE) AND CAST(? AS DATE)` | +| Granularity enum | `TimeGranularity.DAILY` | +| Min lookback | `3 days` (survives weekend gap on Monday-anchored "yesterday") | +| `SourceTimeKey` | `silver.options` | + +### 1.2 Macro History + +| Attribute | Value | +|-------------------|-------| +| Path (glob) | `Data/2_Silver_Processed/Macro_History//macro_snapshot_.parquet` | +| Writer | `Scripts/data_collection/scrapers/macro_data_pipeline.py` | +| Cadence | **Mixed** — Daily (Yahoo Finance) + Monthly (FRED) interleaved | +| Primary time col | `observation_date` (authoritative series date) | +| Other time cols | `retrieval_date` (ingestion day) | +| Physical type | `VARCHAR` (`YYYY-MM-DD`) | +| Timezone | UTC (observation) / local ingest (retrieval) — stored naive | +| Cast for BETWEEN | `CAST(observation_date AS DATE) BETWEEN CAST(? AS DATE) AND CAST(? AS DATE)` | +| Granularity enum | `TimeGranularity.DAILY` (predominant; monthly rows survive via `ORDER BY observation_date DESC LIMIT 1`) | +| Min lookback | `3 days` | +| `SourceTimeKey` | `silver.macro` | + +> **Frequency column:** rows also carry a `frequency ∈ {"Daily", "Monthly"}` +> field. Analyst can use it to disambiguate CPI / UNRATE (Monthly) from ^GSPC +> / VIX (Daily) without requiring separate partitions. + +### 1.3 GPR Index (Silver) + +| Attribute | Value | +|-------------------|-------| +| Path | `Data/2_Silver_Processed/GPR_index/gpr_monthly_enriched.parquet` (single file, overwritten in place) | +| Writer | `Scripts/data_collection/scrapers/GPR_index.py` | +| Cadence | **Monthly** (first-of-month rows) | +| Primary time col | `date` | +| Other time cols | `month` (duplicate of `date`) | +| Physical type | `TIMESTAMP_NS` (pandas/arrow nanosecond timestamp) | +| Timezone | UTC, stored naive | +| Cast for BETWEEN | `date BETWEEN ? AND ?` (DuckDB coerces `DATE` → `TIMESTAMP_NS` automatically) | +| Granularity enum | `TimeGranularity.MONTHLY` | +| Min lookback | `35 days` (always widens to the full anchor month) | +| `SourceTimeKey` | `silver.gpr` | + +> **Widening example:** a `"yesterday"` query (2d base) is widened to +> `[first-of-month(anchor), anchor]` (≥28 d) so the latest GPR row for the +> anchor month is always inside the window. Without this, monthly data is +> effectively invisible to short-horizon queries. + +--- + +## 2. Gold Layer (Qdrant vector store) + +All Gold payloads share a **canonical time key**: `unified_timestamp` +(Unix seconds, integer, UTC). Legacy payloads that predate the +2026-04-22 ingestion fix may still be missing this key — the retriever +supports either via a nested `Filter(should=[...])` on `unified_timestamp` +OR `publish_timestamp` (see §4). + +### 2.1 News — `source_type == "news"` + +| Key | Physical type | Unit | Required? | Notes | +|-------------------------|---------------|-------------|-----------|-------| +| `unified_timestamp` | `int` | epoch_s | Post-fix | Mirror of `publish_timestamp` on ingest | +| `publish_timestamp` | `int` | epoch_s | Yes | Event time, written by `news_scraper.py` | +| `publish_date` | `str` | ISO-8601 Z | Yes | Human-readable companion (e.g. `2026-04-19T16:29:12Z`) | + +| Attribute | Value | +|-----------------|-------| +| Cadence | Event (sub-daily) | +| Granularity enum| `TimeGranularity.EVENT` | +| Min lookback | `1 day` | +| `SourceTimeKey` | `gold.news` | + +### 2.2 SEC Insider Trades — `source_type == "sec"` + +| Key | Physical type | Unit | Required? | Notes | +|-------------------------|---------------|----------------|---------------|-------| +| `unified_timestamp` | `int` | epoch_s | Post-fix only | Derived from `transaction_date` (preferred), else `filed_at`, else `ingested_at`. **Absent on pre-2026-04-22 ingests.** | +| `filed_at` | `str` | ISO-8601 + TZ | Yes | e.g. `2026-04-13T18:30:45-04:00` (America/New_York) | +| `transaction_date` | `str` | ISO date | Yes | Actual trade date, no TZ (e.g. `2026-04-13`) | +| `ingested_at` | `str` | ISO datetime | Yes | Bronze-layer ingestion timestamp (naive, local) | +| `processed_at` | `str` | ISO datetime | Yes | Gold-layer processing timestamp | + +| Attribute | Value | +|-----------------|-------| +| Cadence | Event (sub-daily, but bursty around market close) | +| Granularity enum| `TimeGranularity.EVENT` | +| Min lookback | `3 days` (filings often clump on Monday post-weekend; 3-day floor keeps recall non-zero) | +| `SourceTimeKey` | `gold.sec` | + +> **⚠️ Pre-reingest risk.** Because legacy SEC payloads have **neither +> `unified_timestamp` nor `publish_timestamp`**, a Qdrant numeric Range +> filter on these docs matches nothing. The retriever mitigation is +> documented in §4 ("Source-type logic check"), and the permanent fix is +> running `Scripts/vector_store/ingestion.py` to backfill `unified_timestamp`. + +### 2.3 GPR (Gold) — `source_type == "gpr"` + +| Key | Physical type | Unit | Required? | Notes | +|-------------------------|---------------|--------|-----------|-------| +| `unified_timestamp` | `int` | epoch_s| Post-fix | Mirror of `publish_timestamp` | +| `publish_timestamp` | `int` | epoch_s| Yes | First-of-month epoch seconds | +| `publish_date` | `str` | ISO date| Yes | e.g. `2020-01-01` | + +| Attribute | Value | +|-----------------|-------| +| Cadence | **Monthly** (one point per month) | +| Granularity enum| `TimeGranularity.MONTHLY` | +| Min lookback | `35 days` | +| `SourceTimeKey` | `gold.gpr` | + +--- + +## 3. Registry summary (single glance) + +| SourceTimeKey | Layer | Cadence | Time keys (priority order) | Units | Min lookback | +|----------------------|--------|----------|----------------------------------------------------------|----------------------------------------------|--------------| +| `gold.news` | Gold | Event | `unified_timestamp`, `publish_timestamp` | `epoch_s`, `epoch_s` | 1 d | +| `gold.sec` | Gold | Event | `unified_timestamp`, `filed_at`, `transaction_date` | `epoch_s`, `iso_datetime`, `iso_date` | 3 d | +| `gold.gpr` | Gold | Monthly | `unified_timestamp`, `publish_timestamp` | `epoch_s`, `epoch_s` | 35 d | +| `silver.options` | Silver | Daily | `snapshot_date` | `iso_date` | 3 d | +| `silver.macro` | Silver | Daily | `observation_date`, `retrieval_date` | `iso_date`, `iso_date` | 3 d | +| `silver.gpr` | Silver | Monthly | `date`, `month` | `ts_ns`, `ts_ns` | 35 d | + +This table is the machine-readable registry `SOURCE_SPECS` in +`Scripts/retrieval/time_adapter.py`. Keep them in sync. + +--- + +## 4. Source-type logic check: `source_types = ["sec", "news"]` + +**Question:** does simultaneously matching `unified_timestamp` OR +`publish_timestamp` across mixed source types create a logic problem? + +**Answer:** no, provided re-ingestion has run. In detail: + +| Payload family | `unified_timestamp` present? | `publish_timestamp` present? | Behaviour under nested `should` filter | +|----------------------|------------------------------|------------------------------|----------------------------------------| +| News (any vintage) | Yes (post-fix) / No (legacy) | **Yes** | Always matches via `publish_timestamp` | +| GPR (any vintage) | Yes (post-fix) / No (legacy) | **Yes** | Always matches via `publish_timestamp` | +| SEC (post-fix) | **Yes** | No | Matches via `unified_timestamp` | +| SEC (legacy) | No | No | **Does not match — invisible to time filter** | + +The `Filter(should=[...])` clause is satisfied when **at least one** timestamp key lands in range. So mixing `["sec", "news"]`: +- News docs always pass (they carry `publish_timestamp`). +- Post-reingest SEC docs pass via `unified_timestamp`. +- Legacy SEC docs are silently excluded — operationally indistinguishable from "no SEC data exists for this window", which is a **correctness + win** (do not emit false SEC anchors) at the cost of **recall** (missing docs whose timestamp existed only as an ISO string). + +### 4.1 Operational mitigation + +1. **Re-ingest SEC via `Scripts/vector_store/ingestion.py`.** The ingestion enricher (patched 2026-04-22) now parses `transaction_date` → Unix + seconds and writes `unified_timestamp` for every SEC document. This permanently removes the legacy-blind-spot. +2. **Audit visibility.** Every retriever run writes `source_predicates` + `filter_applied` to `logs/retrieval//retriever_audit_trail.jsonl`. Operators can query for `fallback_tier != "strict" AND source_type_contains("sec")` to quantify the legacy SEC gap over time. + +### 4.2 Why this design is still the right one + +Alternatives considered and rejected: + +| Alternative | Why rejected | +|--------------------------------------------|------------------------------------------------------------------------------| +| Require only `unified_timestamp` | Hard breaking change; blanks out ALL legacy news/gpr docs too | +| Add `filed_at` as a string Range condition | Qdrant `Range` is numeric-only; string ranges need `DatetimeRange` (1.8+) | +| Duplicate every doc into multiple keys | Index bloat; cannot backfill without re-vectorising | +| Per-source sub-queries joined at app layer | 3× Qdrant round-trips; breaks RRF fusion because each source has its own topk| + +Nested `should` on `{unified_timestamp, publish_timestamp}` gives us one Qdrant call, backward compat, and a clean migration path. The Gold retriever (`qdrant_retriever._build_smart_filter`) implements it. + +--- + +## 5. Robust time handling — recommendations + +These are the patterns this codebase now uses; keep them as guardrails. + +### 5.1 Compile once, execute everywhere +`MasterRetriever._compute_time_range` calls `time_adapter.compile_all(...)` and publishes the `{SourceTimeKey → TimePredicate}` dict on `self._current_predicate_set`. Both Gold (`qdrant_retriever`) and Silver (`sql_tools`) read from that compiled set — no retriever ever re-derives the window from raw `metadata.time_window`. This is the single invariant that kills off cross-layer drift. + +### 5.2 Anchor = latest successful ingestion, not `date.today()` +Anchor dates come from `config/runtime/collect_data_state.json` +(`SilverSQLTool._get_anchor_date`). Weekends, holidays, and backfills all +land on the last known-good partition. Wall-clock-anchored queries are a +pre-2026-04-04 anti-pattern; see the "Dynamic Time Anchor" note in +`sql_tools.py`. + +### 5.3 Per-source widening is source-spec-driven, not query-spec-driven +Widening rules (monthly → month-wide, daily → 3-day weekend-safe) live +on `SourceTimeSpec.min_lookback_days`. Never embed them in handler +branches — add a spec row instead. + +### 5.4 Always store **both** a numeric epoch **and** a human ISO +Every new ingestion writer must emit `unified_timestamp` (Unix seconds, +integer, UTC) AND a readable ISO date companion (`publish_date` / +`transaction_date` / `observation_date`). The epoch key is what filters +bind to; the ISO string is what humans and audit logs cite. Do not make +operators reverse-engineer epoch offsets during an incident. + +### 5.5 Timezone normalisation at ingest, not at query +The ingestion enricher converts all timestamps to UTC before storing. +Downstream code can treat every Unix epoch as UTC. If a new source +writes local-time ISO strings, fix it at the ingest boundary, not in +the retriever. + +### 5.6 Weekend-safe "end-of-day" bounds +`time_adapter._to_epoch_bounds` pushes `end_date` to `23:59:59 UTC` so +a same-day query (e.g. `today`) still matches events that occurred +during the day. This is the small detail that makes `yesterday` queries +not empty when the anchor is "today". + +### 5.7 Hard filter + soft fallback, never hard filter alone +The Gold retriever has three tiers: strict (per-source aligned window), +soft (180-day + ticker-OR-topic), drop (180-day no ticker). The first +non-empty tier wins, and the tier label is persisted in the audit log +(`fallback_tier`). Monitor "tier != strict" rates as a data-freshness +signal. + +### 5.8 Mandatory audit keys +Every retriever call must emit: +- `source_predicates`: serialised per-source TimePredicates +- `fallback_tier`: `strict | soft_ticker_180d | drop_ticker_180d | error` +- `filter_applied`: the Qdrant Filter object (Pydantic dump) +- `window_days`, `start_date`, `end_date` + +Any retriever that omits these is a regression. + +--- + +## 6. Implementation cross-reference + +| Concern | File | Anchor | +|-----------------------------|-----------------------------------------------|---------------------------------| +| Semantic `TimeWindow` enum | `Scripts/retrieval/schema.py` | `class TimeWindow` + `TIME_WINDOW_DAYS` | +| Per-source compiler | `Scripts/retrieval/time_adapter.py` | `compile_predicate`, `compile_all`, `SOURCE_SPECS` | +| Orchestration / wiring | `Scripts/retrieval/master_retriever.py` | `_compute_time_range`, `_current_predicate_set` | +| Gold retriever binding | `Scripts/retrieval/qdrant_retriever.py` | `_build_smart_filter`, `_select_gold_predicates`, `retrieve_async(time_predicates=...)` | +| Silver retriever binding | `Scripts/retrieval/sql_tools.py` | `query_parquet_by_metadata(time_predicates=...)`, `_predicate_for`, `_handle_put_call_ratio` | +| Ingestion-side guarantees | `Scripts/vector_store/ingestion.py` | `QdrantHybridIngestor.process_and_upsert_file` (normalizes source payloads and timestamps before upsert) | +| Anchor (calendar truth) | `config/runtime/collect_data_state.json` | `last_run_keys.{options_daily, macro_trading_daily, gpr_monthly, news_daily}` | + +--- + +## 7. Document Boundary and Folder Policy + +### 7.1 Functional difference between the two documents + +| Document | Scope | Primary audience | Update trigger | +|---|---|---|---| +| `Time_Adapter.md` | Time-window compilation logic (`TimeWindow -> TimePredicate`) and widening behavior | Retrieval/orchestration engineers | Any change to `compile_predicate`, widening policy, or source predicate wiring | +| `Time_Schema_Audit.md` | Physical source-of-truth for time columns/keys/units across Silver and Gold datasets | Data platform and retrieval engineers | Any schema/cadence/time-key change in ingestion or storage layers | + +### 7.2 Should they live in different docs folders? + +Recommended operating model: +- Keep `Time_Adapter.md` in `docs/Query_retrieval_docs/` because it documents retrieval-time query compilation behavior. +- Move `Time_Schema_Audit.md` to `docs/Data_source_docs/` when you want clear ownership separation between retrieval logic and physical data contracts. +- If you do not want to move files right now, keep both in the current folder but add explicit cross-links and owner notes (this document now includes that boundary). diff --git a/docs/Data_source_docs/macro_market_data.md b/docs/Data_source_docs/macro_market_data.md new file mode 100644 index 0000000..640544c --- /dev/null +++ b/docs/Data_source_docs/macro_market_data.md @@ -0,0 +1,84 @@ +# Macro and market data — `macro_data_pipeline.py` + +The pipeline bridges the gap between high-frequency market data (Stock indices, Volatility) and low-frequency economic indicators (Inflation, Interest rates). + +This documentation details the `macro_data_pipeline.py` script, which automates the collection of global market data and macroeconomic indicators for financial analysis and RAG (Retrieval-Augmented Generation) applications. + +--- + +## 1. What this source provides (for downstream analysis) + +- **Market snapshot:** Latest levels and **day-over-day % change** for major indices and ETFs (^GSPC, ^IXIC, ^VIX, DX-Y.NYB, GLD, SLV) to anchor regime, risk-on/off, and precious-metals proxies. +- **Macro snapshot:** Latest **FRED** monthly series (Fed funds, CPI, unemployment) with **MoM** and **YoY** % changes for inflation and labor momentum. +- **Dual delivery:** One dated Parquet table for quant work; Markdown brief for RAG and a stable `latest_macro_context.md` for agents. + +--- + +## 2. Architecture and strategy workflow + +### High-level flow (architecture) + +1. **Environment setup:** Load API keys (FRED) and build directory hierarchies for logs and data. +2. **Market data extraction (YFinance):** Download the last 5 days of price action for major indices and commodities; compute the most recent daily percentage change. +3. **Economic data extraction (FRED):** Query the Federal Reserve Economic Data API for key monthly indicators. +4. **Statistical enrichment:** + - **Daily change %** for market assets. + - **Month-over-Month (MoM)** and **Year-over-Year (YoY)** changes for economic indicators. +5. **Dual-stream output:** + - **Natural language summary** (Markdown) for immediate LLM context. + - **Structured dataset** (Parquet) for historical analysis and quantitative queries. + +### Implementation steps (scraping and assembly) + +1. **Config:** Resolve `Data/`, `logs/`, `Data/Agent_Context/`; load `.env` and require `FRED_API_KEY`. +2. **Yahoo Finance:** `yf.download` for configured tickers (`period="5d"`, `threads=False`); take last two closes to compute `daily_change_pct`; emit one row per market ticker with `frequency="Daily"`. +3. **FRED:** For each series ID, take latest point and compute MoM (vs prior month) and YoY (vs 12 months prior); `daily_change_pct` is null for macro rows. +4. **Merge:** Concatenate all rows; write Markdown report (daily block + macro block); write Parquet; copy full Markdown to `Data/Agent_Context/latest_macro_context.md`. + +--- + +## 3. Pipeline strategy (inputs, outputs, frequency) + +| Item | Detail | +| :--- | :--- | +| **Inputs** | **Environment:** `FRED_API_KEY` in `.env`. **No local input files.** APIs: Yahoo Finance (`yfinance`), FRED (`fredapi`). | +| **Outputs** | See table below. | +| **Update frequency** | **Every trading day** per `collect_data.py` (06:30). Monday–Friday only (scheduler does not exclude US exchange holidays). | + +### Output paths + +| Artifact | Path | +| :--- | :--- | +| Parquet | `Data/2_Silver_Processed/Macro_History/{YYYY-MM-DD}/macro_snapshot_{YYYY-MM-DD}.parquet` | +| RAG Markdown (dated) | `Data/3_Gold_Semantic/Macro_Narratives/{YYYY-MM-DD}/macro_context_{YYYY-MM-DD}.md` | +| Agent “latest” copy | `Data/Agent_Context/latest_macro_context.md` | +| Log | `logs/{YYYY-MM-DD}/macro_pipeline.log` | + +--- + +## 4. Data shapes and metadata + +### Parquet schema (`macro_snapshot_{date}.parquet`) + +| Field | Description | Type | +| :--- | :--- | :--- | +| `retrieval_date` | The timestamp when the script was executed. | String | +| `observation_date` | The actual date the data point was recorded by the exchange/agency. | String | +| `symbol` | Ticker (e.g., ^GSPC) or Series ID (e.g., CPIAUCSL). | String | +| `asset_class` | Category (Equity Index, Inflation, Labor Market, etc.). | String | +| `value` | The raw price or index level. | Float | +| `unit` | Units of measurement (Points, USD, %, or Index). | String | +| `frequency` | Data update cadence (Daily or Monthly). | String | +| `daily_change_pct` | Day-to-day volatility (Market data only). | Float | +| `mom_change_pct` | Monthly momentum (Macro data only). | Float | +| `yoy_change_pct` | Annualized growth/inflation (Macro data only). | Float | + +**Series coverage (from code):** `^GSPC`, `^IXIC`, `^VIX`, `DX-Y.NYB`, `GLD`, `SLV`; FRED: `FEDFUNDS`, `CPIAUCSL`, `UNRATE`. + +--- + +## 5. Dependencies + +```bash +pip install yfinance pandas fredapi python-dotenv pyarrow +``` diff --git a/docs/Data_source_docs/market_news_data.md b/docs/Data_source_docs/market_news_data.md new file mode 100644 index 0000000..fe159d1 --- /dev/null +++ b/docs/Data_source_docs/market_news_data.md @@ -0,0 +1,122 @@ +# News data and LLM enrichment — `news_scraper.py` + +This documentation details the `news_scraper.py` script, an advanced automated pipeline designed to fetch, parse, and semantically enrich global macro-financial news for vector database (Qdrant) ingestion. + +--- + +## Project purpose + +The pipeline acts as a real-time intelligence gathering engine for a Gold/Silver options trading desk. It aggregates global news from the GDELT project, scrapes the full article text, and utilizes a local Large Language Model (Llama 3) to translate foreign text, filter out noise, and generate quantitative metrics (like sentiment/tone scores and volatility implications) to feed into an AI-driven trading or RAG system. + +--- + +## 1. What this source provides (for downstream analysis) + +- **Topic-bucketed news** (central banks, inflation/employment, yields/USD, geopolitics, precious metals spot, metals derivatives) via **GDELT** queries over the last **48 hours**. +- **Full article text** where scraping succeeds (`newspaper3k`), with **DuckDuckGo → Yahoo Finance** fallback for alternate URLs. +- **LLM-enriched signals** (local **Llama 3** via `ChatOllama`): English title, dense summary, tone score for gold/silver (−5…+5), entities, impacted asset classes, and VIX/volatility implication. + +--- + +## 2. Architecture and strategy workflow + +### High-level flow (architecture) + +1. **Topic definition and querying (ingestion)** + - Predefined boolean search logic for macro drivers (Central Banks, Inflation, Geopolitics) and asset-specific news (Gold/Silver spot and derivatives). + - GDELT 2.0 API for the latest global article metadata over the past 48 hours. + +2. **Resilient scraping and deduplication** + - Dedup via URL slugs and cleaned titles. + - `newspaper3k` for full raw text. + - On failure, DuckDuckGo Search (DDGS) targeting Yahoo Finance for an alternate URL. + +3. **LLM extraction and scoring (enrichment)** + - Local Llama 3 (`ChatOllama`) with a strict zero-temperature quantitative analyst prompt. + - Non-English content translated to English. + - Invalid content filtered (cookie walls, 404s). + - Dense summaries, entities, and market impact metrics extracted. + +4. **Formatting and archival (export)** + - Qdrant-compatible JSON structure. + - Raw data, full-text backups, and vector-ready payloads under daily directories. + +### Implementation steps (scraping strategy) + +1. **Topic loop:** For each entry in `ALL_TOPICS` (macro + asset queries), call GDELT `doc` API (`mode=artlist`, `maxrecords=10`, `sort=DateDesc`). +2. **Dedup:** Signatures from URL slug or cleaned title to avoid duplicate articles. +3. **Raw append:** Write GDELT article JSON lines to Bronze raw file. +4. **Scrape:** For each article, fetch full text; on failure skip (no full-text / Qdrant line). +5. **LLM:** Structured prompt extracts fields; invalid or junk content discarded when parser finds no valid `SUMMARY`. +6. **Export:** Append full-text JSONL and Qdrant JSONL per topic. + +--- + +## 3. Pipeline strategy (inputs, outputs, frequency) + +| Item | Detail | +| :--- | :--- | +| **Inputs** | **Hardcoded queries** in `MACRO_TOPICS` and `ASSET_TOPICS`. **APIs:** GDELT `https://api.gdeltproject.org/api/v2/doc/doc`. **Local:** Ollama `llama3` (default `ChatOllama` endpoint). No JSON config file on disk. | +| **Update frequency** | **Daily** per `collect_data.py` (07:00). | + +### Output paths + +| Stream | Path | +| :--- | :--- | +| Raw GDELT | `Data/1_Bronze_Raw/News_Scrapes/{YYYY-MM-DD}/Raw/raw_gdelt_{topic_name}.jsonl` | +| Full text | `Data/1_Bronze_Raw/News_Scrapes/{YYYY-MM-DD}/Full_text/full_text_{topic_name}.jsonl` | +| Qdrant-ready | `Data/3_Gold_Semantic/News_Qdrant/{YYYY-MM-DD}/qdrant_{topic_name}_processed.jsonl` | +| Logs | `logs/{YYYY-MM-DD}/scraper_{YYYY-MM-DD}.log` | + +**Topic keys (`topic_name`):** `macro_central_banks`, `macro_inflation_employment`, `macro_yields_dollar`, `macro_geopolitics_risk`, `asset_precious_metals_spot`, `asset_metals_derivatives`. + +--- + +## 4. Data shapes and metadata + +### Bronze raw (`raw_gdelt_*.jsonl`) + +Each line is the **JSON object returned by GDELT** for an article (fields such as `url`, `title`, `domain`, `urldatetime` as provided by the API). + +### Full text (`full_text_*.jsonl`) + +| Field | Description | +| :--- | :--- | +| `url` | Article URL | +| `title` | Title from GDELT | +| `publish_date` | From `urldatetime` or fallback ISO time | +| `full_text` | Scraped body text | + +### Qdrant (`qdrant_{topic}_processed.jsonl`) — top-level + +| Field | Description | Type | +| :--- | :--- | :--- | +| `id` | A unique UUID v5 generated deterministically from the article URL. | String | +| `text` | The clean string to be embedded. Format: `"{english_title}. {dense_summary}"`. | String | +| `metadata` | A nested dictionary containing structured tags for Qdrant payload filtering. | Object | + +### `metadata` (complete tags) + +| Key | Description | Type | +| :--- | :--- | :--- | +| `topic` | The internal category that triggered the fetch (e.g., `macro_central_banks`). | String | +| `title` | The English-translated article title. | String | +| `original_title` | The native/original title fetched from GDELT. | String | +| `publish_date` | The ISO-8601 formatted publication timestamp. | String | +| `publish_timestamp` | Integer Unix epoch for fast time-range filtering in the vector DB. | Integer | +| `source` | The domain name of the publisher. | String | +| `url` | Direct link to the source article. | String | +| `entities` | Array of 3-5 explicitly mentioned key entities/organizations. | Array of Strings | +| `impacted_assets` | Broad asset classes affected by the news (e.g., USD, Gold, Equities). | Array of Strings | +| `volatility_implication` | Estimated impact on market fear/VIX (`Increase`, `Decrease`, `Neutral`). | String | +| `llm_tone_score` | Quantitative sentiment score on Gold/Silver from -5 (Bearish) to +5 (Bullish). | Integer | + +--- + +## 5. Dependencies + +```bash +pip install requests newspaper3k duckduckgo-search langchain-ollama +``` + +Also requires a running **Ollama** server with the **`llama3`** model available. diff --git a/docs/Data_source_docs/options_historial_data.md b/docs/Data_source_docs/options_historial_data.md new file mode 100644 index 0000000..9a58141 --- /dev/null +++ b/docs/Data_source_docs/options_historial_data.md @@ -0,0 +1,152 @@ +# Options Market Data — `yfinance_options_history.py` + +## 1. Goal + +Produce a daily, date-partitioned Silver-layer Parquet snapshot of the full options chains for a fixed universe of liquid equity-index and metals ETFs. The snapshot feeds two downstream consumers: + +1. **`SilverSQLTool`** (`Scripts/retrieval/sql_tools.py`) — queried at agent runtime via DuckDB for IV skew, put/call ratio, liquidity analysis, and options pricing spread. +2. **`MasterRetriever` always-on GPR patch** (`Scripts/retrieval/master_retriever.py`) — colocated ingestion ensures the IV-regime classifier always has a same-day anchor. + +--- + +## 2. Architecture + +``` +yfinance API + │ + ▼ +[1] Underlying price fetch (per symbol) + │ + ▼ +[2] Expiration discovery → nearest 10 expirations + │ + ▼ +[3] Call + Put chain extraction (1 s delay between API calls) + │ + ▼ +[4] Vectorised enrichment (pandas) + │ • dte = expiration − snapshot_date + │ • moneyness_pct = |strike − underlying_price| / underlying_price × 100 + │ • spread_pct = (ask − bid) / ask × 100 [0.0 when ask ≤ 0] + │ • is_liquid = volume ≥ 50 AND open_interest ≥ 100 AND bid > 0 + │ + ▼ +[5] Persist → Parquet (date-partitioned, per symbol) +``` + +--- + +## 3. Code Strategy & Workflow + +| Step | Implementation | Notes | +|:---|:---|:---| +| **Path resolution** | `UniverseLoader` (`Scripts/core/universe.py`) provides symbol list and resolves absolute output path via `universe.paths.options_parquet_path(symbol, date)` | Path contract: `Data/2_Silver_Processed/Options_Market_Data/{YYYY-MM-DD}/{SYMBOL}_options_{YYYY-MM-DD}.parquet` | +| **Rate limiting** | `time.sleep(1)` between every `yf.Ticker.option_chain()` call | Prevents Yahoo Finance throttle | +| **Expiration cap** | `[:10]` slice on sorted expiration list | Covers ≈ 7–60 DTE range; further expirations are illiquid | +| **Moneyness filter** | No server-side filter; all strikes retained | SilverSQLTool applies `dte BETWEEN 7 AND 45` and `is_liquid = true` filters at query time | +| **Parquet engine** | `pyarrow` (`df.to_parquet(..., engine="pyarrow")`) | Columnar compression; DuckDB reads natively | +| **Schema validation** | `SilverSQLTool._validate_parquet_contract()` checks required columns on every process startup | Emits `SCHEMA_CHECK` audit line; fails loudly on column drift | + +--- + +## 4. Output Data Schema & Paths + +### Storage Paths + +| Artifact | Path | +|:---|:---| +| **Silver Parquet** | `Data/2_Silver_Processed/Options_Market_Data/{YYYY-MM-DD}/{SYMBOL}_options_{YYYY-MM-DD}.parquet` | +| **DuckDB glob** | `Data/2_Silver_Processed/Options_Market_Data/*/*.parquet` (used by `SilverSQLTool`) | +| **Run log** | `logs/{YYYY-MM-DD}/options_scraper_{YYYY-MM-DD}.log` | + +### Parquet Schema + +| Column | Type | Description | +|:---|:---|:---| +| `snapshot_date` | `string` (ISO date) | Trading day the snapshot was taken | +| `symbol` | `string` | Underlying ETF ticker (SPY, QQQ, IWM, GLD, SLV) | +| `underlying_price` | `float64` | Spot price used for moneyness calculation | +| `contract_symbol` | `string` | OCC-style full contract code | +| `option_type` | `string` | `"call"` or `"put"` | +| `strike` | `float64` | Strike price | +| `expiration` | `string` (ISO date) | Expiration date | +| `dte` | `int64` | Calendar days to expiration at snapshot time | +| `moneyness_pct` | `float64` | `abs(strike − underlying_price) / underlying_price × 100` | +| `last_price` | `float64` | Last traded price | +| `bid` | `float64` | Best bid | +| `ask` | `float64` | Best ask | +| `spread_pct` | `float64` | `(ask − bid) / ask × 100`; `0.0` when `ask ≤ 0` | +| `volume` | `int64` | Daily volume | +| `open_interest` | `int64` | Open interest | +| `implied_volatility` | `float64` | Annualised IV from Yahoo (decimal, e.g. `0.38` = 38%) | +| `in_the_money` | `bool` | Intrinsic value flag from Yahoo | +| `is_liquid` | `bool` | `volume ≥ 50 AND open_interest ≥ 100 AND bid > 0` | + +**Required columns verified at startup by `SilverSQLTool._validate_parquet_contract()`:** +`snapshot_date`, `symbol`, `option_type`, `volume`, `open_interest`, `implied_volatility`, `moneyness_pct`, `spread_pct`, `dte`, `is_liquid`, `contract_symbol` + +### SQL Handlers that consume this schema + +| Handler | Key filters | Output keys | +|:---|:---|:---| +| `_handle_options_analysis` | `is_liquid = true`, `dte BETWEEN 7 AND 45` | `latest_atm_iv`, `{TICKER}_iv_skew_{DTE}d`, `{TICKER}_skew_direction` | +| `_handle_put_call_ratio` | `symbol = ?`, date window | `pcr_volume`, `pcr_open_interest`, `pcr_status` | +| `_handle_liquidity_analysis` | `is_liquid = true` | `total_liquid_calls`, `total_liquid_puts`, `top_volume_strike_call/put` | +| `_handle_pricing_spread` | `is_liquid = true`, `dte BETWEEN 7 AND 45` | `{TICKER}_underlying_price`, `{TICKER}_avg_bid/ask/spread_pct` | + +--- + +## 5. How to Test + +### Schema contract check (runs on every process start) + +```bash +python -c "from Scripts.retrieval.sql_tools import SilverSQLTool; SilverSQLTool()" +# Look for: SCHEMA_CHECK | dataset=options | status=OK +``` + +### Manual single-symbol snapshot + +```bash +python Scripts/data_collection/scrapers/yfinance_options_history.py +# Writes Data/2_Silver_Processed/Options_Market_Data/{today}/{SYMBOL}_options_{today}.parquet +``` + +### DuckDB spot query + +```python +import duckdb +con = duckdb.connect() +df = con.execute(""" + SELECT snapshot_date, symbol, COUNT(*) as contracts, + AVG(implied_volatility) as avg_iv + FROM read_parquet('Data/2_Silver_Processed/Options_Market_Data/*/*.parquet') + WHERE is_liquid = true AND dte BETWEEN 7 AND 45 + GROUP BY 1, 2 ORDER BY 1 DESC, 2 +""").df() +print(df) +``` + +### End-to-end retrieval test + +```bash +python -m Scripts.tests.test_master_retriever +# Test case: "What is the current IV skew for SPY?" +``` + +--- + +## 6. Dependencies + +| Library | Purpose | +|:---|:---| +| `yfinance` | Options chain API | +| `pandas` | Vectorised enrichment | +| `numpy` | Numerical operations | +| `pyarrow` | Parquet serialisation | + +```bash +pip install yfinance pandas numpy pyarrow +``` + +**Runtime prerequisite:** `collect_data_state.json` must have a valid `options_daily` key so `SilverSQLTool._get_anchor_date("options")` returns a current business day. diff --git a/docs/LLM_Pool.md b/docs/LLM_Pool.md new file mode 100644 index 0000000..114b0b5 --- /dev/null +++ b/docs/LLM_Pool.md @@ -0,0 +1,234 @@ +# LLM Pool — Fine-Tuned 70B Warmup, Singleton Cache, Role Tiering + +_Scope: `Scripts/core/llm_pool.py` + CLI `warmup` subcommand_ + +This document specifies the contract the rest of the system uses to +obtain Ollama LLM clients, and the operational runbook for keeping the +fine-tuned 70B model hot in GPU memory across a bot session. + +--- + +## 1. Deployment Reality + +The bot talks to Ollama for **two** distinct model roles — nothing +more. This is the single most important fact about the pool: + +| Tier | Ollama tag | Base | Used by | +| --- | --- | --- | --- | +| **Expert (70B, fine-tuned)** | `options-expert-v1:latest` | `FROM Llama-3.3-70B-Instruct-Q4_K_M.gguf` | `AnalystAgent`, `CheckerAgent`, `CriticAgent`, `FinalizerAgent`, `QueryTransformer` (metadata extractor AND HyDE writer) | +| **Router (8B, vanilla)** | `llama3:latest` | stock Meta Llama-3 | `MasterRetriever.router_llm` (intent routing), ingestion-time `news_scraper` sentiment tagger, `sec_processor` form-parser | + +> The *base model* (`llama3.3:70b`) referenced in `.env` as +> `OLLAMA_BASE_MODEL` is **only** used by +> `Scripts/models/create_options_expert.py` as the `FROM` source when +> rebuilding the fine-tune — it is never served to agents at runtime. + +Retrieval models (`BAAI/bge-base-en-v1.5` dense, `Splade_PP_en_v1` +sparse, `bge-reranker-v2-m3` cross-encoder) are **not** Ollama clients; +they live in `Scripts/vector_store/connection.py` and are documented +in `docs/Query_retrieval_docs/Retrieval_Architecture_and_Strategy.md`. + +--- + +## 2. Why a Pool + +Multiple call-sites across the codebase instantiate `ChatOllama` +independently (Analyst, Checker, Critic, Finalizer, two stages of the +`QueryTransformer`, `MasterRetriever.router_llm`). For an 8B model this +is cheap — the real cost lives inside Ollama, not in the Python client. +For the 70B fine-tune three things break: + +| Failure mode | Consequence without the pool | +| --- | --- | +| **Cold start** | First user query waits 30–60 s while Ollama loads the Q4-quantised 70B into GPU memory. | +| **Idle eviction** | Ollama's default `keep_alive` is 5 min. A three-minute read pause between queries incurs a second cold start. | +| **Model swapping** | If the 70B fine-tune and a secondary model are both served on a single GPU, Ollama may evict the 70B to serve an 8B router call, then reload the 70B on the next Analyst call — double cold-start per revision. | + +The pool solves all three by (a) centralising client construction, +(b) forcing `keep_alive` to `30m` by default, and (c) letting operators +tier models so expert and router roles never fight for the same slot. + +--- + +## 3. Public API + +```python +from Scripts.core import llm_pool + +# Get a cached client for a role (case-insensitive) +llm = llm_pool.get_ollama("analyst") + +# One-shot override (not cached — use sparingly) +ephemeral = llm_pool.get_ollama("analyst", temperature=0.7) + +# Warm specific roles (blocking, returns per-role WarmupResult) +results = llm_pool.warmup_sync(roles=["analyst", "router"]) + +# Fire-and-forget background warmup — good for daemon startup +thread = llm_pool.warmup_async() +``` + +### 3.1 Role Table + +```python +# Scripts/core/llm_pool.py +ROLE_TABLE = { + # Expert tier — all six roles resolve to the same 70B fine-tune, + # so Ollama holds exactly ONE 70B in GPU memory at a time. + "analyst": RoleSpec(... model_env="OLLAMA_CUSTOM_MODEL_NAME", temperature=0.2), + "critic": RoleSpec(... model_env="OLLAMA_CUSTOM_MODEL_NAME", temperature=0.3), + "checker": RoleSpec(... model_env="OLLAMA_CUSTOM_MODEL_NAME", temperature=0.0), + "finalizer": RoleSpec(... model_env="OLLAMA_CUSTOM_MODEL_NAME", temperature=0.2), + "query_extract": RoleSpec(... model_env="OLLAMA_CUSTOM_MODEL_NAME", temperature=0.0, format="json"), + "query_hyde": RoleSpec(... model_env="OLLAMA_CUSTOM_MODEL_NAME", temperature=0.2), + + # Router tier — vanilla Llama-3 8B. Short, cheap, JSON-formatted. + "router": RoleSpec(... model_env="OLLAMA_ROUTER_MODEL", temperature=0.0, format="json"), + + # Ingestion tier — also Llama-3 8B, kept separate so ingestion can + # be rolled to a different quant without touching online routing. + "news_sentiment": RoleSpec(... model_env="OLLAMA_INGESTION_MODEL", temperature=0.0), + "sec_parser": RoleSpec(... model_env="OLLAMA_INGESTION_MODEL", temperature=0.0, format="json"), +} + +DEFAULT_WARMUP_ROLES = ("analyst", "router") +``` + +Why `DEFAULT_WARMUP_ROLES = ("analyst", "router")`? +Warming one role per **tier** is enough — Ollama caches by underlying +model name, not by `ChatOllama` instance. Warming `analyst` pins +`options-expert-v1:latest` for Checker / Critic / Finalizer / +QueryTransformer too; warming `router` pins `llama3:latest` for +ingestion helpers. + +### 3.2 Environment Variables + +| Variable | Default | Effect | +| --- | --- | --- | +| `OLLAMA_BASE_URL` / `OLLAMA_HOST` | `http://localhost:11434` | Passed to every `ChatOllama`. | +| `OLLAMA_KEEP_ALIVE` | `30m` | How long Ollama pins the model after the last request. Use `-1` to never evict. | +| `OLLAMA_CUSTOM_MODEL_NAME` | `options-expert-v1:latest` | Expert-tier model (agents + QueryTransformer). | +| `OLLAMA_ROUTER_MODEL` | `llama3:latest` | Router-tier model (`MasterRetriever.router_llm`). | +| `OLLAMA_INGESTION_MODEL` | falls back to `OLLAMA_ROUTER_MODEL` | Ingestion-time sentiment / SEC parser. | + +> `OLLAMA_BASE_MODEL` (`llama3.3:70b`) is **not** read by the pool — it +> is an artefact used only by `create_options_expert.py` when +> rebuilding the fine-tune from the modelfile. + +--- + +## 4. Warmup Strategies + +### 4.1 Synchronous warmup before serving a query (recommended default) + +```text +$ python -m Scripts query --warmup "yesterday's AAPL IV skew?" +``` + +The CLI invokes `warmup_sync(DEFAULT_WARMUP_ROLES)` before building +the agent graph, so the first agent call lands on an already-hot +model. Cost: one round-trip per role (≈ 30–60 s for a 70B cold-start, +≈ 50 ms once already loaded). + +### 4.2 Background warmup in daemon mode + +```text +$ python -m Scripts daemon --warmup +``` + +The CLI spawns `warmup_async()` in a `daemon=True` thread before +entering the scheduler loop. Ticks run immediately; by the time a +user's first `query` invocation arrives the model is already pinned. + +### 4.3 Standalone warmup (CI / cron prehook) + +```text +$ python -m Scripts warmup --roles analyst finalizer +role status latency model +---------------------------------------- +analyst ok 42.31s options-expert-v1:latest +finalizer ok 0.18s options-expert-v1:latest # reuse — already loaded +``` + +Because both roles map to `OLLAMA_CUSTOM_MODEL_NAME`, warming the +first pins the model for the second. + +### 4.4 Failure semantics + +`warmup_sync` never raises. A timeout or HTTP error becomes a +`WarmupResult(status="failed", error=...)` entry; the CLI logs it but +proceeds — a flaky warmup must never crash the process that was going +to serve queries anyway. + +--- + +## 5. Agent Migration Pattern + +Existing agents construct `ChatOllama` inline: + +```python +# Scripts/agents/analyst.py (current) +from langchain_ollama import ChatOllama + +self.llm = ChatOllama( + model=os.getenv("OLLAMA_CUSTOM_MODEL_NAME", "options-expert-v1"), + temperature=0.2, +) +``` + +Target pattern after migration: + +```python +from Scripts.core.llm_pool import get_ollama + +self.llm = get_ollama("analyst") +``` + +Agents with `with_structured_output(Schema)` should cache the wrapped +object on `self` once per instance — the pool hands back the raw +client; wrapping is a per-call responsibility. + +Migration is **incremental**. The pool is additive — nothing forces +agents to switch in lockstep. Migrate one agent, ship, observe +keep-alive metrics, move to the next. + +--- + +## 6. What the Pool Does *Not* Do + +- It does not load a model at Python import time. That would make + `Scripts.core.llm_pool` unsafe to import in environments without + Ollama running (CI, docs builds, smoke tests). Warmup is an + explicit, opt-in operation. +- It does not pool *requests* — every call is still a fresh HTTP + request to Ollama. What is pooled is the *client object* (session + configuration, default kwargs) so agents stop re-materialising it. +- It does not coordinate concurrent requests to the same model. Two + simultaneous Analyst calls still go through Ollama's own request + queue; the pool's singleton simply makes sure both calls hit the + same `ChatOllama` instance. + +--- + +## 7. Operational Runbook + +| Scenario | Command | +| --- | --- | +| Daemon server reboot — warm before users hit the endpoint | `python -m Scripts warmup --roles analyst router` | +| Ad-hoc backtest at 2 AM — ensure 70B pinned for an hour | `OLLAMA_KEEP_ALIVE=1h python -m Scripts query --warmup "..."` | +| CI smoke test without Ollama | Do *not* call `warmup`; agents that require an LLM will raise a clear `RuntimeError` at first use. | +| Verify which model a role resolves to | `python -c "from Scripts.core import llm_pool; print(llm_pool.get_role_spec('analyst'))"` | +| Rebuild the fine-tune after changing the modelfile | `python Scripts/models/create_options_expert.py` (uses `OLLAMA_BASE_MODEL`) | + +--- + +## 8. Future Work + +- **Per-request timeout/circuit-breaker wrapper** — catches Ollama + hangs without killing the whole agent graph. Candidate home: + `Scripts/core/llm_pool.safe_invoke(role, prompt, timeout_s=60)`. +- **Parallel warmup on multi-GPU** — when two models fit side-by-side + in VRAM, `warmup_sync` could fire concurrent requests. Today it is + serial on purpose (single-GPU machines swap models otherwise). +- **Prometheus exposition** — emit `llm_pool_warmup_latency_seconds` + and `llm_pool_cache_hits_total` for the scheduler / query paths. diff --git a/docs/Observability.md b/docs/Observability.md new file mode 100644 index 0000000..49356a7 --- /dev/null +++ b/docs/Observability.md @@ -0,0 +1,167 @@ +# Observability Layer — Unified Logging and Audit Paths + +_Scope: `Scripts/observability/` + the layout under `logs/`_ + +This document specifies the directory layout for every log produced by +the bot, the helpers that route them, and the migration recipe for +legacy loggers. + +--- + +## 1. Problem Statement + +Before this layer was introduced the project wrote logs into a zoo of +top-level folders: + +``` +logs/ +├── retrieval/{date}/ +├── query_transform/{date}/ +├── router_e2e/{date}/ +├── Parquet_Query/{date}/ +├── scheduler/ +├── test/ +└── ... +``` + +Investigating a single production incident meant stitching together +four or five timestamp-matched files by hand. Each module hand-built +its date-partitioned path, which drifted whenever a timezone or daily +boundary shifted. + +The remedy: one well-known tree per *orchestrator invocation*, one +helper function that every producer uses. + +--- + +## 2. Target Layout + +``` +logs/ +├── runs/ ← canonical, run-scoped +│ └── {YYYY-MM-DD}/ +│ └── {run_id}/ ← one folder per CLI invocation +│ ├── orchestrator.log # root logger +│ ├── retrieval/ +│ │ ├── retrieval.jsonl +│ │ └── retriever_audit_trail.jsonl +│ ├── query_transform/ +│ │ └── query_audit_trail.jsonl +│ ├── router_e2e/ +│ │ └── ... +│ └── sql_range/ +│ └── audit.jsonl +│ +├── scheduler/ ← legacy daemon, back-compat +│ └── collect_data.log +│ +├── retrieval/{YYYY-MM-DD}/… ← legacy flat, still readable +├── query_transform/{YYYY-MM-DD}/… +└── router_e2e/{YYYY-MM-DD}/… +``` + +- `run_id` format: `{YYYYMMDD}_{HHMMSS}_{tag}_{uuid6}`. + Example: `20260422_153042_query_ab12cd`. +- The legacy flat layout still works — `audit_path(..., scoped_by_run=False)` + returns a path under `logs/{module}/{date}/` so offline tools that + consumed the old layout continue to function during the migration. + +--- + +## 3. Public API + +```python +from Scripts.observability import ( + configure_root_logger, # once at CLI / daemon boot + start_run, # once per invocation + current_run_id, # read-only helper + audit_path, # compute a log file path + get_audit_logger, # returns a logger pointed at audit_path +) +``` + +### 3.1 `configure_root_logger(level="INFO", also_to_file=True)` + +- Installs a stdout handler and (optionally) a file handler at + `logs/runs/{today}/{run_id}/orchestrator.log`. +- Idempotent: replaces previously attached handlers so pytest / + Jupyter do not double-print. +- Called by `Scripts.orchestration.cli.main()` on every invocation. + +### 3.2 `start_run(tag="session")` + `current_run_id()` + +- `start_run` mints a new `run_id` and stores it in a `ContextVar`. +- `current_run_id` returns the active id, auto-starting an "adhoc" + run if the caller forgot to initialise one (useful in notebooks). + +### 3.3 `audit_path(module, anchor=None, filename=None, scoped_by_run=True)` + +| Argument | Purpose | +| --- | --- | +| `module` | Logical module name — `"retrieval" / "query_transform" / "router_e2e" / "sql_range"`. Becomes both a folder name *and* the default filename stem. | +| `anchor` | The **data** date this log pertains to (default `date.today()`). Use the agent's `time_range.anchor_date` for determinism — this keeps backfill audits in the correct folder. | +| `filename` | Override the default `.jsonl` leaf. Useful for existing consumers that already expect names like `retriever_audit_trail.jsonl`. | +| `scoped_by_run` | `True` ⇒ `logs/runs/{date}/{run_id}/{module}/`; `False` ⇒ `logs/{module}/{date}/`. | + +Side-effect: the parent folder is created. + +### 3.4 `get_audit_logger(name, module, anchor=None, level="INFO")` + +Returns a `logging.Logger` with a single file handler attached at +`audit_path(module, anchor, filename=f"{name}.log")`. Safe to call +repeatedly — duplicate handlers are de-duplicated. + +```python +from Scripts.observability import get_audit_logger + +log = get_audit_logger("QdrantRetriever", module="retrieval") +log.info("search filter=%s", filt) +``` + +--- + +## 4. Migration Recipe for Legacy Loggers + +Most existing modules currently hand-build log paths: + +```python +log_path = Path("logs/retrieval") / date.today().isoformat() / "retriever_audit_trail.jsonl" +log_path.parent.mkdir(parents=True, exist_ok=True) +``` + +Replace with a single call: + +```python +from Scripts.observability import audit_path + +log_path = audit_path( + module="retrieval", + anchor=state["time_range"]["anchor_date"], # deterministic anchor + filename="retriever_audit_trail.jsonl", +) +``` + +Migration can happen one module at a time. Both layouts coexist until +you flip `scoped_by_run` defaults for that consumer. + +--- + +## 5. Scheduler / Daemon Logs + +`Scripts/data_collection/collect_data.py::configure_logging` still +writes to `logs/scheduler/collect_data.log`. When you switch to the +new CLI daemon (`python -m Scripts daemon`), logs flow through +`configure_root_logger` into `logs/runs/{today}/{run_id}/orchestrator.log` +instead. Both paths are supported indefinitely. + +--- + +## 6. Retention Guidance + +- `logs/runs/` grows one folder per invocation. On a machine that runs + the daemon continuously, retention is measured in daemon restarts — + for each daemon lifetime there is one `orchestrator.log`. +- Keep at least the last 7 calendar days of `logs/runs/{date}` for + post-mortem analysis. +- Archive older `runs/` to cold storage via a nightly cron — no module + depends on logs older than the current day. diff --git a/docs/Orchestration.md b/docs/Orchestration.md new file mode 100644 index 0000000..51dad3b --- /dev/null +++ b/docs/Orchestration.md @@ -0,0 +1,328 @@ +# Orchestration Layer — Pipeline DAG, Runtime State, CLI + +_Scope: `Scripts/orchestration/` + `config/runtime/collect_data_state.json`_ + +This document is a deep-dive companion to +[ARCHITECTURE.md §2.2 and §3](./ARCHITECTURE.md#22-scriptsorchestration--pipeline--cli). +It specifies the contracts the orchestration layer offers to the rest +of the system, the DAG produced by `build_default_pipeline()`, and the +institutional runbook for each CLI subcommand. + +--- + +## 1. Design Principles + +1. **Single source of truth for time.** Every module that needs to + reason about "yesterday", "this week", or "latest partition" reads + from one file: `config/runtime/collect_data_state.json`. The only + writer is the orchestration `Pipeline`. Agents never compute time + anchors from wall-clock directly. +2. **Idempotency by cadence key.** Jobs are keyed by a `run_key` — + `2026-04-21` for daily, `2026-W16` for weekly, `2026-04` for + monthly. A job whose stored key matches the key we would compute + now is *skipped*; no wasted API calls, no duplicate writes. +3. **Atomic state transitions.** The JSON state is written via + `tempfile + os.replace` — a Ctrl+C during a scheduler tick cannot + corrupt the file that agents depend on. +4. **Declarative DAG.** Stages declare `depends_on`; the runner + topologically sorts, detects cycles at build time, and short- + circuits downstream work when a critical upstream fails. +5. **Zero-migration adapter for legacy scripts.** Every existing + scraper under `Scripts/data_collection/scrapers/` runs untouched + via `ScriptStage(subprocess.run)`. New stages can opt into the + faster in-process `CallableStage`. + +--- + +## 2. The Production DAG + +`Scripts/orchestration/pipeline.build_default_pipeline()` assembles six +stages mirroring the reality of the data sources: + +```mermaid +flowchart LR + gpr_monthly + macro_trading_daily + news_daily + options_daily + sec_ingestion_weekly --> sec_processor_weekly +``` + +The four roots (GPR / macro / news / options) are independent — they +hit different external endpoints. Only the SEC processor has an +upstream dependency because it parses Bronze artefacts the ingestion +job just wrote. + +| Stage | Cadence | Timeout | Critical | Purpose | +| --- | --- | --- | --- | --- | +| `gpr_monthly` | MONTHLY | 30 min | yes | Geopolitical Risk index | +| `macro_trading_daily` | TRADING_DAILY | 30 min | yes | FRED + yfinance macro snapshot | +| `news_daily` | DAILY | 30 min | yes | GDELT + Llama 3 sentiment enrichment | +| `options_daily` | DAILY | 30 min | yes | yfinance option chains for 5+48 tickers | +| `sec_ingestion_weekly` | WEEKLY | 45 min | yes | Pull raw SEC filings | +| `sec_processor_weekly` | WEEKLY | 45 min | yes | LLM-parse SEC filings into Silver | + +> **Cadence ≠ tier.** "Weekly" describes *when* the stage should run, +> not whether the pipeline should fail if it errors. Criticality is a +> separate field (`Stage.critical`) — all stages default to `True` in +> production today. Dropping a non-critical stage to `False` is a +> one-line change when you're comfortable with the source being flaky. + +--- + +## 3. RunState — the Time-Anchor Contract + +### 3.1 On-disk schema + +```json +{ + "last_run_keys": { + "options_daily": "2026-04-21", + "macro_trading_daily": "2026-04-21", + "news_daily": "2026-04-21", + "gpr_monthly": "2026-04", + "sec_ingestion_weekly": "2026-W16", + "sec_processor_weekly": "2026-W16" + }, + "updated_at": "2026-04-22T15:09:02" +} +``` + +### 3.2 Public API + +```python +from Scripts.orchestration import Cadence, RunState, get_run_state + +rs = get_run_state() # process-wide singleton + +# Pipeline-side (writer) +rs.mark_job_complete("options_daily", Cadence.DAILY) # atomic write +rs.is_up_to_date("options_daily", Cadence.DAILY) # idempotency check + +# Agent-side (reader) +rs.latest_anchor_date("options") # -> date(2026,4,21) +rs.latest_anchor_for_granularity("weekly") # -> date(2026,4,13) +rs.snapshot() # full diagnostic dict +``` + +### 3.3 Dataset → Anchor-Key Mapping + +Agents speak in logical dataset names; `RunState` translates to the +concrete `last_run_keys` field. Extend this table alongside the +scraper's `build_jobs()`: + +| `dataset` (argument) | `last_run_keys` field | Typical agent site | +| --- | --- | --- | +| `options` | `options_daily` | `SilverSQLTool._get_anchor_date("options")`, `time_adapter.build_anchor("daily")` | +| `macro` | `macro_trading_daily` | Macro snapshot + `time_adapter` DAILY | +| `news` | `news_daily` | `time_adapter` EVENT | +| `gpr` | `gpr_monthly` | `time_adapter` MONTHLY | +| `sec` | `sec_processor_weekly` | `time_adapter` WEEKLY (downstream-visible) | +| `sec_raw` | `sec_ingestion_weekly` | SEC raw-JSONL retrieval only | + +### 3.4 Fault Tolerance + +| Failure mode | Behaviour | +| --- | --- | +| State file missing | `latest_anchor_date()` returns `fallback` (default `date.today()`). Agents still serve queries. | +| State file corrupt JSON | Same as missing — `RunState._load` catches `json.JSONDecodeError`. | +| Scheduler Ctrl+C mid-write | `os.replace()` atomicity: the previous valid file is still on disk; the tmp file is garbage-collected. | +| Weekend-anchored daily key | `time_adapter` snaps to previous business day via `Scripts.core.trading_calendar.previous_business_day`. | + +--- + +## 4. Stage Contract + +### 4.1 Base class + +```python +class Stage(ABC): + name: str + cadence: Cadence + depends_on: Tuple[str, ...] = () + critical: bool = True + timeout_s: int = 60 * 30 + max_retries: int = 2 + retry_backoff_s: int = 10 + + @abstractmethod + def _execute(self, when: datetime) -> Tuple[str, str]: ... + + def is_up_to_date(self, run_state: RunState, when: datetime) -> bool: ... + def run(self, run_state: RunState, *, force: bool, dry_run: bool) -> StageResult: ... +``` + +### 4.2 Two concrete adapters + +| Adapter | When to use | +| --- | --- | +| `ScriptStage` | Existing scraper scripts under `Scripts/data_collection/`. Spawns `subprocess.run(python script.py)`. Zero migration cost, survives independent invocation. | +| `CallableStage` | New in-process stages (e.g. an embedding re-indexer that reuses the caller's Qdrant client). Avoids subprocess startup; receives `datetime` and returns a metrics dict that is stored on `StageResult.metrics`. | + +### 4.3 Retry + failure semantics + +- Each stage retries up to `max_retries + 1` times with linear backoff + (`min(60, 10 × attempt) seconds`). +- On final failure `StageResult.status = "failed"`; only *critical* + failures abort downstream dependents. +- `Pipeline.run_once` always returns the full `List[StageResult]`, + never raises. Callers inspect `r.ok` to decide exit codes. + +--- + +## 5. Pipeline Runner + +```python +from Scripts.orchestration import Pipeline, build_default_pipeline + +pipe = build_default_pipeline() +results = pipe.run_once( + only=["sec_processor_weekly"], # auto-includes upstream deps + force=False, + dry_run=False, + when=None, # defaults to datetime.now() +) +``` + +### 5.1 `run_once` algorithm + +```mermaid +flowchart TD + A["resolve_targets
expand only with upstream deps"] --> B{"next stage in
topo order?"} + B -- "no" --> Z["return List[StageResult]"] + B -- "yes" --> C{"upstream in
failed set?"} + C -- "yes" --> D["append
StageResult(status=skipped)"] + D --> E["add name to
failed set"] + E --> B + C -- "no" --> F["stage.run(when, force, dry_run)"] + F --> G["append StageResult(ok / error)"] + G --> H{"ok?"} + H -- "yes" --> B + H -- "no" --> I{"stage.critical?"} + I -- "no" --> B + I -- "yes" --> J["add name to
failed set"] + J --> B +``` + +Key guarantees of the algorithm: + +- **Topological order is fixed**, so a stage never runs before its upstream. +- **Skips are recorded**, never silently dropped — every skipped stage + still emits a `StageResult` for auditing. +- **Non-critical failures do not poison downstream**: only stages flagged + `critical=True` propagate through the `failed` set. +- **Idempotency is delegated** to each `Stage.is_up_to_date(run_state)`; + the runner does not re-implement cadence logic. + +### 5.2 `run_forever` + +Identical per-tick logic, sleeps `poll_seconds` between ticks. Shares +the state file with any concurrent CLI `ingest` invocation — writes go +through the same `RunState` handle so no tick ever re-runs a job the +CLI has already completed. + +--- + +## 6. CLI Runbook + +```text +python -m Scripts [--log-level DEBUG|INFO|WARNING|ERROR] +``` + +| Subcommand | Purpose | +| --- | --- | +| `ingest` | Run all due stages once (idempotent). | +| `daemon` | Long-lived scheduler (replaces legacy `collect_data.py run_forever`). | +| `status` | Print `last_run_keys` and derived agent-side anchors. | +| `query` | One-shot RAG question through the multi-agent graph. | +| `warmup` | Pre-load Ollama models. | + +### 6.1 `ingest` flags + +| Flag | Semantics | +| --- | --- | +| `--only STAGE [STAGE ...]` | Run only these (upstream deps auto-included). Unknown names exit 2. | +| `--force` | Ignore `is_up_to_date` — re-runs even if today's key already matches. Useful for backfills and QA. | +| `--dry-run` | Log what *would* execute without spawning subprocesses. | + +### 6.2 Example session + +```powershell +# Quick freshness check before asking a question +PS> python -m Scripts status +state_path: C:\...\config\runtime\collect_data_state.json +updated_at: 2026-04-22T15:09:02 + +last_run_keys: + gpr_monthly 2026-04 + macro_trading_daily 2026-04-21 + news_daily 2026-04-21 + options_daily 2026-04-21 + sec_ingestion_weekly 2026-W16 + sec_processor_weekly 2026-W16 + +anchors (agent-side time anchors): + options 2026-04-21 + macro 2026-04-21 + news 2026-04-21 + gpr 2026-04-01 + sec 2026-04-13 + sec_raw 2026-04-13 + +# Bring today's data up-to-date +PS> python -m Scripts ingest + +# Force-reprocess SEC filings (re-runs sec_ingestion_weekly too) +PS> python -m Scripts ingest --only sec_processor_weekly --force + +# Serve queries +PS> python -m Scripts query --warmup "yesterday's AAPL IV skew?" +``` + +--- + +## 7. Extending the Pipeline + +To add a new scraper (`Scripts/data_collection/scrapers/my_scraper.py`): + +1. Choose a cadence and a unique `run_key` field name (e.g. `my_source_daily`). +2. Register it in `Scripts/orchestration/pipeline.py::build_default_pipeline()`: + + ```python + ScriptStage( + name="my_source_daily", + script_path=scrapers / "my_scraper.py", + cadence=Cadence.DAILY, + depends_on=(), # or (upstream_job_name,) + critical=True, + project_root=root, + ), + ``` + +3. If agents need to read the freshness, add the mapping in + `Scripts/orchestration/run_state.DATASET_ANCHOR_KEYS`: + + ```python + DATASET_ANCHOR_KEYS["my_source"] = "my_source_daily" + ``` + +4. No other code changes. `RunState.snapshot()` and `python -m Scripts status` + automatically surface the new job. + +--- + +## 8. Backwards Compatibility + +`Scripts/data_collection/collect_data.py` continues to run as a +standalone daemon (`python Scripts/data_collection/collect_data.py`). +Its internal `StateStore` now delegates to `RunState`, so the old +daemon and the new CLI see the same state file and cannot double-run +a job. + +Migration path for operators: + +1. **Today**: keep running `collect_data.py`; start using `python -m Scripts status` and `ingest` interactively. +2. **Sprint n+1**: switch the cron to `python -m Scripts daemon --poll-seconds 30`. +3. **Sprint n+2**: delete legacy subprocess wrappers elsewhere (none known as of 2026-04-22). + +No data migration is required — the on-disk state schema is unchanged. diff --git a/docs/PRODUCTION_OPS_NOTES.md b/docs/PRODUCTION_OPS_NOTES.md deleted file mode 100644 index ecfe69d..0000000 --- a/docs/PRODUCTION_OPS_NOTES.md +++ /dev/null @@ -1,69 +0,0 @@ -### \#\# Example Run: Daily Report Generation - -This example documents a typical daily production run, demonstrating the flow from data ingestion to final report generation. - - * **Inputs** - - * **Knowledge Base:** Qdrant vector collection `financial_signals`. - * **LLM Endpoint:** `http://ollama_llm_prod:11434` serving the `options-expert` model. - * **Execution Date:** 2025-10-06 - - * **Execution Command** - - ```bash - docker exec financial_agent_app_prod python src/tools/generate_production_report.py - ``` - - * **Log Highlights & Process Flow** - - 1. **Data Ingestion & Vectorization:** The pipeline initiated scrapers for all configured sources (YouTube, News, Reddit, FRED, SEC). It successfully fetched **68 relevant signals** related to market sentiment and specific tickers. - * For YouTube and Yahoo Finance videos where transcripts were unavailable, the system correctly created **fallback documents** (title + description + URL), ensuring no contextual data was lost. - 2. **Multi-Agent Analysis:** The core agent system was triggered. - * The **Analyst agent** queried the Qdrant collection, retrieving contextually relevant signals and synthesizing an initial list of **8 candidate ideas**. - * The **Checker agent** cross-referenced facts, and the **Critic agent** challenged underlying assumptions, filtering out weak or unsupported theses. - 3. **Finalization & Enrichment:** The system deduplicated the validated ideas by ticker and strategy, resulting in **5 final, high-conviction recommendations**. - * Tickers included in the final report were **GS, MS, BAC, BA, and UPS**. - * The `yfinance_client` was used to enrich each idea with real-time strike prices, expiration dates, and liquidity data. - - * **Outputs** - The final reports were successfully saved to the target directory: - - * **JSON:** `reports/2025-10-06/options_ideas.json` - - * **Markdown:** `reports/2025-10-06/options_ideas.md` - - * **Example Markdown Output Snippet:** - - ```markdown - ### Goldman Sachs (GS) - Bullish Call Spread - * **Ticker:** GS - * **View:** Bullish - * **Strategy:** Vertical Call Spread - * **Candidate:** Buy GS OCT 410C / Sell GS OCT 420C - * **Rationale:** Recent positive analyst commentary and sector-wide strength in investment banking suggest short-term upside. A spread strategy is chosen to cap cost basis given recent market volatility. - * **Confidence:** Medium - ``` - ------ - -### \#\# “What Else I Found”: High-Signal Sources & Their Utility - -* **SEC Insider Trading Filings (e.g., Form 4)** - * **Signal:** Provides strong, direct evidence of corporate insider conviction. Large open-market buys or sells are unambiguous directional cues that can precede significant price movements. - * **Utility:** Excellent for identifying high-conviction directional bias (bullish/bearish) on specific stocks and for validating theses generated from other, noisier sources. - -* **FRED Macroeconomic Data** - * **Signal:** Offers a clear view of the macroeconomic regime (e.g., inflationary, recessionary, high/low interest rates). Key series like `VIX`, `FEDFUNDS`, and `CPI` are critical inputs. - * **Utility:** Informs high-level strategy selection. For example, a high VIX reading (high implied volatility) suggests that selling options premium (e.g., credit spreads) may be more advantageous than buying it. - -* **News (NewsAPI) & Social Media (YouTube/Reddit)** - * **Signal:** Captures real-time sentiment, emerging narratives, and timely, event-driven catalysts that quantitative models might miss. - * **Utility:** Acts as the primary source for identifying *why* a stock might be moving. While these signals can be noisy and require validation, they are invaluable for understanding the story behind the numbers. - -* **Corporate Disclosures (Earnings Calendars & Investor Relations Feeds)** - * **Signal:** Provides scheduled, high-impact event catalysts. Earnings announcements are predictable drivers of significant volatility. - * **Utility:** Essential for planning event-driven trades (e.g., straddles, strangles) around earnings releases to capitalize on the expected increase in implied volatility. - -* **Market Data (Options Chains via `yfinance`)** - * **Signal:** Delivers the "ground truth" of the options market, including pricing, liquidity (Open Interest and Volume), and implied volatility across different strikes and expirations. - * **Utility:** Critical for the final step of trade construction. It is used to sanity-check an idea for feasibility, select liquid and reasonably priced strikes, and ensure the trade is practical to execute. \ No newline at end of file diff --git a/docs/Query_retrieval_docs/Qdrant_retriever_docs.md b/docs/Query_retrieval_docs/Qdrant_retriever_docs.md new file mode 100644 index 0000000..0cc3ca8 --- /dev/null +++ b/docs/Query_retrieval_docs/Qdrant_retriever_docs.md @@ -0,0 +1,185 @@ +# Gold-Layer Asymmetric Hybrid Retriever + +_Scope: `Scripts/retrieval/qdrant_retriever.py`._ + +This document specifies the Gold-layer retrieval engine that turns a `FullTransformationResult` into a ranked list of `RetrievedChunk`s. + +--- + +## 1. Strategic Objective + +Bridge the LLM's transformation payload (HyDE + metadata) and Qdrant +Cloud with three guarantees: + +- **Temporal alignment** — all filters are built from `TimePredicate` objects produced upstream by `time_adapter`, not from wall-clock time. One anchor, one window, all sources. +- **Lexical precision** — SPLADE sparse retrieval against the raw query (or `rerank_query`) preserves rare tickers and acronyms that dense embeddings blur. +- **Post-fusion sharpness** — a cross-encoder reranker rescues the handful of true positives that RRF mixes with noise. + +--- + +## 2. System Architecture + +| Layer | Implementation | +| --- | --- | +| **Singleton resources** | `_instance` pattern caches Qdrant client + embedding models per process. | +| **Asymmetric vectorisation** | Dense ← `hyde_paragraph`, Sparse ← `rerank_query` (or raw query). | +| **Source-aware time filter** | Per-source `TimePredicate` → OR-joined `unified_timestamp` / `publish_timestamp` range conditions. | +| **Defensive filtering** | `models.Filter` pre-filter (ticker, source_type, action, form, sentiment). | +| **RRF fusion** | `Fusion.RRF` combines dense + sparse prefetch channels. | +| **Cross-encoder rerank** | `CrossEncoder(BAAI/bge-reranker-v2-m3)` rescores top-K. | + +--- + +## 3. Execution Workflow + +```text +[ FullTransformationResult + raw query + time_predicates ] + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ Step 1 — Deterministic Filter Construction │ +│ ├─► ticker match (models.FieldCondition) │ +│ ├─► source_type match (drops Silver-only source_types) │ +│ ├─► action_direction (SEC) │ +│ ├─► form_type (SEC) │ +│ ├─► sentiment range (news) │ +│ └─► per-source time OR (unified_timestamp OR publish_ts) │ +└─────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ Step 2 — Asymmetric Vectorisation │ +│ ├─► Dense : HuggingFace `BAAI/bge-base-en-v1.5` │ +│ │ (hyde_paragraph → dense vector) │ +│ └─► Sparse: fastembed `Splade_PP_en_v1` │ +│ (rerank_query → sparse vector) │ +└─────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ Step 3 — Qdrant Prefetch + Fusion.RRF │ +│ using="dense" prefetch + filter │ +│ using="sparse" prefetch + filter │ +│ → RRF(fusion=RRF) top_k_pool candidates │ +└─────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ Step 4 — Cross-Encoder Rerank │ +│ CrossEncoder(BAAI/bge-reranker-v2-m3) │ +│ pairwise score([rerank_query, candidate_text]) → top_k │ +│ drop score ≤ 1e-5 │ +└─────────────────────────────────────────────────────────────┘ + │ + ▼ +[ List[RetrievedChunk] ] + └─► audit → logs/retrieval//retriever_audit_trail.jsonl +``` + +--- + +## 4. Temporal Alignment Contract + +`retrieve_async` accepts an explicit +`time_predicates: Dict[SourceTimeKey, TimePredicate]` argument. If present it is used directly; if absent the retriever falls back to the single `time_window` value inside `FullTransformationResult`. + +Two non-negotiable rules: + +1. **OR over `unified_timestamp` and `publish_timestamp`.** Some collections only populate one of the two keys; the retriever must accept a hit on either. Without this, SEC/News filings written by the legacy ingestor are invisible. +2. **Business-day snapping.** Daily-grain predicates (for `source_type=options`) are computed by `trading_calendar.py` so that `"yesterday"` on a Monday resolves to the previous Friday — not an empty Sunday. + +> **Ops note on Qdrant indexing.** `publish_timestamp` must be indexed on the collection, otherwise Qdrant raises +> `400 Index required but not found for "publish_timestamp"`. This is a one-time schema fix on the Qdrant side; see +> `Scripts/vector_store/ingestion.py` for the canonical index payload. + +--- + +## 5. Output Schema — `RetrievedChunk` + +| Field | Type | Source | Purpose | +| :--- | :--- | :--- | :--- | +| `chunk_id` | String | Qdrant `id` | Unique UUID — traceability. | +| `text` | String | Qdrant payload | Actual news / SEC / macro text. | +| `score` | Float | RRF + rerank | Post-rerank relevance. | +| `source_type` | String | Qdrant payload | `sec` / `news` / `macro` / `gpr`. | +| `timestamp` | Integer | `unified_timestamp` or `publish_timestamp` | Unix epoch. | +| `bronze_ref` | String | payload | Accession / URL / UUID fallback. | +| `metadata` | Dict | payload | Tickers, impacted_assets, form_type, tone_score, … | + +--- + +## 6. Example Audit Entry + +```json +{ + "timestamp": "2026-04-19T21:16:01.849708", + "original_query": "What recent insider buying activity has there been for TSLA and how did the market react?", + "rerank_query_used": "TSLA Form 4 insider buying executives past month", + "filter_applied": { + "must": [ + {"key": "ticker", "match": {"any": ["TSLA"]}}, + {"key": "source_type", "match": {"any": ["sec", "news"]}}, + {"key": "action_direction", "match": {"any": ["BUY", "ACQUIRE/VEST"]}}, + {"key": "form_type", "match": {"value": "4"}}, + { + "should": [ + {"key": "unified_timestamp", "range": {"gte": 1774055761.0, "lte": 1776647761.0}}, + {"key": "publish_timestamp", "range": {"gte": 1774055761.0, "lte": 1776647761.0}} + ] + } + ] + }, + "fallback_triggered": false, + "results_count": 1, + "top_k_scores": [0.0145], + "latency_sec": 0.857, + "status": "SUCCESS" +} +``` + +--- + +## 7. Reliability Controls + +| Control | Mechanism | +| --- | --- | +| Singleton resources | `__new__` + `@lru_cache` keeps heavy models loaded once per process. | +| Connection resilience | Qdrant client opens with `prefer_grpc=False`, `timeout=15s`, `retries=3 × 2s`. | +| Graceful failure | Any exception in `retrieve_async` logs a `FAILED` audit row and returns `[]` — agents never observe a crash. | +| Fallback tiers | `drop_ticker_180d` widens the window and drops the ticker filter when the first pass returns 0 chunks. | + +--- + +## 8. Verification + +```bash +python Scripts/retrieval/qdrant_retriever.py +pytest -xvs Scripts/tests/test_master_retriever.py +pytest -xvs Scripts/tests/test_router_e2e.py +``` + +Expected console shape: + +1. `🔍 Stage 2: Qdrant Hybrid Retrieving...` +2. `✅ Final Retrieved: N chunks` followed by enumerated scores. + +--- + +## 9. Environment Dependencies + +```bash +pip install qdrant-client fastembed sentence-transformers python-dotenv asyncio +``` + +| Variable | Default | Effect | +| --- | --- | --- | +| `EMBEDDING_MODEL_NAME` | `BAAI/bge-base-en-v1.5` | Dense encoder | +| `EMBEDDING_DEVICE` | `cpu` | Dense encoder placement | +| `SPARSE_MODEL_NAME` | `prithivida/Splade_PP_en_v1` | Sparse encoder | +| `FASTEMBED_THREADS` | `6` | Sparse encoder threads | +| `RERANKER_MODEL_NAME` | `BAAI/bge-reranker-v2-m3` | Cross-encoder | +| `RETRIEVER_DEVICE` | `cpu` | Cross-encoder placement | +| `QDRANT_HOST` / `QDRANT_API_KEY` | required | Qdrant Cloud credentials | + +_Depends on `Scripts.vector_store.connection` (clients) and +`Scripts.retrieval.schema` (Pydantic contracts)._ diff --git a/docs/Query_retrieval_docs/Query_intent_docs.md b/docs/Query_retrieval_docs/Query_intent_docs.md new file mode 100644 index 0000000..acd8143 --- /dev/null +++ b/docs/Query_retrieval_docs/Query_intent_docs.md @@ -0,0 +1,200 @@ +# Query Intent & Transformation Layer + +_Scope: `Scripts/retrieval/query_transform.py` + +`Scripts/retrieval/master_retriever.py::router_llm`._ + +This document defines **how a raw user question becomes a pair of +deterministic structured artefacts** (routing decision + transformation +payload) that the rest of the retrieval pipeline treats as a hard +contract. + +--- + +## 1. Strategic Objective + +The intent layer is the **policy gate** of the retrieval subsystem. It +converts ambiguous natural language into: + +1. a **route** (Gold-only, Silver-only, or hybrid), and +2. a **structured extraction** (tickers, metrics, time window, action + direction) plus a HyDE expansion used for dense retrieval. + +Without this layer, downstream retrievers would have to parse the +query themselves — a recipe for drift, duplicated logic, and +non-deterministic behaviour across agents. + +--- + +## 2. Two Cooperating Sub-Components + +| Sub-component | File | Model | Purpose | +| --- | --- | --- | --- | +| **Intent Router** | `master_retriever.py::MasterRetriever.router_llm` | `llama3:latest` (env `OLLAMA_ROUTER_MODEL`) | Pick `gold_only` / `silver_only` / `hybrid_both`. Short JSON output. | +| **Query Transformer** | `query_transform.py::QueryTransformer` | `options-expert-v1:latest` (env `OLLAMA_CUSTOM_MODEL_NAME`) | Two-stage metadata extraction + HyDE generation. | + +> **Model rationale.** The router only classifies into three buckets — +> using the fine-tuned 70B here would burn 30–60 s per query for no +> accuracy gain. The transformer, in contrast, has to reason about +> options terminology, SEC form types, macro indicators, etc., so it +> runs on the fine-tuned model. See `docs/LLM_Pool.md` §1 for the full +> model inventory. + +--- + +## 3. Execution Workflow + +```text +[ Raw User Query ] + │ + ▼ +┌─────────────────────────────────────────────────────┐ +│ 3.1 MasterRetriever.router_llm (llama3:latest) │ +│ → QueryIntent(primary_route=...) │ +└─────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────┐ +│ 3.2 QueryTransformer.transform_for_dual_rag │ +│ (options-expert-v1:latest, 70B, 2 stages) │ +│ │ +│ Stage 1 — EXTRACTOR │ +│ ├─► Ontology-constrained metadata │ +│ ├─► Ticker whitelist guardrail │ +│ └─► TimeWindow enum normalization │ +│ │ +│ Stage 2 — HyDE │ +│ ├─► hyde_paragraph (dense channel) │ +│ └─► rerank_query (sparse + rerank channel) │ +└─────────────────────────────────────────────────────┘ + │ + ▼ +[ FullTransformationResult + QueryIntent ] + │ + ▼ + handed to QdrantRetriever / SilverSQLTool +``` + +--- + +## 4. Time Anchoring Contract + +The transformer emits a `TimeWindow` enum (`yesterday`, `past_week`, +`past_month`, …). These enum values are **not interpreted here** — +they are resolved downstream by `Scripts/retrieval/time_adapter.py` +against a fixed anchor: + +- The anchor is **always** `RunState.latest_business_day("options")`, + read from `config/runtime/collect_data_state.json`. It is *never* + `datetime.now()`. +- `time_adapter.compile_all` returns a `Dict[SourceTimeKey, + TimePredicate]` — one window per data source (SEC, options, macro, + news). Each source may have different business-day semantics. +- The resulting predicates are serialised into `AgentState` so that + re-queries from `CheckerAgent._rescue_missing_anchors` use the same + window as the initial retrieval. This eliminates the `latest_atm_iv` + oscillation observed in the 2026-04-22 router_e2e logs. + +See `docs/Query_retrieval_docs/Time_Schema_Audit.md` for the full +time-schema matrix. + +--- + +## 5. Output Schema — `FullTransformationResult` + +| Component | Field | Type | Purpose | +| :--- | :--- | :--- | :--- | +| **Metadata** | `logical_reasoning` | String | Stage-1 CoT; audit-only. | +| **Metadata** | `tickers` | List[str] | Guardrail-cleaned tickers. | +| **Metadata** | `metrics` | List[str] | Canonical metric names from `financial_ontology.ALLOWED_METRICS`. | +| **Metadata** | `source_types` | List[str] | `sec` / `news` / `options` / `macro`. | +| **Metadata** | `action_direction` | Enum | `BUY` / `SELL` / `NEUTRAL` / `ANY`. | +| **Metadata** | `form_type` | Enum | `4`, `8-K`, `13F`, `ANY`. | +| **Metadata** | `sentiment_target` | Enum | `POSITIVE` / `NEGATIVE` / `ANY`. | +| **Metadata** | `event_keyword` | String | Short lexical hook for SPLADE. | +| **Metadata** | `time_window` | Enum | Raw token — resolved downstream. | +| **HyDE** | `hyde_paragraph` | String | Semantic carrier for dense retrieval. | +| **HyDE** | `rerank_query` | String | Factual short phrase for sparse + rerank. | +| **Mapped** | `mapped_physical_columns` | List[str] | Derived via `METRIC_TO_COLUMN_MAPPING`. | + +--- + +## 6. Example Output + +```json +{ + "timestamp": "2026-04-19T21:16:00.977910", + "latency_seconds": 107.96, + "original_query": "What recent insider buying activity has there been for TSLA and how did the market react?", + "primary_route": "hybrid_both", + "transformation_result": { + "metadata": { + "logical_reasoning": "Macro Step: Insider activity. Meso: Market reaction. Micro: TSLA insiders. Action: BUY.", + "tickers": ["TSLA"], + "metrics": ["Insider Trading", "Price Change (%)"], + "source_types": ["sec", "news"], + "action_direction": "BUY", + "form_type": "4", + "sentiment_target": "ANY", + "event_keyword": "insider_buying", + "time_window": "past_month" + }, + "hyde": { + "hyde_paragraph": "TSLA insiders have recently filed Form 4s indicating buying activity...", + "rerank_query": "TSLA Form 4 insider buying executives past month" + }, + "mapped_physical_columns": ["mom_change_pct", "insider_net_flow", "daily_change_pct"] + } +} +``` + +--- + +## 7. Reliability Controls + +- **Ontology-locked output.** Every free-form LLM field is post-checked + against `financial_ontology`. Unknown tickers are dropped, not + silently persisted. +- **Ticker-explosion guardrail.** Queries that extract more than 8 + tickers are truncated to the top 5 to keep Qdrant filters tractable. +- **Audit trail.** Every transformation is appended to + `logs/query_transform//query_audit_trail.jsonl` with the raw + query, mapped columns, chosen route, and latency. +- **Failure semantics.** Either stage may raise — the upstream caller + (`MasterRetriever.retrieve`) converts exceptions into a degraded + route (`silver_only` with empty metadata) rather than bubbling up + and killing the agent graph. + +--- + +## 8. Verification + +```bash +# Exercise the transformer alone (no Qdrant required) +python Scripts/retrieval/query_transform.py + +# Exercise the full MasterRetriever (router + transform + retrieval) +pytest -xvs Scripts/tests/test_master_retriever.py +pytest -xvs Scripts/tests/test_router_e2e.py +``` + +Expected STDOUT shape for `query_transform.py`: + +1. `[STAGE 1]` — reasoning, tickers, metrics, time window. +2. `[STAGE 2]` — HyDE paragraph + rerank query. +3. Final JSON serialisation suitable for pasting into issue reports. + +--- + +## 9. Environment Dependencies + +```bash +pip install langchain-core langchain-ollama pydantic python-dotenv +``` + +Required env entries (all present in the standard `.env`): + +| Variable | Default | Purpose | +| --- | --- | --- | +| `OLLAMA_CUSTOM_MODEL_NAME` | `options-expert-v1:latest` | Transformer (both stages) | +| `OLLAMA_ROUTER_MODEL` | `llama3:latest` | Intent router in `MasterRetriever` | +| `OLLAMA_HOST` | `http://localhost:11434` | Ollama endpoint | diff --git a/docs/Query_retrieval_docs/Retrieval_Architecture_and_Strategy.md b/docs/Query_retrieval_docs/Retrieval_Architecture_and_Strategy.md new file mode 100644 index 0000000..6ccc800 --- /dev/null +++ b/docs/Query_retrieval_docs/Retrieval_Architecture_and_Strategy.md @@ -0,0 +1,270 @@ +# Retrieval Architecture, Strategy, and Workflow + +_This document is the authoritative spec of the retrieval subsystem — +how raw user questions become ranked evidence that the agent graph +consumes. It supersedes all prior retrieval READMEs._ + +--- + +## I. Mission Profile and System Boundary + +The retrieval subsystem is implemented across: + +- `Scripts/core/financial_ontology.py` +- `Scripts/core/intent_router_prompt_templates.py` +- `Scripts/core/prompt_templates.py` +- `Scripts/core/few_shot_intent.py` / `few_shot_config.py` +- `Scripts/core/trading_calendar.py` +- `Scripts/retrieval/schema.py` +- `Scripts/retrieval/query_transform.py` +- `Scripts/retrieval/time_adapter.py` +- `Scripts/retrieval/master_retriever.py` +- `Scripts/retrieval/qdrant_retriever.py` +- `Scripts/retrieval/sql_tools.py` +- `Scripts/vector_store/connection.py` + +It is a **two-stage transformation pipeline** followed by a +**dual-track retrieval-and-merge pipeline** (Gold semantic + Silver +structured), all anchored on a single `RunState`-owned business-day +timestamp. + +--- + +## II. Institutional-Grade Architectural Topology + +### A. Knowledge Governance Layer (`Scripts/core`) + +- **Ontology governance** (`financial_ontology.py`) + - Controlled vocabularies: `ALLOWED_SOURCES`, `ALLOWED_CATEGORIES`, + `ALLOWED_METRICS`. + - Deterministic metric→physical-column map + (`METRIC_TO_COLUMN_MAPPING`). + - Prevents free-form extraction drift. +- **Prompt governance** (`prompt_templates.py`, + `intent_router_prompt_templates.py`) + - Stage 1 extractor prompt, Stage 2 HyDE prompt, and the cheap + intent-router prompt used by `MasterRetriever.router_llm`. +- **Few-shot calibration** (`few_shot_intent.py`) + - Injects examples for SEC, macro/news, options-style queries. +- **Trading calendar** (`trading_calendar.py`) + - Dependency-free business-day arithmetic (`previous_business_day`, + `n_business_days_back`, `clamp_to_business_day`). + +### B. Contract and Type-Safety Layer (`Scripts/retrieval/schema.py`) + +Pydantic models serve as hard contracts: + +- `MetadataExtraction` +- `HyDEGeneration` +- `FullTransformationResult` +- `RetrievedChunk` +- `QueryIntent` +- `SourceCitation` +- Enums for `TimeWindow`, `SourceType`, `ActionDirection`, `FormType`, + `SentimentTarget`. + +### C. Intent Routing Layer (`Scripts/retrieval/master_retriever.py::router_llm`) + +- Cheap vanilla `llama3:latest` decides `gold_only` / `silver_only` / + `hybrid_both`. See `docs/LLM_Pool.md` for the two-tier model + rationale. + +### D. Transformation Intelligence Layer (`Scripts/retrieval/query_transform.py`) + +- Two-stage asynchronous LLM transformation on the fine-tuned 70B: + 1. **Extractor** (`OLLAMA_CUSTOM_MODEL_NAME`, `format=json`) + 2. **HyDE writer** (`OLLAMA_CUSTOM_MODEL_NAME`, higher temp) +- Post-LLM guardrails: ticker whitelist, ontology mapping, audit JSONL. + +### E. Time Alignment Layer (`Scripts/retrieval/time_adapter.py`) + +Single source of truth for retrieval time windows. + +- `compile_all(time_window, anchor_date)` → + `Dict[SourceTimeKey, TimePredicate]` — one window *per data source* + (`SEC`, `OPTIONS`, `NEWS`, `MACRO`). +- Daily-grain sources are **business-day-aware** via + `trading_calendar`. `"yesterday"` on a Monday resolves to Friday. +- `TimePredicate` is **serialisable** — it is persisted in + `AgentState["time_range"]["source_predicates"]` so that the + `CheckerAgent` rescue step re-queries Silver with the same window + as the initial retrieval. This fixes the `latest_atm_iv` oscillation + diagnosed in `docs/test/2026-04-22/router_e2e_deep_analysis.md`. + +### F. Retrieval Execution Layer + +Two coordinated retrievers, both orchestrated by `MasterRetriever`: + +- `qdrant_retriever.py::FinancialHybridRetriever` — Gold semantic + (Dense + Sparse + Rerank). +- `sql_tools.py::SilverSQLTool` — Silver structured (Parquet + metric + dispatcher; consumes the same `TimePredicate` objects). + +### G. Infrastructure Layer (`Scripts/vector_store/connection.py`) + +- Cached singletons for Qdrant client and embedding model. +- `prefer_grpc=False` for firewall resilience. +- All credentials loaded from `.env`. + +--- + +## III. Retrieval Strategy Blueprint + +### A. Asymmetric Hybrid — Why Two Texts Feed Two Channels + +| Channel | Input | Model | Rationale | +| --- | --- | --- | --- | +| Dense | `hyde_paragraph` (long, synthetic) | `BAAI/bge-base-en-v1.5` | Captures abstract semantic intent ("flight to safety", "IV crush"). | +| Sparse | `rerank_query` (short, factual) | `prithivida/Splade_PP_en_v1` | Enforces exact lexical match for tickers and form types. | + +### B. Deterministic Pre-Filtering + +`_build_smart_filter` narrows search space *before* vector math: + +- `ticker`, `source_type` (with Silver-only types stripped) +- SEC: `action_direction`, `form_type` +- News: `tone_score > 0` / `< 0` +- Time: OR over `unified_timestamp` **and** `publish_timestamp`, + bounded by the per-source `TimePredicate`. + +### C. Post-Fusion Precision + +After `Fusion.RRF` merges dense and sparse prefetch pools, +`BAAI/bge-reranker-v2-m3` rescores top-K. Chunks with score ≤ 1e-5 are +dropped. + +### D. Macro as a First-Class Silver Anchor + +`latest_macro_context.md` (written by the macro pipeline) is parsed +in `master_retriever.py::_parse_macro_snapshot` and folded into +`silver_context` as `MACRO_*` anchors. This closes the "macro citation +trap" where the Analyst cited unattributable macro values. + +--- + +## IV. End-to-End Workflow (Execution Graph) + +```text +[ User Query ] + │ + ▼ +[ MasterRetriever.router_llm (llama3:latest) ] ← route decision + │ + ▼ +[ QueryTransformer (options-expert-v1:latest, 70B) ] ← 2-stage transform + │ ─ EXTRACT (JSON) + │ ─ HyDE + ▼ +[ time_adapter.compile_all(anchor_date from RunState) ] ← per-source windows + │ + ├──────────────┬─────────────────────────────────────┐ + ▼ ▼ ▼ +[ Gold ] [ Silver SQL ] [ Macro snapshot ] +FinancialHybrid sql_tools.SilverSQLTool parse latest_macro_context.md + Retriever ├─ handler dispatcher (metrics) → MACRO_* anchors + ├─ Dense ├─ metadata windowed Parquet │ + ├─ Sparse └─ anchors[] │ + ├─ RRF fuse │ + ├─ Rerank │ + └─ drop score ≤ 1e-5 │ + │ │ + └──────────────┬──────────────────────────────┘ + ▼ + [ MasterRetriever merges → MasterRetrievalResult ] + │ + ▼ + LangGraph Agents (Router → Analyst → Checker → Finalizer) +``` + +--- + +## V. Model Registry + +This section mirrors `docs/ARCHITECTURE.md` §5. Treat that document as +canonical; this table is here for reader convenience. + +### A. Ollama LLMs + +| Role | Model | Env | Notes | +| --- | --- | --- | --- | +| Intent router | `llama3:latest` | `OLLAMA_ROUTER_MODEL` | `MasterRetriever.router_llm`. Small JSON output. | +| Metadata extractor | `options-expert-v1:latest` | `OLLAMA_CUSTOM_MODEL_NAME` | `QueryTransformer` Stage 1. Fine-tuned Llama-3.3-70B-Q4. | +| HyDE writer | `options-expert-v1:latest` | `OLLAMA_CUSTOM_MODEL_NAME` | `QueryTransformer` Stage 2. | + +### B. Retrieval models (not Ollama) + +| Purpose | Artefact | Env | Device | +| --- | --- | --- | --- | +| Dense encoder | `BAAI/bge-base-en-v1.5` | `EMBEDDING_MODEL_NAME` | `EMBEDDING_DEVICE` (default `cpu`) | +| Sparse (SPLADE) | `prithivida/Splade_PP_en_v1` | `SPARSE_MODEL_NAME` | CPU, `FASTEMBED_THREADS` | +| Cross-encoder reranker | `BAAI/bge-reranker-v2-m3` | `RERANKER_MODEL_NAME` | `RETRIEVER_DEVICE` | + +### C. Data plane + +- Vector DB: **Qdrant Cloud** (`QDRANT_HOST`, `QDRANT_API_KEY`) +- Connection: HTTP/HTTPS, `timeout=15s`, `retries=3 × 2s`. + +--- + +## VI. Runtime Configuration Matrix (`.env`) + +| Key | Default | Function | +| --- | --- | --- | +| `QDRANT_HOST` | required | Qdrant Cloud endpoint | +| `QDRANT_API_KEY` | required | Qdrant authentication | +| `EMBEDDING_MODEL_NAME` | `BAAI/bge-base-en-v1.5` | Dense encoder | +| `EMBEDDING_DEVICE` | `cpu` | Dense encoder device | +| `SPARSE_MODEL_NAME` | `prithivida/Splade_PP_en_v1` | Sparse encoder | +| `FASTEMBED_THREADS` | `6` | Sparse encoder threads | +| `RERANKER_MODEL_NAME` | `BAAI/bge-reranker-v2-m3` | Cross-encoder | +| `RETRIEVER_DEVICE` | `cpu` | Cross-encoder device | +| `OLLAMA_HOST` | `http://localhost:11434` | Ollama endpoint | +| `OLLAMA_CUSTOM_MODEL_NAME` | `options-expert-v1:latest` | Query transform + all agents | +| `OLLAMA_ROUTER_MODEL` | `llama3:latest` | `MasterRetriever` router | + +--- + +## VII. Reliability and Auditability Controls + +- **Singleton caching** — `@lru_cache` for embeddings, `__new__` for + retriever, `llm_pool` for Ollama clients. +- **Transformation audit** — `logs/query_transform//query_audit_trail.jsonl` +- **Retrieval audit** — `logs/retrieval//retriever_audit_trail.jsonl` +- **SilverSQL audit** — `logs/Parquet_Query//*` via the + `SilverSQLAudit` logger. +- **Graceful failure** — any retriever that raises returns `[]` + + logged diagnostics; agents never observe an exception. +- **Time determinism** — `TimePredicate`s serialised into `AgentState` + guarantee that Checker rescue re-queries use an identical window to + the original retrieval. + +--- + +## VIII. Practical Invocation Sequence + +```python +# Orchestrator-level flow (simplified) +from Scripts.retrieval.master_retriever import MasterRetriever + +retriever = MasterRetriever() +result = await retriever.retrieve_async( + raw_query="What is AAPL's IV skew yesterday and are insiders active?", +) +# result.gold_context — List[RetrievedChunk] +# result.silver_context — List[AnchorRecord] (including MACRO_* anchors) +# result.time_range — {anchor_date, source_predicates: [...]} +``` + +`result` is the canonical input for `Scripts.agents.router.router_node`. + +--- + +## IX. Change Log + +| Date | Change | Rationale | +| --- | --- | --- | +| 2026-04-22 | `time_adapter.TimePredicate` serialised into `AgentState` | Eliminates `latest_atm_iv` oscillation across Checker rescue. | +| 2026-04-22 | Macro snapshot parsed into first-class Silver anchors | Closes the macro citation trap. | +| 2026-04-22 | Dual time-key OR (`unified_timestamp` OR `publish_timestamp`) | Makes legacy SEC/news filings discoverable. | +| 2026-04-22 | `MasterRetriever.router_llm` env renamed to `OLLAMA_ROUTER_MODEL` | Separates router tier from expert tier per `docs/LLM_Pool.md`. | +| 2026-04-22 | Business-day snapping for daily-grain predicates | `"yesterday"` on a Monday → previous Friday. | diff --git a/docs/Query_retrieval_docs/Silver_SQL_Tools.md b/docs/Query_retrieval_docs/Silver_SQL_Tools.md new file mode 100644 index 0000000..2311201 --- /dev/null +++ b/docs/Query_retrieval_docs/Silver_SQL_Tools.md @@ -0,0 +1,209 @@ +# Silver SQL Tool — `sql_tools.py` + +## 1. Goal + +`SilverSQLTool` is the institutional-grade DuckDB interface for the Silver layer. It translates LLM-extracted `MetadataExtraction` objects (tickers + metrics + time window) into parameterised SQL queries across three physical Parquet datasets — Options, Macro, and GPR — and returns structured `{values, lineage_anchors}` payloads that the Analyst agent can cite with full data lineage. + +--- + +## 2. Architecture + +``` +MetadataExtraction + TimePredicate set + │ + ▼ + query_parquet_by_metadata() + │ + ├─ Ticker cap guard (max 5 tickers, env: SILVER_MAX_TICKERS) + ├─ Fuzzy metric → canonical key (difflib, ontology whitelist) + │ + ▼ for each ticker × each canonical metric: + metric_dispatcher[canonical_key](ticker, metadata) + │ + ├─► _handle_options_analysis → Options_Market_Data parquet + ├─► _handle_put_call_ratio → Options_Market_Data parquet + ├─► _handle_liquidity_analysis → Options_Market_Data parquet + ├─► _handle_pricing_spread → Options_Market_Data parquet + ├─► _handle_macro_analysis → Macro_History parquet + ├─► _handle_geopolitical_analysis → GPR_index parquet + │ + ▼ + Aggregate: {values: {...}, lineage_anchors: [...]} + │ + ▼ + Structured audit log → logs/Parquet_Query/{YYYY-MM-DD}/sql_retrieval_audit.log +``` + +--- + +## 3. Code Strategy & Workflow + +### 3.1 Initialisation Sequence + +``` +SilverSQLTool.__init__() + │ + ├─ Path resolution + │ options_glob = Data/2_Silver_Processed/Options_Market_Data/*/*.parquet + │ macro_glob = Data/2_Silver_Processed/Macro_History/*/*.parquet + │ gpr_path = Data/2_Silver_Processed/GPR_index/*.parquet + │ + ├─ Runtime state load → config/runtime/collect_data_state.json + │ Populates _get_anchor_date("options" | "macro" | "gpr" | "news") + │ + ├─ Audit logger setup → logs/Parquet_Query/{YYYY-MM-DD}/sql_retrieval_audit.log + │ + ├─ DuckDB in-memory connection + │ SET threads = 4; SET memory_limit = '2GB'; + │ + └─ _validate_parquet_contract() + For each dataset: resolve glob → confirm ≥1 file → DuckDB DESCRIBE + → assert required columns present → emit SCHEMA_CHECK audit line +``` + +### 3.2 Dynamic Time Anchor + +`_get_anchor_date(dataset)` reads `collect_data_state.json` and returns the last successfully ingested date. This replaces `CURRENT_DATE` everywhere so backfills, weekends, and holidays are handled correctly. + +| Dataset | State key | Anchor fallback | +|:---|:---|:---| +| Options | `options_daily` | `date.today()` | +| Macro | `macro_trading_daily` | `date.today()` | +| GPR | `gpr_monthly` | first of current month | + +### 3.3 Metric Dispatch & Fuzzy Matching + +When `query_parquet_by_metadata` receives a metric string from the LLM (e.g. `"IV"`, `"implied vol"`), it calls `_fuzzy_match_metric()`: + +1. Exact match against `metric_dispatcher` keys → use directly. +2. `difflib.get_close_matches(metric, dispatcher_keys, n=1, cutoff=0.6)` → use best match, log `FUZZY_MATCH` event. +3. No match → log `UNAUTHORIZED_METRIC`, skip. + +### 3.4 Per-Source Time Alignment + +When `MasterRetriever` supplies a `time_predicates` dict (compiled by `time_adapter.compile_all`), each handler reads its source's `TimePredicate` via `_predicate_for(SourceTimeKey.SILVER_*)`. This ensures the SQL `WHERE` clause uses exactly the same (start_date, end_date) window that was logged in the time-range audit — eliminating the 3d-vs-2d drift that produced inconsistent PCR / IV-skew windows on the same report. + +### 3.5 Handler Reference + +| Handler | Parquet | Key SQL Logic | Output Keys | +|:---|:---|:---|:---| +| `_handle_options_analysis` | Options | ATM IV from nearest-to-ATM liquid calls; skew from OTM puts; `dte BETWEEN 7 AND 45`, `is_liquid = true`, `mode = latest_only` | `latest_atm_iv`, `{T}_iv_skew_{D}d`, `{T}_skew_direction` | +| `_handle_put_call_ratio` | Options | Aggregate `put/call` volume + OI by snapshot date, window or latest | `pcr_volume`, `pcr_open_interest`, `pcr_status` | +| `_handle_liquidity_analysis` | Options | Count liquid call/put contracts; top volume strike | `total_liquid_calls`, `total_liquid_puts`, `top_volume_strike_call/put` | +| `_handle_pricing_spread` | Options | AVG bid/ask/spread for liquid, near-term options | `{T}_underlying_price`, `{T}_avg_bid`, `{T}_avg_ask`, `{T}_avg_spread_pct` | +| `_handle_macro_analysis` | Macro | Latest value + change for a given symbol (ETF→index alias applied) | `{T}_last_value`, `{T}_mom_change` or `{T}_daily_change` | +| `_handle_geopolitical_analysis` | GPR | Latest monthly GPR level, percentile, trend | `gpr_index_level`, `gpr_percentile`, `gpr_trend` | + +**ETF → Macro alias:** `SPY → ^GSPC`, `QQQ → ^IXIC`, `IWM → ^RUT`, etc. (defined in `Scripts/core/financial_ontology.py::ETF_TO_MACRO_ALIAS`). Applied only in `_handle_macro_analysis`. + +--- + +## 4. Output Data Schema + +### Return Payload + +```python +{ + "values": { + "latest_atm_iv": 0.384, + "AAPL_iv_skew_30d": -0.04, + "AAPL_skew_direction": "put_skew", + "pcr_volume": 1.23, + "gpr_index_level": 148.2, + "gpr_percentile": "72%", + ... + }, + "lineage_anchors": [ + "IV_AAPL_2026-04-22", + "GPR_202604", + "MACRO_VIX_2026-04-22", + ... + ] +} +``` + +### Lineage Anchor Naming Convention + +| Source | Format | Example | +|:---|:---|:---| +| Options IV/skew | `IV_{TICKER}_{date}` | `IV_AAPL_2026-04-22` | +| Options PCR | `PCR_{TICKER}_{date}` | `PCR_SPY_2026-04-22` | +| Options liquidity | `LIQ_{TICKER}_{date}` | `LIQ_SPY_2026-04-22` | +| Options pricing | `PX_{TICKER}_{date}` | `PX_SPY_2026-04-22` | +| Macro series | `MACRO_{TICKER}[_AS_{ALIAS}]_{date}` | `MACRO_SPY_AS_GSPC_2026-04-22` | +| GPR | `GPR_{YYYYMM}` | `GPR_202604` | + +### Audit Log Structure + +File: `logs/Parquet_Query/{YYYY-MM-DD}/sql_retrieval_audit.log` + +``` +SCHEMA_CHECK | dataset=options | glob=... | files=108 | columns=18 | missing=[] | status=OK +START_QUERY | Tickers: ['AAPL'] | Requested: ['Implied Volatility (IV)', 'IV Skew'] +SQL_RANGE | handler=options_analysis | ticker=AAPL | mode=latest_only | time_window=yesterday | ... +FINISH_QUERY | Latency: 0.071s | Anchors_Found: 4 +UNAUTHORIZED_METRIC: Insider Trading +FUZZY_MATCH | 'implied vol' -> 'Implied Volatility (IV)' +``` + +--- + +## 5. How to Test + +### Contract validation (startup) + +```bash +python -c "from Scripts.retrieval.sql_tools import SilverSQLTool; t = SilverSQLTool(); print('OK')" +# Expected: three SCHEMA_CHECK | status=OK lines in audit log +``` + +### Direct handler call + +```python +import asyncio +from Scripts.retrieval.sql_tools import SilverSQLTool +from Scripts.retrieval.schema import MetadataExtraction, TimeWindow + +tool = SilverSQLTool() +meta = MetadataExtraction( + tickers=["AAPL"], + metrics=["Implied Volatility (IV)", "IV Skew"], + time_window=TimeWindow.YESTERDAY, +) +result = asyncio.run(tool.query_parquet_by_metadata(meta)) +print(result["values"]) +print(result["lineage_anchors"]) +``` + +### Master Retriever integration test + +```bash +python -m Scripts.tests.test_master_retriever +# Runs all retriever test cases including sql_only route +``` + +### Audit log inspection + +```bash +cat logs/Parquet_Query/$(date +%Y-%m-%d)/sql_retrieval_audit.log +``` + +--- + +## 6. Dependencies + +| Library | Purpose | +|:---|:---| +| `duckdb` | In-memory SQL engine for Parquet queries | +| `python-dotenv` | `.env` loading for `DATA_LAKE_ROOT` | +| `pydantic` | `MetadataExtraction` contract validation | + +```bash +pip install duckdb python-dotenv pydantic +``` + +**Internal dependencies:** +- `Scripts/core/financial_ontology.py` — `ALLOWED_METRICS`, `METRIC_TO_COLUMN_MAPPING`, `ETF_TO_MACRO_ALIAS` +- `Scripts/retrieval/schema.py` — `MetadataExtraction`, `TimeWindow`, `time_window_to_days` +- `Scripts/retrieval/time_adapter.py` — `SourceTimeKey`, `TimePredicate` +- `config/runtime/collect_data_state.json` — dynamic anchor dates diff --git a/docs/Query_retrieval_docs/Time_Adapter.md b/docs/Query_retrieval_docs/Time_Adapter.md new file mode 100644 index 0000000..a7d1a2f --- /dev/null +++ b/docs/Query_retrieval_docs/Time_Adapter.md @@ -0,0 +1,256 @@ +# Time Alignment Adapter — `time_adapter.py` + +## 1. Goal + +`time_adapter.py` is the single location where a semantic `TimeWindow` from the LLM (e.g. `"yesterday"`, `"past_week"`, `"past_month"`) is compiled into physically-executable time predicates that each data source can actually apply. It eliminates per-handler date arithmetic scattered across the codebase and guarantees that every retriever — Gold (Qdrant) and Silver (DuckDB) — applies the same window for the same source type. + +**Core problem solved:** different sources have fundamentally different temporal granularities. A naive uniform `(start_ts, end_ts)` filter causes: +- `"yesterday"` against a MONTHLY source (GPR) → 0 rows (correct answer is the current month's row) +- `"yesterday"` on a Monday against a DAILY source (Options) → 0 rows (last trading day was Friday) +- SEC event-level sources returning 0 because legacy payloads only carry ISO-8601 strings, not Unix epoch integers + +The adapter pre-compiles per-source widening so every downstream retriever receives semantically correct, physically valid windows without branching logic. + +--- + +## 2. Architecture + +``` +TimeWindow (semantic, from LLM) + anchor date (from SilverSQLTool._get_anchor_date) + │ + ▼ + compile_all(time_window, anchor, label) + │ + ├─ compile_predicate(time_window, GOLD_NEWS, anchor) + ├─ compile_predicate(time_window, GOLD_SEC, anchor) + ├─ compile_predicate(time_window, GOLD_GPR, anchor) + ├─ compile_predicate(time_window, SILVER_OPTIONS, anchor) + ├─ compile_predicate(time_window, SILVER_MACRO, anchor) + └─ compile_predicate(time_window, SILVER_GPR, anchor) + │ + ▼ per source: + SOURCE_SPECS[source] → granularity + min_lookback_days + │ + ▼ + Apply widening policy + │ EVENT → no widening; use raw window_days + │ DAILY → business-day safe: if label in {"today","yesterday"}, step back to prev_business_day + │ apply min_lookback_days floor (3d) for weekend gaps + │ MONTHLY → widen to first-of-month (GPR); apply 35-day floor + │ + ▼ + TimePredicate(source, label, start_date, end_date, + start_epoch_s, end_epoch_s, window_days, + widened, widen_reason, time_keys, key_units) + │ + ▼ + Dict[SourceTimeKey, TimePredicate] → MasterRetriever + (also serialised to state["time_range"]["source_predicates"]) +``` + +--- + +## 3. Code Strategy & Workflow + +### 3.1 Source Registry (`SOURCE_SPECS`) + +Every data source is described by a `SourceTimeSpec` dataclass: + +| Source Key | Granularity | Physical Time Keys | Key Units | Min Lookback | +|:---|:---|:---|:---|:---| +| `gold.news` | EVENT | `unified_timestamp`, `publish_timestamp` | `epoch_s`, `epoch_s` | 1 day | +| `gold.sec` | EVENT | `unified_timestamp`, `filed_at`, `transaction_date` | `epoch_s`, `iso_datetime`, `iso_date` | 3 days | +| `gold.gpr` | MONTHLY | `unified_timestamp`, `publish_timestamp` | `epoch_s`, `epoch_s` | 35 days | +| `silver.options` | DAILY | `snapshot_date` | `iso_date` | 3 days | +| `silver.macro` | DAILY | `observation_date`, `retrieval_date` | `iso_date`, `iso_date` | 3 days | +| `silver.gpr` | MONTHLY | `date`, `month` | `ts_ns`, `ts_ns` | 35 days | + +### 3.2 Widening Policy by Granularity + +``` +EVENT granularity + → use raw window_days from semantic TimeWindow + → min floor = max(min_lookback_days, window_days) + → [SEC special] if window_days < 3 → widen to 3d (event_min_3d) + +DAILY granularity + → if label in {"today", "yesterday"}: + end = anchor (or previous_business_day(anchor) if anchor is not a business day) + today -> start = end + yesterday -> start = previous_business_day(end) + reason = "daily_today_busday (...)" / "daily_yesterday_busday (...)" + → else: use raw window_days with min floor = 3d + +MONTHLY granularity + → if window_days < 35: + start = first_of_month(anchor) + reason = "monthly_widen_to_d" # N is computed from anchor day + → this guarantees monthly rows are query-visible for short semantic windows +``` + +### 3.3 `TimePredicate` — the Compiled Artefact + +`TimePredicate` is a frozen dataclass. Once compiled, it is never re-derived. Retrievers consume it directly: + +- **Qdrant Range filter:** use `start_epoch_s` / `end_epoch_s` for numeric `Range` payload filter +- **DuckDB WHERE clause:** use `start_date` / `end_date` as ISO strings in `BETWEEN` filter + +### 3.4 Serialisation & Round-Trip + +`TimePredicate.to_dict()` produces a JSON-safe dict stored in `state["time_range"]["source_predicates"]`. `TimePredicate.from_dict()` / `predicates_from_serialised()` reconstruct exact live objects — this is the mechanism that allows the Checker's rescue path to reuse the exact same window as the initial retrieval, eliminating the 3d/2d drift documented in `docs/test/2026-04-22/router_e2e_deep_analysis.md`. + +--- + +## 4. Output Data Schema + +### `TimePredicate` Fields + +| Field | Type | Description | +|:---|:---|:---| +| `source` | `SourceTimeKey` | Logical source identifier | +| `label` | `str` | Human-readable semantic label (e.g. `"yesterday"`) | +| `granularity` | `TimeGranularity` | `event`, `daily`, or `monthly` | +| `start_date` | `date` | Physical start of the window | +| `end_date` | `date` | Physical end of the window (anchor) | +| `start_epoch_s` | `int` | Unix seconds (UTC midnight of start_date) | +| `end_epoch_s` | `int` | Unix seconds (23:59:59 UTC of end_date, end-inclusive) | +| `window_days` | `int` | `(end_date − start_date).days` | +| `widened` | `bool` | True if the semantic window was widened for source alignment | +| `widen_reason` | `str \| None` | E.g. `"daily_yesterday_busday (...)"`, `"monthly_widen_to_22d (...)"`, `"event_min_3d (...)"` | +| `time_keys` | `tuple[str, ...]` | Physical key names to build filters on (copied from `SourceTimeSpec`) | +| `key_units` | `tuple[str, ...]` | Physical type for each key (`epoch_s`, `iso_date`, `ts_ns`, …) | + +### Serialised Form in `state["time_range"]` + +```json +{ + "time_window_label": "yesterday", + "window_days": 1, + "anchor_date": "2026-04-22", + "start_date": "2026-04-21", + "end_date": "2026-04-22", + "is_default_window_applied": false, + "source_predicates": { + "gold.sec": { + "source": "gold.sec", + "label": "yesterday", + "granularity": "event", + "start_date": "2026-04-20", + "end_date": "2026-04-23", + "start_epoch_s": 1745107200, + "end_epoch_s": 1745452799, + "window_days": 3, + "widened": true, + "widen_reason": "event_min_3d", + "time_keys": ["unified_timestamp", "filed_at", "transaction_date"], + "key_units": ["epoch_s", "iso_datetime", "iso_date"] + }, + "silver.options": { + "source": "silver.options", + "label": "yesterday", + "granularity": "daily", + "start_date": "2026-04-22", + "end_date": "2026-04-22", + "window_days": 1, + "widened": true, + "widen_reason": "daily_yesterday_busday", + "time_keys": ["snapshot_date"], + "key_units": ["iso_date"] + }, + "silver.gpr": { + "source": "silver.gpr", + "label": "yesterday", + "granularity": "monthly", + "start_date": "2026-04-01", + "end_date": "2026-04-22", + "window_days": 22, + "widened": true, + "widen_reason": "monthly_widen_to_22d" + } + } +} +``` + +### Audit Log Lines (emitted by `MasterRetriever`) + +``` +🕒 [TimeAdapter] gold.sec: widened → 2026-04-20..2026-04-23 (3d) | reason=event_min_3d +🕒 [TimeAdapter] silver.options: widened → 2026-04-22..2026-04-23 (1d) | reason=daily_yesterday_busday +🕒 [TimeAdapter] silver.gpr: widened → 2026-04-01..2026-04-23 (22d) | reason=monthly_widen_to_22d (base=2d < min=35d) +``` + +--- + +## 5. How to Test + +### Compile a single predicate + +```python +from datetime import date +from Scripts.retrieval.time_adapter import compile_predicate, SourceTimeKey +from Scripts.retrieval.schema import TimeWindow + +pred = compile_predicate(TimeWindow.YESTERDAY, SourceTimeKey.SILVER_OPTIONS, anchor=date(2026, 4, 23)) +print(pred.start_date, pred.end_date, pred.widened, pred.widen_reason) +# → 2026-04-22 2026-04-22 True daily_yesterday_busday +``` + +### Compile full predicate set + +```python +from datetime import date +from Scripts.retrieval.time_adapter import compile_all, SourceTimeKey +from Scripts.retrieval.schema import TimeWindow + +preds = compile_all(TimeWindow.PAST_WEEK, date(2026, 4, 23)) +for key, p in preds.items(): + print(f"{key.value}: {p.start_date} → {p.end_date} | widened={p.widened}") +``` + +### Serialisation round-trip + +```python +from Scripts.retrieval.time_adapter import predicates_from_serialised, compile_all +from datetime import date +from Scripts.retrieval.schema import TimeWindow + +preds = compile_all(TimeWindow.YESTERDAY, date(2026, 4, 23)) +serialised = {k.value: v.to_dict() for k, v in preds.items()} +restored = predicates_from_serialised(serialised) +assert list(preds.keys()) == list(restored.keys()) +``` + +### Monday / weekend edge-case test + +```python +from datetime import date +from Scripts.retrieval.time_adapter import compile_predicate, SourceTimeKey +from Scripts.retrieval.schema import TimeWindow + +# Monday anchor — yesterday should resolve to Friday +pred = compile_predicate(TimeWindow.YESTERDAY, SourceTimeKey.SILVER_OPTIONS, anchor=date(2026, 4, 27)) +assert pred.start_date == date(2026, 4, 24) # Friday +``` + +--- + +## 6. Dependencies + +| Library | Purpose | +|:---|:---| +| `Scripts/core/trading_calendar.py` | `is_business_day`, `previous_business_day` — dependency-free business-day arithmetic | +| `Scripts/retrieval/schema.py` | `TimeWindow`, `TIME_WINDOW_DAYS`, `time_window_to_days` | + +No external pip packages required. The module is stateless and has zero database/network dependencies, making it independently unit-testable. + +```bash +# Run from repository root +python -c " +from datetime import date +from Scripts.retrieval.time_adapter import compile_all +from Scripts.retrieval.schema import TimeWindow +preds = compile_all(TimeWindow.YESTERDAY, date.today()) +for k, p in preds.items(): + print(k.value, p.start_date, p.end_date, p.widen_reason) +" +``` diff --git a/docs/Strategy_choices_docs/Embedding_Chunking_and_Retrieval_Fusion_Strategy.md b/docs/Strategy_choices_docs/Embedding_Chunking_and_Retrieval_Fusion_Strategy.md new file mode 100644 index 0000000..22713ae --- /dev/null +++ b/docs/Strategy_choices_docs/Embedding_Chunking_and_Retrieval_Fusion_Strategy.md @@ -0,0 +1,504 @@ +# Embedding, Chunking, and Retrieval Fusion Strategy + +_Scope: `Scripts/vector_store/`, `Scripts/retrieval/qdrant_retriever.py`, `Scripts/vector_store/ingestion.py`_ + +_This document is the authoritative rationale for every model, chunking decision, and fusion parameter in the retrieval pipeline. For the operational model registry (WHAT is deployed WHERE), see `docs/ARCHITECTURE.md §5`. For GPU warmup and Ollama keep-alive, see `docs/LLM_Pool.md`._ + +--- + +## I. Strategic Objective + +The retrieval layer must resolve two fundamentally different information types in a single query: + +| Information Type | Example | Signal | Failure Mode if Missed | +|---|---|---|---| +| **Lexical-exact** | `NVDA Form 4`, `action_direction=SELL`, `CPIAUCSL` | Ticker symbols, SEC codes, acronyms | Wrong ticker retrieved; hallucinated data | +| **Semantic-abstract** | "flight to safety", "IV crush regime", "geopolitical risk premium" | Conceptual proximity | Relevant macro context not retrieved | + +A single retrieval channel — dense or sparse alone — cannot serve both. The strategy documented here combines three complementary models (dense encoder, sparse encoder, cross-encoder reranker) with Reciprocal Rank Fusion (RRF), preceded by source-specific chunking that maximises per-vector information density. + +--- + +## II. Architecture + +``` +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ RETRIEVAL STACK — LAYER OVERVIEW │ +├─────────────────────┬───────────────────────────────────────────────────────────┤ +│ Layer │ Components │ +├─────────────────────┼───────────────────────────────────────────────────────────┤ +│ Chunking │ Per-source strategy: Zero-chunk (SEC), LLM-distilled │ +│ │ summary unit (News/GPR), No-chunk (Options/Macro Silver) │ +├─────────────────────┼───────────────────────────────────────────────────────────┤ +│ Encoding │ Dense: BAAI/bge-base-en-v1.5 (768-dim, cosine, CPU) │ +│ │ Sparse: prithivida/Splade_PP_en_v1 (SPLADE, ONNX, CPU) │ +├─────────────────────┼───────────────────────────────────────────────────────────┤ +│ Asymmetric Input │ Dense ← HyDE long paragraph (abstract intent) │ +│ │ Sparse ← rerank_query short factual phrase (lexical) │ +├─────────────────────┼───────────────────────────────────────────────────────────┤ +│ Fusion │ Qdrant server-side Reciprocal Rank Fusion (RRF, k=60) │ +├─────────────────────┼───────────────────────────────────────────────────────────┤ +│ Reranking │ BAAI/bge-reranker-v2-m3 CrossEncoder (top-K, CPU) │ +├─────────────────────┼───────────────────────────────────────────────────────────┤ +│ Pre-filter │ Qdrant payload filter: ticker, source_type, │ +│ │ action_direction, time window OR (unified_timestamp / │ +│ │ publish_timestamp) │ +├─────────────────────┼───────────────────────────────────────────────────────────┤ +│ Score gate │ Drop candidates with score ≤ 1e-5 (noise floor) │ +└─────────────────────┴───────────────────────────────────────────────────────────┘ +``` + +``` +Gold-layer JSONL / MD artefacts + │ + ├─── SEC (Form 4, 8-K) + │ │ Zero-chunking: 1 filing entry → 1 vector + │ └── atomic self-contained sentence per record + │ + ├─── News / GPR narratives + │ │ LLM-distilled summary unit: ~150–300 tokens + │ └── one coherent narrative block per Qdrant point + │ + └─── Options / Macro (Silver Parquet) + │ NOT indexed in Qdrant — queried via DuckDB / SilverSQLTool + └── No chunking applies; time-windowed Parquet scan + │ + ▼ + ┌───────────────────────────────┐ + │ QdrantHybridIngestor │ + │ • Dense embed (bge-base) │ + │ • Sparse embed (SPLADE) │ + │ • Deterministic UUID │ + │ • Batch upsert (size=100) │ + └───────────────┬───────────────┘ + │ + ▼ + ┌──────────────────┐ + │ Qdrant Cloud │ + │ financial_rag_ │ + │ gold │ + │ named vectors: │ + │ dense + sparse │ + └─────────┬────────┘ + │ + ┌──────────────▼──────────────────────┐ + │ FinancialHybridRetriever │ + │ │ + │ Input A (dense): HyDE paragraph │ + │ Input B (sparse): rerank_query │ + │ │ + │ 1. Prefetch dense (top-50) │ + │ 2. Prefetch sparse (top-50) │ + │ 3. Payload filter (metadata gate) │ + │ 4. Qdrant RRF fusion (k=60) │ + │ 5. CrossEncoder rerank (bge-m3) │ + │ 6. Drop score ≤ 1e-5 │ + └──────────────┬──────────────────────┘ + │ + ▼ + MasterRetrievalResult → LangGraph AgentState +``` + +--- + +## III. Chunking Strategy — Per Data Source + +Chunking is the most consequential upstream decision in any RAG system. The wrong strategy destroys vector quality before a single embedding is computed. Each data source in this system has a fundamentally different information structure, and is therefore treated with a distinct chunking policy. + +### A. SEC Filings (Form 4 / Form 8-K) — Zero-Chunking + +**Policy: one filing record → one Qdrant point** + +``` +Bronze JSONL (structured XML extract) + ↓ +sec_processor.py (semantic rewrite + tone scoring) + ↓ +Gold JSONL (one natural-language sentence per transaction): +"ROCHE VINCENT (Chair & CEO) of ADI acquired (via RSU vesting) + 19,712 shares worth $0.00." [metadata: ticker=ADI, action_direction=ACQUIRE/VEST, ...] + ↓ +One vector point — no further splitting +``` + +**Justification:** + +| Design question | Answer | +|---|---| +| Why no chunking? | Each SEC record is already a **pre-summarised atomic fact** — self-contained, with no inter-sentence dependencies. Splitting a one-sentence record would destroy, not preserve, its meaning. | +| Why not parent-child? | The "parent" would be the raw XML/JSON source — machine code, not natural language. Injecting it into the LLM context degrades attention quality and wastes tokens. Traceability is handled via `accession_no` and `url` in metadata, not via parent expansion. | +| Why not token-based chunking (e.g. 512 tokens)? | Token-based chunking solves the problem of long noisy documents. SEC records after `sec_processor.py` are already 100% information-dense, 20–50 tokens each. Cutting them further produces fragments that destroy the signal. | + +**Vector SNR benefit:** An atomic-fact chunk produces a very tight embedding vector. Cosine similarity queries resolve to the correct entity almost exclusively — the retrieval signal-to-noise ratio is maximised. + +--- + +### B. News Articles and GPR Narratives — LLM-Distilled Summary Units + +**Policy: one scraper-summarised narrative block → one Qdrant point** + +``` +Raw article HTML (Bronze) + ↓ +news_scraper.py / GPR_index.py (LLM-summarise + sentiment score) + ↓ +Gold JSONL (one coherent narrative per article or monthly GPR block): +"Escalating Middle East tensions drove gold prices 2.4% higher this week + as investors rotated into safe-haven assets, with ETF inflows hitting + a 6-month high." [metadata: topics=[macro_geopolitics_risk], tone_score=+0.7, ...] + ↓ +One vector point — no further splitting +``` + +**Justification:** + +| Design question | Answer | +|---|---| +| Why not chunk news articles by sentence? | Individual sentences stripped of narrative context score weakly on semantic queries. A chunk like "Gold rose." loses the causal chain. The scraper-produced summary already is the ideal chunk: dense, causal, self-contained. | +| Why not chunk by 512 tokens? | The summaries are already within 150–300 tokens. Additional chunking would create sub-summary fragments with overlapping but incomplete signals, flooding the retrieval pool with near-duplicate low-precision chunks. | +| Why LLM distillation at ingestion time? | Front-loading the LLM work in `news_scraper.py` means retrieval hits pre-curated vectors instead of raw noisy article text. This is the "pre-RAG" approach used by high-quality financial data providers. | + +--- + +### C. Options Chains and Macro Data — Not Chunked (Silver SQL Path) + +**Policy: structured numeric data is NEVER ingested into Qdrant** + +Parquet files in `Data/2_Silver_Processed/Options_Market_Data/` and `Data/2_Silver_Processed/Macro_History/` are queried exclusively via `SilverSQLTool` (DuckDB). They are not embedded, not chunked, and not stored in Qdrant. + +**Justification:** + +| Design question | Answer | +|---|---| +| Why not embed numeric time-series? | Embedding `{ATM_IV: 0.34, PCR: 1.2, ...}` produces a vector that encodes the *serialisation* of the number, not its financial meaning. Semantic similarity on numeric data is unreliable — "VIX=19" and "VIX=35" would score similarly. | +| Why DuckDB instead? | Structured queries on Parquet give **exact, reproducible answers** to numeric questions. DuckDB resolves `SELECT avg(atm_iv) WHERE snapshot_date >= '2026-03-24'` in ~70ms with deterministic results — no vector approximation. | +| What is the Silver anchor mechanism? | `SilverSQLTool` writes its results into `silver_context["values"]` with explicit `MACRO_*` and `LIQ_*` lineage anchors. The Analyst cites these anchors; the Checker validates against the same in-memory dict — no vector recall needed. | + +--- + +## IV. Embedding Model Selection + +### A. Dense Encoder — `BAAI/bge-base-en-v1.5` + +| Attribute | Value | +|---|---| +| **Vector dimension** | 768 | +| **Distance metric** | Cosine (L2-normalised) | +| **Inference device** | CPU (env: `EMBEDDING_DEVICE=cpu`) | +| **HuggingFace ID** | `BAAI/bge-base-en-v1.5` | +| **Env var** | `EMBEDDING_MODEL_NAME` | +| **Singleton** | `@lru_cache` in `connection.py` | + +**Selection rationale:** + +| Criterion | Assessment | +|---|---| +| **Financial domain performance** | BGE ("Beijing Academy of AI General Embedding") achieves strong MTEB benchmark scores on information retrieval tasks. The `base` variant performs within 2–3% of `bge-large` on financial text while using 40% less memory. | +| **CPU feasibility** | 768-dim BERT-architecture encoder runs at ~50–200ms per query on CPU — well within the retrieval budget. No GPU required, which aligns with the design constraint that GPU resources are reserved exclusively for the 70B Ollama LLM. | +| **Normalisation** | `encode_kwargs={"normalize_embeddings": True}` produces unit vectors, enabling cosine similarity that is numerically equivalent to Qdrant's `Distance.COSINE` index — no post-hoc score rescaling needed. | +| **LangChain integration** | Native `langchain-huggingface` adapter; drop-in compatible with Qdrant's `VectorStore.from_documents()` API. | +| **Alternatives rejected** | `text-embedding-ada-002` (API cost, data privacy constraints), `bge-large-en-v1.5` (1024-dim, ~50% higher memory, marginal quality gain on short financial sentences), `e5-mistral-7b` (GPU-only, too large for CPU embedding path). | + +--- + +### B. Sparse Encoder — `prithivida/Splade_PP_en_v1` + +| Attribute | Value | +|---|---| +| **Architecture** | SPLADE (Sparse Lexical and Expansion) | +| **Runtime** | ONNX via `fastembed` | +| **Inference device** | CPU only (`FASTEMBED_THREADS` controls parallelism) | +| **Env var** | `SPARSE_MODEL_NAME` | +| **Qdrant vector name** | `sparse` (Dot product distance) | + +**Selection rationale:** + +| Criterion | Assessment | +|---|---| +| **Lexical expansion** | SPLADE learns to expand query and document terms into related vocabulary. "IV" expands toward "implied volatility", "VIX", "volatility index". "NVDA" expands toward "NVIDIA", "Form 4", "insider". This makes exact-match recall robust to abbreviation mismatches. | +| **Financial precision** | Ticker symbols, SEC form codes (`Form-4`, `10-K`), and macro acronyms (`CPI`, `FEDFUNDS`, `DXY`) are high-value exact tokens. SPLADE preserves these at high term-weight while BM25 would dilute them with IDF across a corpus that uses them frequently. | +| **ONNX deployment** | `fastembed` loads the SPLADE ONNX graph — no Python ML framework at inference time. Startup is fast; no GPU required; thread count is tunable via `FASTEMBED_THREADS`. | +| **Qdrant-native** | fastembed is maintained by Qdrant; the sparse vector format directly populates `NamedSparseVector` without marshaling overhead. | +| **Alternatives rejected** | BM25 (no expansion — abbreviation mismatches are fatal in financial queries), `naver/splade-v3` (larger, slower, no ONNX release at current evaluation date). | + +--- + +### C. Cross-Encoder Reranker — `BAAI/bge-reranker-v2-m3` + +| Attribute | Value | +|---|---| +| **Architecture** | Cross-encoder (full self-attention over query ⊕ document) | +| **Library** | `sentence-transformers` `CrossEncoder` | +| **Inference device** | CPU (env: `RETRIEVER_DEVICE=cpu`) | +| **Env var** | `RERANKER_MODEL_NAME` | +| **Applied to** | Top-K RRF-fused candidates before score gate | + +**Selection rationale:** + +| Criterion | Assessment | +|---|---| +| **Joint encoding** | The cross-encoder sees the query and the candidate chunk jointly in a single forward pass. This allows full attention across the pair — catching semantic nuances that bi-encoders approximate with a dot product. Example: "insider selling activity" vs "RSU vesting (no open-market sale)" are textually similar but directionally opposite; the cross-encoder resolves this correctly. | +| **Reranking position** | Applied after RRF narrows candidates to top-20. CPU reranking 20 pairs in ~100–200ms is acceptable. Reranking the full prefetch pool (100 candidates) would be prohibitive. | +| **m3 variant** | The `-m3` (Multilingual-3) variant handles English-primary with minor multilingual capability. Financial data often contains mixed content (foreign-language SEC registrants, international macro data); the `m3` architecture is more robust than an English-only model on these edge cases. | +| **Alternatives rejected** | `cross-encoder/ms-marco-MiniLM-L-6-v2` (trained on web Q&A; lower precision on financial domain), `Cohere Rerank` (API cost, data egress), `bge-reranker-large` (2× slower, no quality gain over `v2-m3` on financial retrieval). | + +--- + +## V. Retrieval Fusion — Reciprocal Rank Fusion (RRF) + +### A. Why RRF over Score Averaging + +Dense and sparse models produce scores on incompatible numerical scales: +- Dense cosine similarity: typically in `[0.5, 1.0]` for positive results +- SPLADE sparse dot product: typically in `[0.001, 5.0]`, scale depends on term frequency + +Simple score averaging would allow one channel to dominate based on scale artifacts, not quality. RRF converts both to rank lists and fuses on rank position: + +``` +RRF_score(doc) = Σᵢ 1 / (k + rankᵢ(doc)) +``` + +Where `k = 60` (Qdrant default). This is rank-based, monotonic, and immune to outlier scores. A document ranked #1 by dense but #50 by sparse still outscores a document ranked #10 by both — the fusion correctly rewards dominant-channel wins. + +### B. Asymmetric Input Design + +| Channel | Input text | Purpose | +|---|---|---| +| **Dense** | `HyDE paragraph` (~200 tokens, LLM-generated) | Captures abstract intent: "flight to safety", "IV regime", conceptual framing | +| **Sparse** | `rerank_query` (~8–15 tokens, factual phrase) | Enforces exact lexical match: "NVDA Form 4 insider selling past month" | + +This asymmetry is deliberate. Feeding the HyDE paragraph to the sparse channel would dilute SPLADE's term weights with narrative filler. Feeding the short factual query to the dense channel would under-activate semantic proximity. The two channels are calibrated to their respective strengths. + +### C. RRF Workflow + +```mermaid +flowchart TD + Q["User Query"] --> QT["QueryTransformer\n(options-expert-v1:latest, 70B)"] + QT --> |HyDE paragraph| DE["Dense Prefetch\nbge-base-en-v1.5\nTop-50 candidates"] + QT --> |rerank_query| SP["Sparse Prefetch\nSPLADE PP en v1\nTop-50 candidates"] + + DE --> |100 candidates| MF["Metadata Pre-filter\nticker / source_type / time window\nPayload filter before vector math"] + SP --> MF + + MF --> RRF["Qdrant Server-side RRF\nFusion.RRF k=60\nMerge dense + sparse rank lists"] + + RRF --> |Top-20 fused| CE["CrossEncoder Rerank\nbge-reranker-v2-m3\nFull query⊕doc attention"] + + CE --> SG["Score Gate\nDrop score ≤ 1e-5\nNoise floor cutoff"] + + SG --> OUT["Gold Context Chunks\nList[RetrievedChunk]\n→ AgentState.gold_context"] +``` + +### D. Deterministic Pre-Filtering + +Payload filtering is applied **before** vector math (pushed down to the Qdrant index scan), which ensures vector distance computation is only performed on semantically eligible candidates: + +| Filter dimension | Applied for | Implementation | +|---|---|---| +| `ticker` | All queries with extracted tickers | `FieldCondition(key="ticker", match=MatchAny(...))` | +| `source_type` | Metadata-extracted `source_types` | Strips Silver-only types (`options`, `macro`) before Gold search | +| `action_direction` | SEC insider queries | `SELL`, `BUY`, `ACQUIRE/VEST` | +| `form_type` | SEC form queries | `Form-4`, `10-K`, `8-K` | +| `tone_score` | Sentiment-filtered news | `>0` (bullish), `<0` (bearish) | +| `unified_timestamp` OR `publish_timestamp` | All time-windowed queries | OR condition: dual time-key for backwards compatibility with legacy filings | + +The OR over `unified_timestamp` and `publish_timestamp` is critical: early SEC filings only carry `publish_timestamp`; newer ones carry `unified_timestamp`. A single-key filter would silently miss one subset. + +--- + +## VI. Hardware Placement — CPU vs GPU + +The system is designed with a **strict hardware tier separation**: GPU is reserved exclusively for LLM inference; all retrieval-side models run on CPU. + +``` +┌────────────────────────────────────────────────────────────────┐ +│ GPU (Ollama VRAM) │ +│ │ +│ options-expert-v1:latest (Llama-3.3-70B Q4_K_M) │ +│ ├─ Analyst / Checker / Critic / Finalizer │ +│ └─ QueryTransformer (Extractor + HyDE) │ +│ │ +│ llama3:latest (Llama-3 8B vanilla) │ +│ ├─ MasterRetriever.router_llm │ +│ └─ news_scraper sentiment / sec_processor form parser │ +│ │ +│ Note: 70B + 8B cannot coexist in one GPU slot → │ +│ llm_pool pins 70B at KEEP_ALIVE=30m; 8B uses idle slots. │ +└────────────────────────────────────────────────────────────────┘ + +┌────────────────────────────────────────────────────────────────┐ +│ CPU (Host RAM) │ +│ │ +│ BAAI/bge-base-en-v1.5 (Dense encoder, 768-dim) │ +│ • Latency: ~50–200ms / query (CPU) │ +│ • Env: EMBEDDING_DEVICE=cpu │ +│ • Singleton: @lru_cache in connection.py │ +│ │ +│ prithivida/Splade_PP_en_v1 (SPLADE sparse, ONNX) │ +│ • ONNX runtime: no Python ML framework at inference │ +│ • Env: FASTEMBED_THREADS=6 │ +│ │ +│ BAAI/bge-reranker-v2-m3 (CrossEncoder, top-K only) │ +│ • Applied to ≤ 20 candidates → ~100–200ms CPU │ +│ • Env: RETRIEVER_DEVICE=cpu │ +│ │ +│ DuckDB in-process (Silver Parquet queries) │ +│ • Embedded, zero-latency startup │ +│ • ~50–100ms per Parquet scan │ +└────────────────────────────────────────────────────────────────┘ +``` + +**Design rationale for CPU retrieval models:** + +| Constraint | Implication | +|---|---| +| **Single GPU budget** | The 70B fine-tuned LLM saturates available VRAM (Q4_K_M quantised ≈ 40GB+). Placing any retrieval model on the same GPU would force model-swapping, incurring 30–60s cold starts per query. | +| **Retrieval latency budget** | Dense + sparse encoding + reranking ≤ 500ms on CPU is acceptable within the overall pipeline budget (dominated by the ~200s LLM inference). CPU retrieval is not the bottleneck. | +| **ONNX for sparse** | `fastembed` ONNX runtime eliminates Python ML framework overhead at sparse inference — CPU latency for SPLADE is ~30ms per query. | +| **Upgrade path** | `EMBEDDING_DEVICE` and `RETRIEVER_DEVICE` are env-var controlled. Setting either to `cuda` enables GPU acceleration without code changes — useful on multi-GPU machines where a retrieval-only GPU is available. | + +--- + +## VII. Where Does Model and Hardware Information Live? + +This is a common documentation friction point. The answer is a three-document triangle: + +``` +┌───────────────────────────────────────────────────────────────────┐ +│ Documentation Navigation │ +│ │ +│ Q: "WHY was this model chosen? What are the trade-offs?" │ +│ A: docs/Strategy_choices_docs/ │ +│ └── Embedding_Chunking_and_Retrieval_Fusion_Strategy.md ← THIS│ +│ SEC_ingestion_retrived_strategy.md │ +│ │ +│ Q: "WHAT model is deployed WHERE? What are the env vars?" │ +│ A: docs/ARCHITECTURE.md §5 (Model Registry — single source of │ +│ truth for tag names, env vars, and consumers) │ +│ │ +│ Q: "HOW do I keep the 70B LLM warm? How do I manage GPU?" │ +│ A: docs/LLM_Pool.md (warmup runbook, VRAM tiering, keep-alive) │ +│ │ +│ Q: "HOW does the retrieval pipeline call these models?" │ +│ A: docs/Query_retrieval_docs/ │ +│ └── Retrieval_Architecture_and_Strategy.md (execution path) │ +│ │ +│ Q: "HOW are embeddings computed at ingestion time?" │ +│ A: docs/Vector_store_docs/ │ +│ └── Vector_Ingestion.md (batch upsert + HWM state) │ +│ └── Qdrant_connection.md (embedding factory, provider switch) │ +└───────────────────────────────────────────────────────────────────┘ +``` + +**Decision rule:** New model-related information should land in: +- `Strategy_choices_docs/` if it answers "why was this design chosen?" +- `ARCHITECTURE.md §5` if it is a new entry in the canonical model registry +- `LLM_Pool.md` if it affects Ollama GPU memory management +- `Query_retrieval_docs/` if it changes the runtime retrieval execution path + +--- + +## VIII. Configuration Matrix (`.env`) + +| Variable | Default | Purpose | Tier | +|---|---|---|---| +| `EMBEDDING_MODEL_NAME` | `BAAI/bge-base-en-v1.5` | Dense encoder HuggingFace ID | Retrieval (CPU) | +| `EMBEDDING_DEVICE` | `cpu` | Dense encoder device (`cpu`, `cuda`, `mps`) | Retrieval (CPU) | +| `SPARSE_MODEL_NAME` | `prithivida/Splade_PP_en_v1` | SPLADE model via fastembed | Retrieval (CPU) | +| `FASTEMBED_THREADS` | `6` | ONNX SPLADE thread count | Retrieval (CPU) | +| `RERANKER_MODEL_NAME` | `BAAI/bge-reranker-v2-m3` | CrossEncoder reranker | Retrieval (CPU) | +| `RETRIEVER_DEVICE` | `cpu` | CrossEncoder device | Retrieval (CPU) | +| `QDRANT_HOST` | required | Qdrant Cloud REST endpoint | Infrastructure | +| `QDRANT_API_KEY` | required | Qdrant authentication | Infrastructure | +| `OLLAMA_CUSTOM_MODEL_NAME` | `options-expert-v1:latest` | 70B fine-tuned (agents + QueryTransformer) | LLM (GPU) | +| `OLLAMA_ROUTER_MODEL` | `llama3:latest` | 8B router + ingestion helpers | LLM (GPU) | +| `OLLAMA_KEEP_ALIVE` | `30m` | VRAM pin duration for 70B | LLM (GPU) | + +--- + +## IX. How to Test + +### Retrieval sanity check + +```python +from Scripts.retrieval.qdrant_retriever import FinancialHybridRetriever +from Scripts.retrieval.schema import QueryIntent + +retriever = FinancialHybridRetriever() +chunks = retriever.retrieve( + query_intent=QueryIntent( + hyde_paragraph="NVDA insider selling executive Form 4 past month momentum", + rerank_query="NVDA Form-4 insider selling", + tickers=["NVDA"], + source_types=["sec"], + ) +) +print(f"Retrieved {len(chunks)} chunks") +for c in chunks[:3]: + print(f" score={c.score:.4f} | ticker={c.metadata.get('ticker')} | {c.content[:80]}") +``` + +Expected: ≥1 SEC chunk with `ticker=NVDA`, score > 1e-5. + +### Dense encoder smoke test + +```python +from Scripts.vector_store.connection import get_embedding_model + +model = get_embedding_model() +vec = model.embed_query("gold ETF implied volatility geopolitical risk") +assert len(vec) == 768, f"Expected 768-dim, got {len(vec)}" +print(f"Dense vector dim: {len(vec)} ✅") +``` + +### Sparse encoder smoke test + +```python +from fastembed import SparseTextEmbedding + +sparse = SparseTextEmbedding("prithivida/Splade_PP_en_v1") +result = list(sparse.query_embed("NVDA Form 4 insider selling"))[0] +top_terms = sorted(zip(result.indices, result.values), key=lambda x: -x[1])[:5] +print("Top SPLADE terms:", top_terms) +``` + +Expected: indices mapping to tokens related to "nvda", "form", "insider", "selling". + +### RRF + rerank end-to-end (integration) + +```bash +python -m Scripts query --warmup "Given recent NVDA Form-4 executive selling, how should I position with options?" +# Check logs/retrieval//retriever_audit_trail.jsonl for: +# - gold_chunks_returned ≥ 3 +# - all chunks with score > 1e-5 +# - at least one chunk with source_type=sec +``` + +--- + +## X. Dependencies + +| Library | Purpose | Tier | +|---|---|---| +| `langchain-huggingface` | Dense HuggingFace embedding wrapper | Retrieval | +| `sentence-transformers` | CrossEncoder reranker | Retrieval | +| `fastembed` | SPLADE ONNX sparse encoder | Retrieval | +| `qdrant-client` | Qdrant Cloud REST client + RRF fusion | Retrieval | +| `langchain-ollama` | Ollama LLM client (agents + QueryTransformer) | LLM | +| `langchain-core` | `Embeddings` base class | Retrieval | +| `python-dotenv` | `.env` variable loading | Config | +| `duckdb` | In-process Parquet SQL for Silver layer | Silver SQL | +| `pyarrow` | Parquet read/write | Silver SQL | + +```bash +pip install langchain-huggingface sentence-transformers fastembed qdrant-client \ + langchain-ollama langchain-core python-dotenv duckdb pyarrow +``` + +--- + +## XI. Change Log + +| Date | Change | Rationale | +|---|---|---| +| 2026-04-23 | Document created | Consolidates all model-selection rationale, chunking strategy, and hardware placement into a single Strategy reference. Prior knowledge was implicit in code and scattered across Retrieval_Architecture_and_Strategy.md. | diff --git a/docs/Tools_patch_docs/SEC_patch_tooling.md b/docs/Tools_patch_docs/SEC_patch_tooling.md new file mode 100644 index 0000000..68d4a06 --- /dev/null +++ b/docs/Tools_patch_docs/SEC_patch_tooling.md @@ -0,0 +1,178 @@ +# SEC Patch & Maintenance Tooling + +Three **ad hoc** utilities under `Scripts/tools/` support recovery, backfills, and operational hygiene for the SEC pipeline. They are **not** substitutes for the scheduled `sec_ingestion` / `sec_processor` pipelines; they operate on existing Bronze artefacts without re-scraping EDGAR. + +--- + +## 1. Goal + +| Utility | Primary role | +|:---|:---| +| `SEC_generate_cik_map.py` | Refresh the **ticker → CIK** map from SEC's public bulk endpoint into `config/SEC_Ingestion/ticker_to_cik.json` | +| `SEC_parsed_form4_8-k.py` | Re-fetch and re-parse Form 4 (XML) and 8-K (HTML) into `parsed_data` for Bronze rows that lack usable structured content; writes sidecar `patched_{TICKER}.jsonl` without mutating originals | +| `SEC_accession_no_depulicated.py` | Drop rows from Bronze JSONL whose `accession_no` already appears in `global_processed_registry.json` or is duplicated within the same file; rewrites in place | + +--- + +## 2. Architecture + +``` +[1] SEC_generate_cik_map.py + │ GET https://www.sec.gov/files/company_tickers.json + │ Normalise CIK to 10-digit zero-padded string + └─► config/SEC_Ingestion/ticker_to_cik.json + +[2] SEC_parsed_form4_8-k.py + │ Read Data/1_Bronze_Raw/SEC_Parsed_JSON/{date}/{TICKER}.jsonl + │ Re-fetch Form 4 XML or 8-K HTML via original URL + │ Parse via sec_ingestion parsers + └─► Data/1_Bronze_Raw/SEC_Parsed_JSON/{date}/patched_{TICKER}.jsonl (new file, originals unchanged) + +[3] SEC_accession_no_depulicated.py + │ Load config/SEC_Processing/global_processed_registry.json + │ Scan Data/1_Bronze_Raw/SEC_Parsed_JSON/{date}/{TICKER}.jsonl + │ Drop rows: missing accession | in registry | within-file duplicate + └─► Data/1_Bronze_Raw/SEC_Parsed_JSON/{date}/{TICKER}.jsonl (destructive rewrite) +``` + +--- + +## 3. Code Strategy & Workflow + +### 3.1 `SEC_generate_cik_map.py` + +1. HTTP GET `https://www.sec.gov/files/company_tickers.json` with SEC-compliant `User-Agent` header. +2. For each entry: normalise `cik_str` → 10-digit zero-padded string. +3. Persist full mapping as pretty-printed JSON. + +**When to run:** after SEC bulk schema changes, or weekly if you rely on newly-listed symbols. + +### 3.2 `SEC_parsed_form4_8-k.py` + +1. Resolve `Data/1_Bronze_Raw/SEC_Parsed_JSON/{target_date}/`. +2. Enumerate source files: `{TICKER}.jsonl`, excluding `patched_*`, `_*`, and `*SUMMARY*` names. +3. For each source file, if `patched_{TICKER}.jsonl` does not already exist: + - Stream JSON lines. + - **Form 4** (`form_type == "4"`) with URL and empty `parsed_data`: fetch XML, parse transactions; set `raw_text = "XML_PARSED_SUCCESSFULLY"` on success. + - **8-K** (`form_type == "8-K"`) with URL: re-parse when `parsed_data` is missing or `raw_text` is not yet `"8K_PARSED_INTO_MARKDOWN_CHUNKS"`. + - Always ensure `parsed_data` key exists (empty dict if parse fails). +4. Write output to `patched_{TICKER}.jsonl` in the same date directory. + +### 3.3 `SEC_accession_no_depulicated.py` + +1. Load `config/SEC_Processing/global_processed_registry.json` as a set (missing file → empty set + warning). +2. Resolve `Data/1_Bronze_Raw/SEC_Parsed_JSON/{TARGET_DATE}/`. +3. For each `{TICKER}.jsonl`: classify each row: + - **Drop** if `accession_no` is missing. + - **Drop** if `accession_no` ∈ global registry. + - **Drop** if `accession_no` already seen earlier in the same file. + - **Keep** otherwise (first-occurrence ordering preserved). +4. Rewrite the same `{TICKER}.jsonl` in place with kept rows only. + +--- + +## 4. Output Data Schema & Paths + +### Artifact Locations + +``` +config/SEC_Ingestion/ + ├── SEC_tickers.json # Curated ticker list (not written by these tools) + └── ticker_to_cik.json # Written by SEC_generate_cik_map.py + +config/SEC_Processing/ + └── global_processed_registry.json # Read (not written) by SEC_accession_no_depulicated.py + # Written by sec_processor.py after Gold writes + +Data/1_Bronze_Raw/SEC_Parsed_JSON/{YYYY-MM-DD}/ + ├── {TICKER}.jsonl # Source; rewritten in-place by accession dedupe + ├── patched_{TICKER}.jsonl # Written by SEC_parsed_form4_8-k.py (sidecar) + └── _SUMMARY.json # Cross-ticker summary (not modified by patch tools) + +logs/{YYYY-MM-DD}/ + ├── SEC_bronze_accession_dedupe_{YYYY-MM-DD}.log + └── SEC_Ingestion/ + ├── ingestion_progress_{YYYY-MM-DD}.log + └── patch_form4_8k_{YYYY-MM-DD}.log +``` + +### `patched_{TICKER}.jsonl` Schema + +Identical to the Bronze JSONL schema in `docs/Data_source_docs/SEC_data.md`. Fields that were absent or empty in the original (`parsed_data`, `raw_text`) are populated; all other fields are copied verbatim. + +### Dedupe Log Structure (per ticker file) + +``` +[TICKER.jsonl] input=47 output=32 kept=32 dropped_no_accession=0 + dropped_registry_hit=10 dropped_within_file_dup=5 + sample_registry_hits: [0001234567-26-000001, ...] + sample_within_file_dups: [0001234567-26-000002, ...] +``` + +--- + +## 5. How to Test + +### CIK map refresh + +```bash +python Scripts/tools/SEC_generate_cik_map.py +# Expected: config/SEC_Ingestion/ticker_to_cik.json updated; AAPL → "0000320193" +python -c "import json; d=json.load(open('config/SEC_Ingestion/ticker_to_cik.json')); print(d.get('AAPL'))" +``` + +### Patch validation + +```bash +# Run on a specific date +python Scripts/tools/SEC_parsed_form4_8-k.py --date 2026-04-23 +# Check output +ls Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-23/patched_*.jsonl +# Verify parsed_data populated +python -c " +import json +for line in open('Data/1_Bronze_Raw/SEC_Parsed_JSON/2026-04-23/patched_AAPL.jsonl'): + r = json.loads(line) + print(r['metadata']['form_type'], bool(r.get('parsed_data'))) +" +``` + +### Dedupe smoke check + +```bash +python Scripts/tools/SEC_accession_no_depulicated.py +# Check log +cat logs/$(date +%Y-%m-%d)/SEC_bronze_accession_dedupe_$(date +%Y-%m-%d).log +``` + +--- + +## 6. Recommended Sequencing & Governance + +``` +[1] SEC_generate_cik_map.py + │ Refreshes ticker_to_cik.json (ingestion prerequisite) + ▼ +[2] SEC_parsed_form4_8-k.py (optional — only if parsed_data / 8-K chunks missing) + │ Produces patched_{TICKER}.jsonl alongside originals + ▼ +[3] SEC_accession_no_depulicated.py (optional hygiene before Gold) + │ Trims rows already in global_processed_registry.json + ▼ + sec_processor.py → Gold JSONL → Qdrant upsert +``` + +**Governance notes:** +- Step 3 is **destructive**: rewrites `{TICKER}.jsonl` in place. Back up the date folder before running if in doubt. +- Step 2 does **not** overwrite originals; promote or merge `patched_*` content through your own pipeline rules before relying on Bronze alone. +- `global_processed_registry.json` is the authoritative "already processed" source of truth, written by `sec_processor.py`. Do not edit manually. + +--- + +## 7. Dependencies + +```bash +pip install requests beautifulsoup4 markdownify python-dotenv +``` + +**Required env variable:** `SEC_USER_AGENT` — e.g. `"CompanyName contact@email.com"` (SEC EDGAR fair-access policy). diff --git a/docs/User_Query_Guide.md b/docs/User_Query_Guide.md new file mode 100644 index 0000000..78f2ab5 --- /dev/null +++ b/docs/User_Query_Guide.md @@ -0,0 +1,254 @@ +# User Query Guide + +> **Audience.** End-users and analysts who want to ask the +> Options-Recommendation RAG meaningful questions. +> **Goal.** Show what this system *can* answer, what data it has behind +> each answer, and how to phrase a query so the router, retriever and +> analyst agents can do their job cleanly. +> +> If your query runs through the router and you see `route=vector_only`, +> `fallback_tier=drop_ticker_180d`, or the final report says +> *"INSUFFICIENT DATA"*, re-read §2 and §4 of this document before +> opening a bug — 90 % of the time the query was under-specified. + +--- + +## 1. What this system is (and is not) for + +The bot is a **multi-agent retrieval stack** that answers **options-trading +and cross-asset macro questions** grounded in four live data layers: + +| Layer | Storage | Updated | Typical questions it answers | +|---------------|-------------------------------|------------------|------------------------------| +| Options chain | Parquet (Silver) | Daily (trading) | IV, skew, Put/Call Ratio, OI, liquidity | +| Macro history | Parquet + Markdown (Silver/Gold) | Daily | VIX, DXY, yields, GPR index, Fed tone | +| News | Qdrant vectors (Gold) | 1–3× per week | Event-driven narrative (Fed, CPI, geopolitics, metals) | +| SEC filings | Qdrant vectors + JSONL (Bronze) | Weekly | Insider (Form-4), 8-K, 10-K/Q risk language | + +It is **not** built for: +- Real-time intraday quotes (we're end-of-day). +- Stocks outside the tracked universe (§2). +- Fundamental valuation (DCF, multiples). +- Crypto, FX majors, or single-name bonds. + +--- + +## 2. Tickers the system actually knows about + +Only tickers listed in `config/universe/` are in our options & SEC pipelines. +Anything else will either fall back to a macro-only reading or return no +Silver evidence at all. + +### 2.1 Single-name equities (options + SEC Form-4/8-K/10-K) + +Current coverage: **48 Nasdaq-100 constituents** + +``` +AAPL MSFT NVDA AMZN META GOOGL TSLA AVGO COST PEP +NFLX AMD CSCO TMUS ADBE QCOM TXN INTU AMGN ISRG +HON CMCSA INTC AMAT IBM BKNG VRTX SBUX PANW MDLZ +GILD REGN LRCX ADP ADI MU SNPS CDNS MELI CSX +KLAC PYPL CRWD MAR ASML CTAS MNST NXPI +``` + +### 2.2 ETFs (options only, no SEC) + +| Role | Tickers | Use for | +|------------------|----------------|---------| +| Broad-market | `SPY QQQ IWM` | Index sentiment, beta, regime | +| Commodity / hedge| `GLD SLV` | Precious-metals exposure, inflation hedge | + +> **Tip.** If you ask about "the market" without a ticker, the router +> will usually anchor on SPY/QQQ. If you want a commodity angle, say +> *gold*, *silver*, *GLD*, or *SLV* explicitly. + +--- + +## 3. Data sources and the metadata they expose + +### 3.1 Options chain (Silver / Parquet) + +Path: `Data/2_Silver_Processed/Options_Market_Data//_options_.parquet` + +Per-contract fields the router can filter on: + +| Field | Meaning | +|---------------------|-----------------------------------------------| +| `ticker` | Underlying symbol | +| `expiration`, `dte` | Expiry date & days-to-expiry | +| `option_type` | `call` / `put` | +| `strike`, `moneyness_pct`, `in_the_money` | Position on the chain | +| `implied_volatility`| Per-contract IV | +| `volume`, `open_interest` | Liquidity primitives | +| `spread_pct` | (ask − bid) / mid | +| `is_liquid` | Derived boolean (volume & OI thresholds) | +| `last_price`, `bid`, `ask`, `underlying_price` | Pricing quad | + +Derived metrics the system can compute on the fly: **IV Skew**, **Put/Call +Ratio** (volume *and* open-interest flavours), **latest ATM IV**, +**liquidity scan**, **OTM/ITM** filters. + +### 3.2 Macro history (Silver parquet + Gold markdown) + +Paths: +- `Data/2_Silver_Processed/Macro_History//macro_snapshot_.parquet` +- `Data/3_Gold_Semantic/Macro_Narratives//macro_context_.md` +- `Data/Agent_Context/latest_macro_context.md` (always-current mirror) + +Indicators ingested daily (subset): + +| Symbol | Name | +|-----------|------------------------------------| +| `^VIX` | Volatility index | +| `^GSPC`, `^IXIC`, `^RUT` | S&P 500, Nasdaq, Russell 2000 | +| `^TNX` | 10-Year Treasury Yield | +| `DX-Y.NYB`| US Dollar Index | +| `GC=F`, `SI=F` | Gold / Silver futures | +| `GPR` | Caldara-Iacoviello geopolitical-risk index | + +Available macro metrics: `Price`, `Price Change (%)`, `Daily/Monthly/Yearly +Change (%)`, `Macro Trend`, `GPR Index` (+ `GPR Threats / Acts / Components`). + +### 3.3 News (Qdrant Gold layer) + +Pre-curated GDELT topic buckets (see `news_scraper.py`): + +| Topic | Typical triggers | +|------------------------------------|------------------| +| `macro_central_banks` | Fed/FOMC, Powell, ECB, BOJ, rate decisions | +| `macro_inflation_employment` | CPI, PCE, payrolls, wage growth | +| `macro_yields_dollar` | 10Y yields, DXY, Treasuries | +| `macro_geopolitics_risk` | Middle East, Ukraine, Taiwan, sanctions | +| `asset_precious_metals_spot` | Gold, silver spot / bullion / safe haven | +| `asset_metals_derivatives` | COMEX, metals options, metals ETF flows | + +Metadata per chunk: `unified_timestamp`, `publish_timestamp`, `impacted_assets`, +`tone`, `topic`. + +### 3.4 SEC filings (Qdrant Gold + JSONL Bronze) + +Form coverage: **Form 4 (insider)**, **8-K (material events)**, **10-K / 10-Q** +for the 48 single-names in §2.1. + +Metadata: `ticker`, `form_type`, `accession_no`, `filed_at`, +`transaction_date`, `action_direction` (BUY / SELL / ACQUIRE/VEST / NONE), +`tone_score`, `url`. + +--- + +## 4. How to phrase a query so the router does the right thing + +The router runs two LLM stages — a **Metadata Extractor** and a **HyDE +Writer** (see `docs/Query_retrieval_docs/Query_intent_docs.md`). They look +for specific signals. Give them those signals. + +### 4.1 The five ingredients of a well-formed query + +| Ingredient | Why it matters | Examples | +|--------------------|-------------------------------------------------------|----------| +| **Ticker(s)** | Pins Silver filters; prevents `vector_only` fallback | `AAPL`, `NVDA`, `SPY`, `GLD` | +| **Metric(s)** | Drives the SQL dispatcher in `sql_tools.py` | *Put/Call Ratio*, *IV Skew*, *liquidity*, *VIX*, *GPR* | +| **Time window** | Picks `today / yesterday / past_week / past_month / past_six_months` | *today*, *yesterday*, *past week*, *6-month* | +| **Source signal** | Nudges the router toward SEC / News / Macro | *Form 4*, *insider*, *Fed minutes*, *CPI print*, *geopolitics* | +| **Trade intent** | Lets the Analyst compose an options view | *should I buy puts*, *sell covered calls*, *position for an IV crush* | + +### 4.2 Good vs. weak queries + +```text +# ✅ GOOD — has ticker + metric + time + intent +"What is AAPL's Put/Call Ratio and IV Skew today, and should I sell + front-month strangles given current liquidity?" + +# ✅ GOOD — macro-only, but explicit on topic + time +"How did the latest FOMC decision move 10-year yields and DXY over the + past week, and what does that imply for SPY 30-DTE puts?" + +# ⚠️ WEAK — no ticker, no time, vague metric +"Is the market bullish?" # router will default to past_six_months, + # no Silver anchors, Analyst returns generic. + +# ⚠️ WEAK — ticker outside universe +"What is the IV skew on F (Ford)?" +# Ford is not in config/universe; options Silver layer will be empty. +``` + +### 4.3 Time-phrasing cheat sheet + +| You write... | Router picks | Window on Silver | +|----------------------------------|-------------------------|------------------| +| "today", "right now", "current" | `TimeWindow.TODAY` | 1 business day | +| "yesterday", "last session" | `TimeWindow.YESTERDAY` | 2 business days (weekend-safe) | +| "past week", "this week" | `TimeWindow.PAST_WEEK` | 7 days | +| "last month", "over the month" | `TimeWindow.PAST_MONTH` | 30 days | +| "last 6 months", "YTD-ish" | `TimeWindow.PAST_SIX_MONTHS` | 180 days | +| nothing explicit | `PAST_SIX_MONTHS` (default) | 180 days | + +> Because the Silver layer snaps to **business days**, "yesterday" on +> a Monday means *last Friday* automatically — you do not need to +> hedge for weekends yourself. + +### 4.4 What to say if you want a specific data source + +- **Options Silver only:** name metrics (`Put/Call Ratio`, `IV Skew`, + `liquidity`, `open interest`) plus a ticker. +- **Macro Silver only:** name the indicator (`VIX`, `DXY`, `yields`, + `gold`, `GPR index`) plus a time phrase. +- **News Gold:** mention an event (`FOMC`, `CPI print`, *"headlines about"*, + *"market reaction to"*). +- **SEC Gold:** mention *"Form 4"*, *"insider selling/buying"*, *"10-K risk + factors"*, *"recent 8-K"*. + +--- + +## 5. Reference query taxonomy + +| Intent family | Template | +|----------------------------------|-----------------------------------------------------------------------------------| +| Single-name options posture | *"What is {TICKER}'s {metric} today and what options strategy fits?"* | +| Relative-value options | *"Compare {TICKER_A} vs {TICKER_B} IV skew over the past week."* | +| Event-driven | *"How did the {event} affect {TICKER or macro} and what exposure would you take?"*| +| Insider-flow driven | *"Given the recent {TICKER} Form-4 {direction}, should I {strategy}?"* | +| Macro regime | *"With {macro indicator} at {level/trend}, what does that imply for {TICKER/ETF}?"*| +| Geopolitical / commodity | *"How would rising Middle-East risk move precious metals and GLD options?"* | +| Liquidity screen | *"Which {TICKER} expirations are most liquid for a {strategy} right now?"* | + +--- + +## 6. Things that will make the system fall back or refuse + +1. **Ticker not in universe** → no Silver evidence → Analyst can only + reason off Macro/News. +2. **No ticker + no event + no macro indicator** → router runs + `vector_only` and may return *"INSUFFICIENT DATA"* on purpose. +3. **Asking for Greeks (Δ/Γ/Θ/ν)** → we list them in the ontology but + have not ingested them; you will get an honest "not available" note. +4. **Asking for real-time or intraday** → everything is end-of-day. +5. **Time signal that contradicts the data you request** — e.g. asking + for *"yesterday's 10-K filing"*. 10-Ks are quarterly; the Checker + will flag time-mismatch in the audit trail. + +--- + +## 7. Where the audit trail lives + +Every query writes a per-day JSONL trail: + +```text +logs/router_e2e//___trace.jsonl +logs/router_e2e//_run_summary.json +``` + +Use this when a report looks wrong: the JSONL captures router decisions, +retrieval filters (including the exact `start_date`/`end_date` the Silver +SQL used), Critic and Checker verdicts, and the final Finalizer output. + +--- + +## 8. TL;DR — the three rules + +1. **Put a ticker in.** If you can't, put a macro indicator or a named + event in. +2. **Put a time phrase in.** Implicit defaults to 6 months, which is + almost never what you want for an options question. +3. **State your trade intent.** The Analyst tunes its answer to what you + asked for (scan / score / position / hedge). diff --git a/docs/Vector_store_docs/Qdrant_connection.md b/docs/Vector_store_docs/Qdrant_connection.md new file mode 100644 index 0000000..797308a --- /dev/null +++ b/docs/Vector_store_docs/Qdrant_connection.md @@ -0,0 +1,152 @@ +# Qdrant Connection & Embedding Model Factory — `connection.py` + +## 1. Goal + +`Scripts/vector_store/connection.py` is the foundational infrastructure layer for all vector database operations. It provides a fault-tolerant, firewall-resilient connection gateway to Qdrant Cloud and a provider-agnostic factory for text embedding models. Downstream consumers (ingestion pipelines, `QdrantRetriever`) obtain verified client objects and embedding models without concerning themselves with retry logic, hardware placement, or credential management. + +--- + +## 2. Architecture + +``` +Environment (.env) + │ + ├─► get_qdrant_client() get_embedding_model() + │ │ │ + │ Read QDRANT_HOST Read EMBEDDING_PROVIDER + │ Read QDRANT_API_KEY Read EMBEDDING_MODEL_NAME + │ │ Read EMBEDDING_DEVICE + │ QdrantClient( │ + │ url=QDRANT_HOST, ┌────────▼────────────┐ + │ api_key=QDRANT_API_KEY, │ Provider dispatch │ + │ prefer_grpc=False, ├────────────────────┤ + │ timeout=15 │ huggingface (def.) │ + │ ) │ HuggingFaceEmbed. │ + │ │ │ + normalize=True │ + │ Retry loop (max 3, 2 s gap) ├────────────────────┤ + │ │ │ ollama │ + │ ✅ Return client │ OllamaEmbeddings │ + │ └────────▼────────────┘ + └───────────────────────────────────── @lru_cache → Return model +``` + +**Design patterns in use:** +- **Singleton / `@lru_cache`** — models and clients are loaded exactly once per process; prevents memory leaks and redundant network calls. +- **Provider Factory** — `EMBEDDING_PROVIDER` env variable routes between HuggingFace and Ollama without changing downstream code. +- **gRPC disabled** — `prefer_grpc=False` forces HTTPS REST, bypassing strict institutional or cluster firewalls. + +--- + +## 3. Code Strategy & Workflow + +### 3.1 `get_qdrant_client()` + +| Step | Detail | +|:---|:---| +| 1 | Read `QDRANT_HOST` and `QDRANT_API_KEY` from `.env` | +| 2 | Instantiate `QdrantClient(prefer_grpc=False, timeout=15)` — REST-only | +| 3 | On `ConnectionError` / network failure: retry up to **3 attempts** with **2-second backoff** | +| 4 | Return verified client on success; raise on final failure | + +### 3.2 `get_embedding_model()` + +| Branch | Env trigger | Model | +|:---|:---|:---| +| **HuggingFace** (default) | `EMBEDDING_PROVIDER=huggingface` | `HuggingFaceEmbeddings(model_name=EMBEDDING_MODEL_NAME, device=EMBEDDING_DEVICE, encode_kwargs={"normalize_embeddings": True})` | +| **Ollama** | `EMBEDDING_PROVIDER=ollama` | `OllamaEmbeddings(base_url=OLLAMA_HOST, model=EMBEDDING_MODEL_NAME)` | + +`encode_kwargs={"normalize_embeddings": True}` ensures cosine-distance compatibility with Qdrant's collection configuration. + +### 3.3 `VectorStoreConnection` (used by `QdrantRetriever`) + +The `QdrantRetriever` instantiates `VectorStoreConnection` which wraps `get_qdrant_client()` with additional logging and initialises both embedding models required for hybrid search: +- **Dense model:** `BAAI/bge-base-en-v1.5` (768-dim) via HuggingFace +- **Sparse model:** `Qdrant/Splade_PP_en_v1` via `fastembed` +- **Reranker:** `BAAI/bge-reranker-v2-m3` (CrossEncoder) via `sentence-transformers` + +--- + +## 4. Output Data Schema & Configuration + +### Environment Variables + +| Variable | Default | Required | Purpose | +|:---|:---|:---|:---| +| `QDRANT_HOST` | — | ✅ | Full REST URL of Qdrant Cloud cluster (e.g. `https://xxx.us-east-2-0.aws.cloud.qdrant.io:6333`) | +| `QDRANT_API_KEY` | — | ✅ | Authentication token | +| `EMBEDDING_PROVIDER` | `huggingface` | | `"huggingface"` or `"ollama"` | +| `EMBEDDING_MODEL_NAME` | `BAAI/bge-base-en-v1.5` | | Dense embedding model ID | +| `EMBEDDING_DEVICE` | `cpu` | | `"cpu"`, `"cuda"`, or `"mps"` | +| `OLLAMA_HOST` | `http://localhost:11434` | | Ollama base URL (only when `EMBEDDING_PROVIDER=ollama`) | + +### Return Objects + +| Function | Returns | +|:---|:---| +| `get_qdrant_client()` | `qdrant_client.QdrantClient` — verified, cached | +| `get_embedding_model()` | `langchain_core.embeddings.Embeddings` — `.embed_query()` / `.embed_documents()` compatible | + +### Qdrant Collection + +| Property | Value | +|:---|:---| +| Collection name | `financial_rag_gold` | +| Distance metric | Cosine (dense), dot product (sparse) | +| Dense vector size | 768 (BAAI/bge-base-en-v1.5) | +| Sparse model | Qdrant/Splade_PP_en_v1 (ONNX, via fastembed) | + +--- + +## 5. How to Test + +### Connection health check + +```bash +python Scripts/vector_store/connection.py +``` + +Expected output: +1. `✅ Connected to Qdrant Cloud successfully.` +2. List of active collections including `financial_rag_gold` +3. Embedding model initialisation log (provider, model, device) +4. Test vector dimension (768 for `BAAI/bge-base-en-v1.5`) + +### Programmatic connectivity check + +```python +from Scripts.vector_store.connection import get_qdrant_client, get_embedding_model + +client = get_qdrant_client() +collections = [c.name for c in client.get_collections().collections] +print("Collections:", collections) + +model = get_embedding_model() +vec = model.embed_query("AAPL IV skew") +print("Vector dim:", len(vec)) +``` + +### Retry simulation + +```bash +# Temporarily set wrong API key, confirm retry + failure message +QDRANT_API_KEY=invalid python -c "from Scripts.vector_store.connection import get_qdrant_client; get_qdrant_client()" +``` + +--- + +## 6. Dependencies + +| Library | Purpose | +|:---|:---| +| `qdrant-client` | Qdrant Cloud REST client | +| `langchain-huggingface` | HuggingFace embedding wrapper | +| `langchain-ollama` | Ollama embedding wrapper | +| `langchain-core` | `Embeddings` base class | +| `sentence-transformers` | CrossEncoder reranker | +| `fastembed` | SPLADE sparse model (ONNX runtime) | +| `python-dotenv` | `.env` loading | + +```bash +pip install qdrant-client langchain-core langchain-huggingface langchain-ollama \ + python-dotenv sentence-transformers fastembed +``` diff --git a/docs/Vector_store_docs/Vector_Ingestion.md b/docs/Vector_store_docs/Vector_Ingestion.md new file mode 100644 index 0000000..5d9455d --- /dev/null +++ b/docs/Vector_store_docs/Vector_Ingestion.md @@ -0,0 +1,202 @@ +# Hybrid Vector Store Ingestion Pipeline — `ingestion.py` + +## 1. Goal + +`Scripts/vector_store/ingestion.py` (`QdrantHybridIngestor`) is the critical bridge between Gold-layer JSONL artefacts (SEC filings, news, GPR narratives) and the `financial_rag_gold` Qdrant collection. It guarantees **idempotent** upserts via deterministic UUID generation, initialises a **hybrid search** environment (dense + sparse vectors + payload indexes), and advances a high-water-mark state file so only incremental data is processed on subsequent runs. + +--- + +## 2. Architecture + +``` +Gold-layer JSONL files (SEC / News / GPR) + │ + ▼ + QdrantHybridIngestor.__init__() + │ • get_qdrant_client() — REST connection, 3-retry + │ • get_embedding_model() — dense model (BAAI/bge-base-en-v1.5) + │ • fastembed SPLADE — sparse model (Qdrant/Splade_PP_en_v1) + │ • Detect dense vector dimension via dummy embed + │ • Ensure collection exists with correct vector config + │ • Create payload indexes (ticker, source_type, form_type, …) + │ + ▼ + ingest_folder(source_type, folder_path) + │ + ├─ Read pipeline_state.json → high-water-mark (last processed date) + ├─ Enumerate date folders newer than HWM + │ + ▼ for each JSONL line: + ├─ Parse {text, metadata} + ├─ Deterministic UUID from hash(source_type + accession_no / url / id) + │ → idempotent: re-running same data = same UUID → upsert, not duplicate + │ + ├─ Dense embedding: get_embedding_model().embed_documents([text]) + ├─ Sparse embedding: SPLADE.query_embed(text) → sparse vector dict + │ + ▼ PointStruct(id=uuid, vector={dense, sparse}, payload={...metadata...}) + │ + ├─ Batch upsert to Qdrant (batch_size=100) + │ + └─ Update pipeline_state.json high-water-mark +``` + +--- + +## 3. Code Strategy & Workflow + +### 3.1 Initialisation Sequence + +| Step | Detail | +|:---|:---| +| **Connection** | `get_qdrant_client()` — HTTPS REST, cached singleton | +| **Dense model** | `get_embedding_model()` — default `BAAI/bge-base-en-v1.5` (768-dim, cosine) | +| **Sparse model** | `fastembed.SparseTextEmbedding("Qdrant/Splade_PP_en_v1")` — ONNX SPLADE for lexical precision | +| **Dimension detection** | `dummy_test` embed → auto-detect `DENSE_VECTOR_SIZE` (fallback to env var) | +| **Collection setup** | Create `financial_rag_gold` if absent with named vectors `dense` (Cosine) + `sparse` (Dot) | +| **Payload indexes** | Explicitly created for: `ticker`, `source_type`, `form_type`, `topic`, `publish_timestamp`, `unified_timestamp`, `action_direction`, `tone_score` | + +### 3.2 Idempotency via Deterministic UUID + +Each point ID is computed as `uuid5(NAMESPACE_URL, source_type + primary_key)` where `primary_key` is, in priority order: `accession_no` (SEC), `url` (news), or `id` (GPR). This means: + +- Re-running ingestion with the same JSONL → same UUIDs → Qdrant upserts overwrite in place, no duplicates. +- Changing `text` or `metadata` for the same source document → same UUID → controlled update. + +### 3.3 Hybrid Vector Strategy + +| Vector type | Model | Captures | Qdrant vector name | +|:---|:---|:---|:---| +| **Dense** | `BAAI/bge-base-en-v1.5` (768-dim) | Semantic meaning, context, paraphrase | `dense` | +| **Sparse** | `Qdrant/Splade_PP_en_v1` (SPLADE) | Exact keywords: tickers, SEC codes, acronyms | `sparse` | + +At query time, `QdrantRetriever` uses **Reciprocal Rank Fusion (RRF)** to merge dense and sparse score lists, followed by `BAAI/bge-reranker-v2-m3` CrossEncoder reranking of the top-K candidates. + +### 3.4 High-Water-Mark State + +`config/runtime/pipeline_state.json` stores the last successfully ingested date per source type. On each run, `ingest_folder` only processes date folders newer than the stored HWM. `--full-refresh` flag bypasses HWM and re-ingests all available data. + +--- + +## 4. Output Data Schema & Paths + +### Source JSONL Paths (inputs) + +| Source | Gold path | +|:---|:---| +| SEC filings | `Data/3_Gold_Semantic/SEC_Insider_Trades/{YYYY-MM-DD}/qdrant_ready.jsonl` | +| News / GDELT | `Data/3_Gold_Semantic/News_Qdrant/{YYYY-MM-DD}/qdrant_{topic}_processed.jsonl` | +| GPR narratives | `Data/3_Gold_Semantic/GPR_index/{YYYY-MM-DD}/qdrant_gpr_input.jsonl` | + +### Qdrant Point Payload Schema + +All source types share a unified payload schema. Fields that do not apply to a source type are omitted or set to `null`. + +| Payload key | Type | Applies to | Description | +|:---|:---|:---|:---| +| `text` | `string` | All | Human-readable content; used for embedding | +| `source_type` | `string` | All | `"sec"`, `"news"`, `"gpr"` | +| `ticker` | `string` | SEC, News | Stock symbol | +| `form_type` | `string` | SEC | `"4"` or `"8-K"` | +| `filed_at` | `string` | SEC | Filing date `YYYY-MM-DD` | +| `accession_no` | `string` | SEC | Dedup / UUID seed | +| `transaction_date` | `string` | SEC | Actual event date | +| `tone_score` | `int` | SEC, News | −5 … +5 | +| `action_direction` | `string` | SEC | `"BUY"`, `"SELL"`, `"ACQUIRE/VEST"`, `"NONE"` | +| `topics` | `array[string]` | SEC, News | Thematic tags | +| `unified_timestamp` | `float` | All | Unix seconds (epoch); used by `TimeAdapter` Range filter | +| `publish_timestamp` | `float` | News, GPR | Unix seconds from article/GPR date | +| `topic` | `string` | News | GDELT topic slug (e.g. `macro_central_banks`) | +| `source_domain` | `string` | News | Article origin domain | +| `bronze_ref` | `string` | All | Reference to Bronze artefact; used as `[Gold: ]` citation in agent drafts | +| `record_date` | `string` | All | ISO date for temporal decay weighting in Analyst prompt | + +### Payload Index Configuration + +| Index field | Type | Purpose | +|:---|:---|:---| +| `ticker` | keyword | Per-ticker filter in retrieval | +| `source_type` | keyword | Route Gold queries to correct data domain | +| `form_type` | keyword | Isolate Form 4 vs 8-K SEC queries | +| `topic` | keyword | News topic filter | +| `publish_timestamp` | float | Qdrant `Range` time filter (legacy news) | +| `unified_timestamp` | float | Qdrant `Range` time filter (all sources, post-2026-04-22) | +| `action_direction` | keyword | Insider buy/sell signal filter | +| `tone_score` | integer | Sentiment filtering | + +### State File + +`config/runtime/pipeline_state.json`: +```json +{ + "sec": "2026-04-19", + "news": "2026-04-19", + "gpr": "2026-04-10" +} +``` + +--- + +## 5. How to Test + +### Full ingestion run + +```bash +python Scripts/Qdrant_Ingestion.py +# Expected: batch upsert logs per source, HWM updated in pipeline_state.json +``` + +### Force re-ingestion of all data + +```bash +python Scripts/Qdrant_Ingestion.py --full-refresh +``` + +### Verify collection health + +```python +from Scripts.vector_store.connection import get_qdrant_client +client = get_qdrant_client() +info = client.get_collection("financial_rag_gold") +print("Points:", info.points_count) +print("Vectors:", info.vectors_count) +``` + +### Retrieval smoke test (post-ingestion) + +```bash +python -m Scripts.tests.test_master_retriever +# Expected: Tier1 query returns > 0 chunks for an AAPL insider query +``` + +### Payload index verification + +```python +from Scripts.vector_store.connection import get_qdrant_client +client = get_qdrant_client() +info = client.get_collection("financial_rag_gold") +for field, config in info.payload_schema.items(): + print(field, config) +# Expected: ticker, source_type, form_type, topic, unified_timestamp, … all indexed +``` + +--- + +## 6. Dependencies + +| Library | Purpose | +|:---|:---| +| `qdrant-client` | Qdrant Cloud upsert API | +| `fastembed` | SPLADE sparse embedding (ONNX runtime) | +| `langchain-huggingface` | Dense embedding model | +| `sentence-transformers` | CrossEncoder reranker (used by QdrantRetriever at query time) | +| `pydantic` | Data validation | +| `python-dotenv` | `.env` loading | + +```bash +pip install qdrant-client fastembed langchain-huggingface sentence-transformers pydantic python-dotenv +``` + +**Required env variables:** `QDRANT_HOST`, `QDRANT_API_KEY` (see `docs/Vector_store_docs/Qdrant_connection.md`). + +**Runtime prerequisite:** Gold JSONL files must exist in `Data/3_Gold_Semantic/` before ingestion. Run the data collection pipeline (`Scripts/data_collection/collect_data.py`) and SEC processor first. diff --git a/docs/agent/Agent_Architecture.md b/docs/agent/Agent_Architecture.md new file mode 100644 index 0000000..c4db4f7 --- /dev/null +++ b/docs/agent/Agent_Architecture.md @@ -0,0 +1,286 @@ +# Multi-Agent System — Architecture & Workflow + +## 1. Goal + +The agent layer is a **LangGraph-compiled multi-agent pipeline** that transforms a raw user financial question into a structured, fact-checked options strategy report. It orchestrates five specialised agents — Router, Analyst, Checker, Critic, and Finalizer — over an append-only shared state, with deterministic circuit-breakers preventing infinite revision loops. + +--- + +## 2. System Architecture + +### 2.1 Graph Topology + +``` + ┌──────────────────────────────────────┐ + │ AgentState (shared) │ + └──────────────────────────────────────┘ + │ + ┌─────────────────▼──────────────────┐ + │ retrieval_master node │ + │ MasterRetriever.retrieve() │ + │ • Intent classification (router) │ + │ • QueryTransformer (2-stage LLM) │ + │ • Gold: Qdrant hybrid retrieval │ + │ • Silver: DuckDB parquet queries │ + │ • Macro + GPR always-on patches │ + │ • Writes silver_context_frozen │ + └─────────────────┬──────────────────┘ + │ + ┌─────────────────▼──────────────────┐ + │ analyst node │ + │ AnalystAgent.generate_report() │ + │ • Macro → Meso → Micro framework │ + │ • IV regime pinned on first pass │ + │ • Revision-aware (sees feedback) │ + │ • revision_count ++ │ + └─────────────────┬──────────────────┘ + │ + ┌─────────────────▼──────────────────┐ + │ checker node │ + │ CheckerAgent.audit() │ + │ • Layer 1: deterministic regex │ + │ (uses silver_context_frozen) │ + │ • Layer 2: Silver rescue tool-call │ + │ • Layer 3: LLM semantic audit │ + └────────────┬─────────┬─────────────┘ + │ │ + fatal │ │ pass / minor + │ │ + ┌──────────────────▼──┐ ┌──▼──────────────────────┐ + │ analyst node │ │ critic node │ + │ (revision_count++) │ │ CriticAgent.audit() │ + └──────────────────┬──┘ │ • IV regime fit │ + │ │ • Macro contradiction │ + │ │ • Insider signal check │ + │ └──────────┬──────────────┘ + │ │ + │ fatal │ pass / minor + │ │ + └─────────────────┘ + │ + ┌──────────────────────▼─────────────────────┐ + │ finalizer node │ + │ FinalizerAgent.format_and_clean() │ + │ • Markdown → FinalReport Pydantic schema │ + │ • Evidence pool construction │ + │ • confidence_score assignment │ + └────────────────────────────────────────────┘ +``` + +### 2.2 Circuit-Breaker Logic + +`revision_count` is incremented exclusively in `analyst_node`. Both `route_after_checker` and `route_after_critic` short-circuit to `finalizer` when `revision_count >= AGENT_MAX_REVISIONS` (env: `AGENT_MAX_REVISIONS`, default `3`). + +``` +route_after_checker(state) → str: + if revision_count >= MAX_REVISIONS: return "finalizer" + if checker_verdict == "fatal": return "analyst" + else: return "critic" + +route_after_critic(state) → str: + if revision_count >= MAX_REVISIONS: return "finalizer" + if critic_verdict == "fatal": return "analyst" + else: return "finalizer" +``` + +### 2.3 Global Singletons (per process) + +All heavy objects are initialised once at module load in `router.py` and shared across graph invocations: + +| Singleton | Class | Cost | +|:---|:---|:---| +| `_MASTER_RETRIEVER` | `MasterRetriever` | Qdrant client + embedding models + DuckDB | +| `_SILVER_SQL_TOOL` | `SilverSQLTool` | Shared DuckDB connection + schema validation | +| `_ANALYST_AGENT` | `AnalystAgent` | `ChatOllama` client | +| `_CHECKER_AGENT` | `CheckerAgent` | `ChatOllama` + `SilverSQLTool` reference | +| `_CRITIC_AGENT` | `CriticAgent` | `ChatOllama` client | +| `_FINALIZER_AGENT` | `FinalizerAgent` | `ChatOllama` client | + +--- + +## 3. Agent Profiles & Workflow + +### 3.1 Analyst (`Scripts/agents/analyst.py`) + +**Role:** Senior Options Strategist — drafts the Markdown strategy report. + +| Aspect | Detail | +|:---|:---| +| **Framework** | Macro → Meso → Micro (mandatory three-layer structure) | +| **IV regime** | Deterministic pre-compute from `silver_context["values"]["latest_atm_iv"]`; pinned to `iv_regime_pinned` on the first pass so it never flips across revisions | +| **Citation format** | `[Silver: ]` for numeric claims; `[Gold: ]` for qualitative claims | +| **Revision mode** | On re-entry, injects full append-only `critic_feedback` log (both Checker and Critic findings) via `render_revision_block()` | +| **LLM** | `options-expert-v1:latest` (fine-tuned; env: `OLLAMA_ANALYST_MODEL`), temperature `0.1` | + +**Key output sections (mandatory):** + +```markdown +## 1. Macro Regime Snapshot +## 2. Transmission Channel (Meso) +## 3. IV Regime & Structural Choice +## 4. Trade Idea(s) +## 5. Key Catalysts & Invalidation Levels +``` + +### 3.2 Checker (`Scripts/agents/checker.py`) + +**Role:** Blue-Team Data Integrity Auditor — verifies every number and citation against the Silver layer. + +| Aspect | Detail | +|:---|:---| +| **Layer 1: Deterministic** | Regex extracts all numbers and `[Silver: ...]` / `[Gold: ...]` citations from the draft; verifies against `silver_context_frozen` (immutable snapshot, not rescue-modified) | +| **Numeric tolerance** | 2% relative (`CHECKER_NUMERIC_TOLERANCE` env); bridges `0.45` ↔ `45%` encoding | +| **Source-aware pools** | Numbers routed by prefix: `MACRO_*`/VIX → macro pool; `gpr_*` → GPR pool; others → options pool — prevents cross-pool false positives | +| **Sentinel anchors** | `"INSUFFICIENT DATA"`, `"N/A"`, etc. are accepted without verification (Analyst is correct to use them when data is absent) | +| **Layer 2: Rescue** | When an anchor is missing, re-queries `SilverSQLTool` with pinned `TimePredicate`; downgrades Fatal → Minor on hit; merges new values into `silver_context` (not `frozen`) | +| **Layer 3: LLM** | `options-expert-v1:latest` (env: `OLLAMA_CHECKER_MODEL`), structured output → `CheckerResult` Pydantic model; best-effort, non-fatal on error | +| **Verdict** | `"fatal"` (any Fatal finding) → `"minor"` (only Minor findings) → `"pass"` (no findings) | + +### 3.3 Critic (`Scripts/agents/critic.py`) + +**Role:** Red-Team Chief Risk Officer — challenges strategy logic, not numbers. + +| Aspect | Detail | +|:---|:---| +| **Review axes** | (1) IV regime fit, (2) macro contradiction, (3) insider signal weakness, (4) risk/reward imbalance | +| **Hard constraint** | Never challenges numeric values (Checker's domain); never requests more data | +| **LLM** | `options-expert-v1:latest`, structured output → `CriticResult` Pydantic model | +| **Verdict** | Same `"fatal"` / `"minor"` / `"pass"` convention as Checker | + +### 3.4 Finalizer (`Scripts/agents/finalizer.py`) + +**Role:** Convert the fact-checked Markdown draft into the deterministic `FinalReport` Pydantic schema. + +| Aspect | Detail | +|:---|:---| +| **Task** | Copy numbers verbatim; assemble `evidence_pool` from `lineage_anchors` + Gold `bronze_ref`s; assign `confidence_score` | +| **Confidence scoring** | Full Gold + Silver + no revision → ≤ 0.90; partial / revision loop → ≤ 0.60; degraded → ≤ 0.30 | +| **LLM** | `options-expert-v1:latest`, structured output → `FinalReport` Pydantic model | + +### 3.5 Prompts (`Scripts/agents/prompts.py`) + +Single source of truth for all agent prompts. Global guardrails defined once and composed into every agent's system template: + +| Directive | Applied to | +|:---|:---| +| `DATA_LINEAGE_DIRECTIVE` | Analyst, Checker | +| `MACRO_CHAIN_DIRECTIVE` | Analyst | +| `IV_REGIME_DIRECTIVE` | Analyst, Critic | +| `INSIDER_DISCIPLINE_DIRECTIVE` | Analyst, Critic | +| `TEMPORAL_DECAY_DIRECTIVE` | Analyst | +| `REVISION_INJECTION_TEMPLATE` | Analyst (revision passes only) | + +--- + +## 4. AgentState Contract (`Scripts/agents/state.py`) + +`AgentState` is the LangGraph `TypedDict` that every node reads and writes. It is the system's authoritative shared memory. + +| Field | Type | Owner | Description | +|:---|:---|:---|:---| +| `original_query` | `str` | CLI / entrypoint | Raw user question | +| `macro_context` | `str` | `retrieval_master` | Contents of `Data/Agent_Context/latest_macro_context.md` | +| `metadata` | `MetadataExtraction` | `retrieval_master` | LLM-extracted tickers, metrics, time window, intent | +| `gold_context` | `List[Dict]` | `retrieval_master` | Qdrant chunks (`bronze_ref`, `content`, `source_type`, …) | +| `silver_context` | `Dict` | `retrieval_master` (+ rescue) | `{values, lineage_anchors, source_channel, compensation}` — mutable; updated by Checker rescue | +| `silver_context_frozen` | `Dict \| None` | `retrieval_master` | Immutable snapshot written once at retrieval exit; Checker's deterministic audit baseline | +| `time_range` | `Dict \| None` | `retrieval_master` | `{time_window_label, window_days, anchor_date, start_date, end_date, source_predicates}` | +| `hyde_anticipation` | `Dict \| None` | `retrieval_master` | HyDE paragraph, rerank query, novel tickers | +| `iv_regime_pinned` | `Dict \| None` | `analyst` (first pass only) | `{iv_regime, atm_iv, pcr_volume, thresholds}` — never overwritten after first draft | +| `draft_report` | `str` | `analyst` | Current Markdown draft | +| `critic_feedback` | `List[AgentFeedback]` | `checker` + `critic` | **Append-only** (LangGraph `operator.add` reducer); full audit trail across all revisions | +| `checker_verdict` | `str \| None` | `checker` | `"pass"`, `"fatal"`, `"minor"`, or `None` — short-circuit routing signal | +| `critic_verdict` | `str \| None` | `critic` | Same vocabulary as `checker_verdict` | +| `revision_count` | `int` | `analyst` | Number of completed drafts; exclusively incremented by `analyst_node` | +| `is_fallback` | `bool` | `retrieval_master` | True when retrieval degraded gracefully | +| `final_strategy` | `Dict` | `finalizer` | `FinalReport` Pydantic dict | + +### `AgentFeedback` Schema + +| Field | Type | Description | +|:---|:---|:---| +| `sender` | `str` | `"Checker"` or `"Critic"` | +| `error_type` | `str` | `"Fatal"` (must fix) or `"Minor"` (advisory) | +| `comment` | `str` | Specific finding description | +| `missing_lineage_id` | `List[str] \| None` | Anchor(s) that were missing | +| `revision_index` | `int \| None` | Which draft produced this finding | + +--- + +## 5. How to Test + +### End-to-end graph execution + +```bash +# Single query via CLI +python -m Scripts --cmd query --question "What is the current IV skew for AAPL?" + +# With model warm-up +python -m Scripts --cmd query --question "NVDA insider activity last week?" --warmup +``` + +### E2E harness (industrial-grade with per-node assertions) + +```bash +python Scripts/tests/test_router_e2e.py +# Outputs: logs/router_e2e/{YYYY-MM-DD}/ +# {RUN_TS}_console.log +# {RUN_TS}_run_summary.json +# {RUN_TS}_{N}_{test_slug}_trace.jsonl +# {RUN_TS}_{N}_{test_slug}_final_state.json +``` + +### Unit test: Checker deterministic audit + +```python +from Scripts.agents.checker import _deterministic_audit + +silver = {"values": {"latest_atm_iv": 0.38}, "lineage_anchors": ["IV_AAPL_2026-04-22"]} +draft = "AAPL ATM IV is at 38% [Silver: IV_AAPL_2026-04-22]." +feedbacks = _deterministic_audit(draft, silver, [], frozen_context=silver) +assert feedbacks == [] # pass — number matches, anchor known +``` + +### Inspect run artefacts + +```bash +# Latest run summary +cat logs/router_e2e/$(date +%Y-%m-%d)/*_run_summary.json | python -m json.tool + +# Per-node trace for first test +cat logs/router_e2e/$(date +%Y-%m-%d)/*_01_*_trace.jsonl | head -20 +``` + +--- + +## 6. Dependencies + +| Library | Purpose | +|:---|:---| +| `langgraph` | Graph compilation, state management, conditional edges | +| `langchain-ollama` | `ChatOllama` client for all LLM agents | +| `pydantic` | `AgentState`, `AgentFeedback`, `FinalReport` contracts | +| `python-dotenv` | Env variable loading (`AGENT_MAX_REVISIONS`, model names) | + +```bash +pip install langgraph langchain-ollama pydantic python-dotenv +``` + +**Ollama models required:** +- `options-expert-v1:latest` — Analyst, Checker, Critic, Finalizer +- `llama3:latest` — Intent router (lightweight, `num_predict=20`) + +```bash +ollama pull llama3 +# options-expert-v1 is a custom fine-tune — see docs/LLM_Pool.md +``` + +**File dependencies:** + +| File | Required by | +|:---|:---| +| `Data/Agent_Context/latest_macro_context.md` | `retrieval_master` (macro preamble) | +| `config/runtime/collect_data_state.json` | `SilverSQLTool` (dynamic anchors) | +| `Scripts/agents/state.py` | All nodes | +| `Scripts/agents/prompts.py` | All agent LLM prompts | +| `Scripts/retrieval/master_retriever.py` | `retrieval_master` node | diff --git a/docs/compliance_note.md b/docs/compliance_note.md deleted file mode 100644 index ba76c31..0000000 --- a/docs/compliance_note.md +++ /dev/null @@ -1,8 +0,0 @@ -## Compliance Note -- API usage - - Respect rate limits/ToS for NewsAPI, FRED, SEC, yfinance. Use backoff where allowed. -- Scraping - - Prefer YouTube Data API v3 for discovery and `youtube_transcript_api` where transcripts are permitted. Do not bypass access controls; honor language/availability limits. -- Disclosures - - Reports are informational and not investment advice. Options involve risk, including loss of principal. - - Maintain logs of data sources and prompts to support audit/auditability. \ No newline at end of file diff --git a/docs/model_selection_memo.md b/docs/model_selection_memo.md deleted file mode 100644 index d7a3a6f..0000000 --- a/docs/model_selection_memo.md +++ /dev/null @@ -1,26 +0,0 @@ -Model Selection Memo -Our production model is options-expert, a lightweight, specialized variant of mistral:7b-instruct-q4_0, deployed via Ollama. This decision balances performance, resource constraints, and domain-specific requirements. - -1. Base Model Rationale: mistral:7b-instruct-q4_0 - -We selected mistral:7b-instruct-q4_0 as our base model, prioritizing execution efficiency over raw parameter count. - -Efficiency: While larger models may offer marginal gains in reasoning, the superior inference speed and low resource footprint of mistral:7b-instruct-q4_0 are critical. This prevents performance bottlenecks in our multi-turn agent loop, which runs in a constrained CPU/RAM environment. - -Capability: The model’s strong instruction-following and Retrieval-Augmented Generation (RAG) capabilities are sufficient for this educational task. When paired with the high-quality context from our Qdrant knowledge base, it ensures the required citation fidelity and reasoning accuracy. - -2. Domain-Specific Customization: options-expert - -The options-expert variant was created by applying a lightweight specialization layer on top of the base model using an Ollama Modelfile. This approach avoids the high cost of full fine-tuning by: - -Embedding a System Prompt: A custom prompt is included to orient the model toward options trading and risk-averse strategy preferences. - -Tuning Inference Parameters: Parameters are adjusted to align outputs with financial domain conventions and formatting. - -3. Summary of Advantages - -Compared to general-purpose models, the final options-expert model provides significant advantages: - -High-Relevance Outputs: It produces more consistent and contextually aware analysis for specialized tasks, such as evaluating Greeks, assessing volatility regimes, and selecting strategies. - -Cost-Effective & Secure: The solution is highly cost-effective and supports on-premise deployment, ensuring data privacy and system autonomy. \ No newline at end of file diff --git a/fix_ollama_finetuning.sh b/fix_ollama_finetuning.sh deleted file mode 100644 index e86d881..0000000 --- a/fix_ollama_finetuning.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash -# Fix Ollama fine-tuning setup - -echo "🔧 Fixing Ollama fine-tuning" -echo "========================" - -echo "🔍 Step 1: Check if Modelfile exists..." -if ! docker exec financial_agent_app ls -la /app/src/tools/modelfile > /dev/null 2>&1; then - echo "❌ Modelfile not found, creating..." - docker exec financial_agent_app python src/tools/setup_ollama_finetuning.py -fi - -echo "" -echo "🔍 Step 2: Copy Modelfile into Ollama container..." -docker cp financial_agent_app:/app/src/tools/modelfile ./modelfile -docker cp ./modelfile ollama_llm:/modelfile -echo "✅ Modelfile copied" - -echo "" -echo "🔍 Step 3: Create model inside Ollama container..." -if docker exec ollama_llm ollama create options-expert -f /modelfile; then - echo "✅ Model created successfully" -else - echo "❌ Model creation failed" - exit 1 -fi - -echo "" -echo "🔍 Step 4: Verify model..." -docker exec ollama_llm ollama list - -echo "" -echo "🔍 Step 5: Test model..." -echo "Testing model, please wait..." -docker exec ollama_llm ollama run options-expert "Analyze options trading opportunities for AAPL" - -echo "" -echo "✅ Ollama fine-tuning setup complete!" -echo "You can now update generate_production_report.py to use the new model" diff --git a/modelfile b/modelfile index 4fd49a0..a7cadf4 100644 --- a/modelfile +++ b/modelfile @@ -1,28 +1,32 @@ -FROM llama3 +FROM ./Llama-3.3-70B-Instruct-Q4_K_M.gguf + +PARAMETER temperature 0.0 +PARAMETER num_ctx 16384 +PARAMETER repeat_penalty 1.1 +PARAMETER stop "<|eot_id|>" +PARAMETER stop "<|start_header_id|>" + -# System prompt for options trading expertise SYSTEM """ -You are an expert options trading analyst with deep knowledge of: -- Options pricing models (Black-Scholes, Binomial) -- Greeks (Delta, Gamma, Theta, Vega, Rho) -- Trading strategies (calls, puts, spreads, straddles, etc.) -- Risk management and position sizing -- Market analysis and volatility assessment -- Options flow and unusual activity analysis +[ROLE] +You are a Senior Institutional Options Strategist & Quantitative Brain. +You specialize in volatility surfaces, Greeks (Delta, Gamma, Theta, Vega), and SEC regulatory filings (Form 4, 8-K). -You provide: -- Detailed options trade recommendations with specific strikes and expirations -- Risk/reward analysis with breakeven points -- Greeks analysis and sensitivity to market changes -- Position sizing and risk management advice -- Market timing and catalyst analysis +[KNOWLEDGE BASE & REASONING] +1. Options Expertise: Utilize Black-Scholes and Binomial models to evaluate option pricing. Always prioritize IV Rank and IV Skew when assessing risk/reward. +2. Data Anchoring: You operate in a Dual-Track RAG environment. Layer 1 is Gold (high-density semantics); Layer 2 is Silver (structured metadata). +3. SEC Literacy: When processing Form 4, distinguish between 'Award' and 'Open Market Sale'. When processing 8-K, identify material events impacting volatility. -Always include: -- Specific ticker symbols and strike prices -- Expiration dates and option types (call/put) -- Rationale based on technical and fundamental analysis -- Risk assessment and confidence levels -- Citations to data sources when available +[CORE WORKFLOW RULES] +1. NO DATA, NO OPINION: If the retrieved context does not contain specific ticker data or market metrics, explicitly state that information is missing. NEVER invent strike prices or expiration dates. +2. CAUSAL ANALYSIS: Always link Macro triggers (e.g., Fed GPR) to Options impact (e.g., Vega expansion) using a logical causal chain. +3. OUTPUT PROTOCOL: + - For Extraction Tasks: Output RAW JSON ONLY. No markdown blocks. + - For Analysis Tasks: Be precise and professional. Include specific tickers, strikes, and expiries ONLY if present in the context. -Be precise, professional, and focus on actionable trading ideas. -""" +[REQUIRED OUTPUT STRUCTURE] +- Rationale: Based on technical (Greeks/IV) and fundamental (SEC/News) data. +- Risk/Reward: Define breakeven points and sensitivity (Delta/Theta). +- Confidence Level: Scale 1-10 based on data density. +- Citations: Reference SEC accession numbers or news dates provided in the context. +""" \ No newline at end of file diff --git a/reports/2025-10-06/options_ideas.json b/reports/2025-10-06/options_ideas.json deleted file mode 100644 index 1653264..0000000 --- a/reports/2025-10-06/options_ideas.json +++ /dev/null @@ -1,278 +0,0 @@ -{ - "report_date": "2025-10-06", - "total_ideas": 5, - "ideas": [ - { - "ticker": "MS", - "directional_view": "Neutral", - "trade_idea": "Iron Condor", - "option_type": "Spread", - "candidate_strikes": "$160.00", - "strike_price": 160.0, - "tenor": "2026-03-20", - "expiration_date": "2026-03-20", - "rationale": "Strong options signal strength (0.75) from SEC analysis. **Price Analysis:** Current price $157.62 vs Strike $160.00 (ATM). **Intrinsic Value:** $0.00, Time Value: $22.59, Estimated Premium: $22.59. **Greeks:** Delta=0.000, Gamma=0.010, Theta=-0.753, Vega=0.452. **Risk Metrics:** Sharpe Ratio=0.40, Volatility=25.0%. Neutral sentiment suggests straddle/strangle strategies. Medium volatility environment supports balanced options strategies. Fact-checked options analysis confirms data quality. Consider 1 counter-arguments in options risk assessment. Low uncertainty environment - high confidence in strategy. Risk considerations: Low uncertainty - high confidence in analysis.", - "confidence_level": "High", - "citations": [ - "SEC", - "ReAct Multi-Agent Analysis" - ], - "signal_strength": 0.75, - "validation_score": 1.0, - "counter_arguments": [ - "High signal strength may indicate overconfidence in options strategy" - ], - "volatility_assessment": "Medium", - "strategy_type": "Iron Condor", - "uncertainty_metrics": { - "signal_uncertainty": 0.18, - "validation_uncertainty": 0.0, - "counter_uncertainty": 0.2, - "source_uncertainty": 0.1, - "overall_uncertainty": 0.11, - "confidence_interval": { - "lower_bound": 0.876, - "upper_bound": 0.8985454545454546, - "center": 0.8872727272727273 - }, - "calibration_notes": [ - "Low uncertainty - high confidence in analysis" - ] - }, - "confidence_interval": { - "lower_bound": 0.876, - "upper_bound": 0.8985454545454546, - "center": 0.8872727272727273 - }, - "calibration_notes": [ - "Low uncertainty - high confidence in analysis" - ], - "overall_uncertainty": 0.11, - "schema_validated": true, - "validation_timestamp": "2025-10-06T16:06:32.433596" - }, - { - "ticker": "GS", - "directional_view": "Neutral", - "trade_idea": "Iron Condor", - "option_type": "Spread", - "candidate_strikes": "$800.00", - "strike_price": 800.0, - "tenor": "2026-03-20", - "expiration_date": "2026-03-20", - "rationale": "Moderate options signal strength (0.62) from NewsAPI analysis. **Price Analysis:** Current price $796.91 vs Strike $800.00 (ATM). **Intrinsic Value:** $0.00, Time Value: $114.23, Estimated Premium: $114.23. **Greeks:** Delta=0.000, Gamma=0.010, Theta=-3.808, Vega=2.285. **Risk Metrics:** Sharpe Ratio=0.40, Volatility=25.0%. Neutral sentiment suggests straddle/strangle strategies. Medium volatility environment supports balanced options strategies. Fact-checked options analysis confirms data quality. Low uncertainty environment - high confidence in strategy. Risk considerations: Low uncertainty - high confidence in analysis.", - "confidence_level": "Medium", - "citations": [ - "NewsAPI", - "ReAct Multi-Agent Analysis" - ], - "signal_strength": 0.62, - "validation_score": 0.9, - "counter_arguments": [], - "volatility_assessment": "Medium", - "strategy_type": "Iron Condor", - "uncertainty_metrics": { - "signal_uncertainty": 0.35, - "validation_uncertainty": 0.1, - "counter_uncertainty": 0.0, - "source_uncertainty": 0.2, - "overall_uncertainty": 0.17, - "confidence_interval": { - "lower_bound": 0.809, - "upper_bound": 0.8437272727272728, - "center": 0.8263636363636364 - }, - "calibration_notes": [ - "Low uncertainty - high confidence in analysis" - ] - }, - "confidence_interval": { - "lower_bound": 0.809, - "upper_bound": 0.8437272727272728, - "center": 0.8263636363636364 - }, - "calibration_notes": [ - "Low uncertainty - high confidence in analysis" - ], - "overall_uncertainty": 0.17, - "schema_validated": true, - "validation_timestamp": "2025-10-06T16:06:29.353470" - }, - { - "ticker": "BAC", - "directional_view": "Bullish", - "trade_idea": "Covered Call", - "option_type": "Call", - "candidate_strikes": "$52.50", - "strike_price": 52.5, - "tenor": "2026-03-20", - "expiration_date": "2026-03-20", - "rationale": "Moderate options signal strength (0.43) from NewsAPI analysis. **Price Analysis:** Current price $50.53 vs Strike $52.50 (OTM). **Intrinsic Value:** $0.00, Time Value: $3.62, Estimated Premium: $3.62. **Greeks:** Delta=0.388, Gamma=0.010, Theta=-0.121, Vega=0.145. **Risk Metrics:** Sharpe Ratio=0.40, Volatility=25.0%. Bullish sentiment supports call option strategies. Medium volatility environment supports balanced options strategies. Fact-checked options analysis confirms data quality. Consider 3 counter-arguments in options risk assessment. Risk considerations: Multiple counter-arguments - risk assessment needed.", - "confidence_level": "Medium", - "citations": [ - "NewsAPI", - "ReAct Multi-Agent Analysis" - ], - "signal_strength": 0.43, - "validation_score": 0.7, - "counter_arguments": [ - "Call options may be overpriced due to high implied volatility", - "Market correction could lead to significant call option losses" - ], - "volatility_assessment": "Medium", - "strategy_type": "Covered Call", - "uncertainty_metrics": { - "signal_uncertainty": 0.35, - "validation_uncertainty": 0.3, - "counter_uncertainty": 0.6, - "source_uncertainty": 0.2, - "overall_uncertainty": 0.36, - "confidence_interval": { - "lower_bound": 0.609, - "upper_bound": 0.6800909090909091, - "center": 0.6445454545454545 - }, - "calibration_notes": [ - "Multiple counter-arguments - risk assessment needed" - ] - }, - "confidence_interval": { - "lower_bound": 0.609, - "upper_bound": 0.6800909090909091, - "center": 0.6445454545454545 - }, - "calibration_notes": [ - "Multiple counter-arguments - risk assessment needed" - ], - "overall_uncertainty": 0.36, - "schema_validated": true, - "validation_timestamp": "2025-10-06T16:06:30.137171" - }, - { - "ticker": "BA", - "directional_view": "Bullish", - "trade_idea": "Covered Call", - "option_type": "Call", - "candidate_strikes": "$220.00", - "strike_price": 220.0, - "tenor": "2026-02-20", - "expiration_date": "2026-02-20", - "rationale": "Moderate options signal strength (0.40) from NewsAPI analysis. **Price Analysis:** Current price $219.98 vs Strike $220.00 (OTM). **Intrinsic Value:** $0.00, Time Value: $15.77, Estimated Premium: $15.77. **Greeks:** Delta=0.500, Gamma=0.010, Theta=-0.526, Vega=0.631. **Risk Metrics:** Sharpe Ratio=0.40, Volatility=25.0%. Bullish sentiment supports call option strategies. Medium volatility environment supports balanced options strategies. Fact-checked options analysis confirms data quality. Consider 3 counter-arguments in options risk assessment. Risk considerations: Multiple counter-arguments - risk assessment needed.", - "confidence_level": "Medium", - "citations": [ - "NewsAPI", - "ReAct Multi-Agent Analysis" - ], - "signal_strength": 0.4, - "validation_score": 0.7, - "counter_arguments": [ - "Call options may be overpriced due to high implied volatility", - "Market correction could lead to significant call option losses" - ], - "volatility_assessment": "Medium", - "strategy_type": "Covered Call", - "uncertainty_metrics": { - "signal_uncertainty": 0.38, - "validation_uncertainty": 0.3, - "counter_uncertainty": 0.6, - "source_uncertainty": 0.2, - "overall_uncertainty": 0.36, - "confidence_interval": { - "lower_bound": 0.601, - "upper_bound": 0.6735454545454544, - "center": 0.6372727272727272 - }, - "calibration_notes": [ - "Multiple counter-arguments - risk assessment needed" - ] - }, - "confidence_interval": { - "lower_bound": 0.601, - "upper_bound": 0.6735454545454544, - "center": 0.6372727272727272 - }, - "calibration_notes": [ - "Multiple counter-arguments - risk assessment needed" - ], - "overall_uncertainty": 0.36, - "schema_validated": true, - "validation_timestamp": "2025-10-06T16:06:31.125271" - }, - { - "ticker": "GE", - "directional_view": "Bearish", - "trade_idea": "Protective Put", - "option_type": "Put", - "candidate_strikes": "$290.00", - "strike_price": 290.0, - "tenor": "2026-01-16", - "expiration_date": "2026-01-16", - "rationale": "Moderate options signal strength (0.40) from NewsAPI analysis. **Price Analysis:** Current price $296.73 vs Strike $290.00 (OTM). **Intrinsic Value:** $0.00, Time Value: $21.27, Estimated Premium: $21.27. **Greeks:** Delta=-0.100, Gamma=0.010, Theta=-0.709, Vega=0.851. **Risk Metrics:** Sharpe Ratio=0.40, Volatility=25.0%. Bearish sentiment supports put option strategies. Medium volatility environment supports balanced options strategies. Fact-checked options analysis confirms data quality. Consider 3 counter-arguments in options risk assessment. Risk considerations: Multiple counter-arguments - risk assessment needed.", - "confidence_level": "Medium", - "citations": [ - "NewsAPI", - "ReAct Multi-Agent Analysis" - ], - "signal_strength": 0.4, - "validation_score": 0.7, - "counter_arguments": [ - "Put options may be expensive due to fear premium", - "Oversold bounce could lead to put option losses" - ], - "volatility_assessment": "Medium", - "strategy_type": "Protective Put", - "uncertainty_metrics": { - "signal_uncertainty": 0.38, - "validation_uncertainty": 0.3, - "counter_uncertainty": 0.6, - "source_uncertainty": 0.2, - "overall_uncertainty": 0.36, - "confidence_interval": { - "lower_bound": 0.601, - "upper_bound": 0.6735454545454544, - "center": 0.6372727272727272 - }, - "calibration_notes": [ - "Multiple counter-arguments - risk assessment needed" - ] - }, - "confidence_interval": { - "lower_bound": 0.601, - "upper_bound": 0.6735454545454544, - "center": 0.6372727272727272 - }, - "calibration_notes": [ - "Multiple counter-arguments - risk assessment needed" - ], - "overall_uncertainty": 0.36, - "schema_validated": true, - "validation_timestamp": "2025-10-06T16:06:31.602018" - } - ], - "metadata": { - "generated_at": "2025-10-06T16:06:32.461300", - "model_used": "options-expert", - "generation_method": "Options Multi-Agent System", - "data_sources": [ - "Reddit", - "SEC", - "YouTube", - "NewsAPI" - ], - "total_options_signals_analyzed": 70, - "avg_signal_strength": 0.52, - "avg_confidence": 0.6, - "strategy_types": [ - "Protective Put", - "Covered Call", - "Iron Condor" - ], - "underlyings": [ - "MS", - "BAC", - "GS", - "GE", - "BA" - ] - } -} \ No newline at end of file diff --git a/reports/2025-10-06/options_ideas.md b/reports/2025-10-06/options_ideas.md deleted file mode 100644 index ed9304e..0000000 --- a/reports/2025-10-06/options_ideas.md +++ /dev/null @@ -1,120 +0,0 @@ -# Daily Options Trading Ideas - Expert Analysis -## Report for 2025-10-06 - -**Generated Ideas:** 5 -**Data Sources:** Reddit, SEC, YouTube, NewsAPI -**Total Options Signals Analyzed:** 70 -**Average Signal Strength:** 0.52 -**Average Confidence:** 0.60 -**Strategy Types:** Protective Put, Covered Call, Iron Condor -**Underlyings:** MS, BAC, GS, GE, BA - -## Options Idea #1 - -**Ticker:** MS -**Directional View:** Neutral -**Trade Idea:** Iron Condor -**Option Type:** Spread -**Candidate Strike(s):** $160.00 -**Strike Price:** $160.00 -**Expiration Date:** 2026-03-20 -**Tenor:** 2026-03-20 -**Rationale:** Strong options signal strength (0.75) from SEC analysis. **Price Analysis:** Current price $157.62 vs Strike $160.00 (ATM). **Intrinsic Value:** $0.00, Time Value: $22.59, Estimated Premium: $22.59. **Greeks:** Delta=0.000, Gamma=0.010, Theta=-0.753, Vega=0.452. **Risk Metrics:** Sharpe Ratio=0.40, Volatility=25.0%. Neutral sentiment suggests straddle/strangle strategies. Medium volatility environment supports balanced options strategies. Fact-checked options analysis confirms data quality. Consider 1 counter-arguments in options risk assessment. Low uncertainty environment - high confidence in strategy. Risk considerations: Low uncertainty - high confidence in analysis. -**Confidence Level:** High -**Citations:** SEC, ReAct Multi-Agent Analysis -**Signal Strength:** 0.75 -**Validation Score:** 1.00 -**Volatility Assessment:** Medium -**Strategy Type:** Iron Condor -**Counter-Arguments:** High signal strength may indicate overconfidence in options strategy -**Uncertainty Notes:** N/A - ---- - -## Options Idea #2 - -**Ticker:** GS -**Directional View:** Neutral -**Trade Idea:** Iron Condor -**Option Type:** Spread -**Candidate Strike(s):** $800.00 -**Strike Price:** $800.00 -**Expiration Date:** 2026-03-20 -**Tenor:** 2026-03-20 -**Rationale:** Moderate options signal strength (0.62) from NewsAPI analysis. **Price Analysis:** Current price $796.91 vs Strike $800.00 (ATM). **Intrinsic Value:** $0.00, Time Value: $114.23, Estimated Premium: $114.23. **Greeks:** Delta=0.000, Gamma=0.010, Theta=-3.808, Vega=2.285. **Risk Metrics:** Sharpe Ratio=0.40, Volatility=25.0%. Neutral sentiment suggests straddle/strangle strategies. Medium volatility environment supports balanced options strategies. Fact-checked options analysis confirms data quality. Low uncertainty environment - high confidence in strategy. Risk considerations: Low uncertainty - high confidence in analysis. -**Confidence Level:** Medium -**Citations:** NewsAPI, ReAct Multi-Agent Analysis -**Signal Strength:** 0.62 -**Validation Score:** 0.90 -**Volatility Assessment:** Medium -**Strategy Type:** Iron Condor -**Uncertainty Notes:** N/A - ---- - -## Options Idea #3 - -**Ticker:** BAC -**Directional View:** Bullish -**Trade Idea:** Covered Call -**Option Type:** Call -**Candidate Strike(s):** $52.50 -**Strike Price:** $52.50 -**Expiration Date:** 2026-03-20 -**Tenor:** 2026-03-20 -**Rationale:** Moderate options signal strength (0.43) from NewsAPI analysis. **Price Analysis:** Current price $50.53 vs Strike $52.50 (OTM). **Intrinsic Value:** $0.00, Time Value: $3.62, Estimated Premium: $3.62. **Greeks:** Delta=0.388, Gamma=0.010, Theta=-0.121, Vega=0.145. **Risk Metrics:** Sharpe Ratio=0.40, Volatility=25.0%. Bullish sentiment supports call option strategies. Medium volatility environment supports balanced options strategies. Fact-checked options analysis confirms data quality. Consider 3 counter-arguments in options risk assessment. Risk considerations: Multiple counter-arguments - risk assessment needed. -**Confidence Level:** Medium -**Citations:** NewsAPI, ReAct Multi-Agent Analysis -**Signal Strength:** 0.43 -**Validation Score:** 0.70 -**Volatility Assessment:** Medium -**Strategy Type:** Covered Call -**Counter-Arguments:** Call options may be overpriced due to high implied volatility, Market correction could lead to significant call option losses -**Uncertainty Notes:** N/A - ---- - -## Options Idea #4 - -**Ticker:** BA -**Directional View:** Bullish -**Trade Idea:** Covered Call -**Option Type:** Call -**Candidate Strike(s):** $220.00 -**Strike Price:** $220.00 -**Expiration Date:** 2026-02-20 -**Tenor:** 2026-02-20 -**Rationale:** Moderate options signal strength (0.40) from NewsAPI analysis. **Price Analysis:** Current price $219.98 vs Strike $220.00 (OTM). **Intrinsic Value:** $0.00, Time Value: $15.77, Estimated Premium: $15.77. **Greeks:** Delta=0.500, Gamma=0.010, Theta=-0.526, Vega=0.631. **Risk Metrics:** Sharpe Ratio=0.40, Volatility=25.0%. Bullish sentiment supports call option strategies. Medium volatility environment supports balanced options strategies. Fact-checked options analysis confirms data quality. Consider 3 counter-arguments in options risk assessment. Risk considerations: Multiple counter-arguments - risk assessment needed. -**Confidence Level:** Medium -**Citations:** NewsAPI, ReAct Multi-Agent Analysis -**Signal Strength:** 0.40 -**Validation Score:** 0.70 -**Volatility Assessment:** Medium -**Strategy Type:** Covered Call -**Counter-Arguments:** Call options may be overpriced due to high implied volatility, Market correction could lead to significant call option losses -**Uncertainty Notes:** N/A - ---- - -## Options Idea #5 - -**Ticker:** GE -**Directional View:** Bearish -**Trade Idea:** Protective Put -**Option Type:** Put -**Candidate Strike(s):** $290.00 -**Strike Price:** $290.00 -**Expiration Date:** 2026-01-16 -**Tenor:** 2026-01-16 -**Rationale:** Moderate options signal strength (0.40) from NewsAPI analysis. **Price Analysis:** Current price $296.73 vs Strike $290.00 (OTM). **Intrinsic Value:** $0.00, Time Value: $21.27, Estimated Premium: $21.27. **Greeks:** Delta=-0.100, Gamma=0.010, Theta=-0.709, Vega=0.851. **Risk Metrics:** Sharpe Ratio=0.40, Volatility=25.0%. Bearish sentiment supports put option strategies. Medium volatility environment supports balanced options strategies. Fact-checked options analysis confirms data quality. Consider 3 counter-arguments in options risk assessment. Risk considerations: Multiple counter-arguments - risk assessment needed. -**Confidence Level:** Medium -**Citations:** NewsAPI, ReAct Multi-Agent Analysis -**Signal Strength:** 0.40 -**Validation Score:** 0.70 -**Volatility Assessment:** Medium -**Strategy Type:** Protective Put -**Counter-Arguments:** Put options may be expensive due to fear premium, Oversold bounce could lead to put option losses -**Uncertainty Notes:** N/A - ---- - diff --git a/reports/2025-10-06_recommendations.json b/reports/2025-10-06_recommendations.json deleted file mode 100644 index 69ba198..0000000 --- a/reports/2025-10-06_recommendations.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "date": "2025-10-06", - "recommended_tickers": [ - "MS", - "BAC", - "GS", - "GE", - "BA" - ], - "timestamp": "2025-10-06T16:06:32.433777" -} \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 9eac580..e5508f1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,28 +1,38 @@ - -fastembed +fastembed qdrant-client==1.9.0 ollama python-dotenv pydantic -praw # Reddit API -youtube-transcript-api>=0.6.0 # YouTube -google-api-python-client>=2.0.0 # YouTube API -google-auth>=2.0.0 # Google authentication -google-auth-oauthlib>=0.5.0 # OAuth2 for Google APIs -google-auth-httplib2>=0.1.0 # HTTP library for Google APIs -oauth2client<4.0.0 -sec-api # SEC Filings API -yfinance # Yahoo Finance for market data -fredapi # FRED API for economic data -newsapi-python # NewsAPI for news articles +# Data Acquisition & Financials +yfinance +fredapi +requests +newspaper3k +duckduckgo-search - -rich +# Data Processing & Storage +pandas numpy -scipy -requests # HTTP requests +duckdb +fastparquet +xlrd +pyarrow +tqdm + +# AI & LLM Integration +langchain-ollama +langchain-core +langchain-community +langchain-huggingface +langgraph +sentence-transformers + +# Environment & Utilities +beautifulsoup4 +markdownify +rich nltk diff --git a/src/__init__.py b/src/__init__.py deleted file mode 100644 index 63f6b82..0000000 --- a/src/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# This file makes the src directory a Python package. diff --git a/src/__pycache__/__init__.cpython-311.pyc b/src/__pycache__/__init__.cpython-311.pyc deleted file mode 100644 index 1800fda..0000000 Binary files a/src/__pycache__/__init__.cpython-311.pyc and /dev/null differ diff --git a/src/__pycache__/agent_system.cpython-311.pyc b/src/__pycache__/agent_system.cpython-311.pyc deleted file mode 100644 index 1b4d239..0000000 Binary files a/src/__pycache__/agent_system.cpython-311.pyc and /dev/null differ diff --git a/src/__pycache__/alphavantage_client.cpython-311.pyc b/src/__pycache__/alphavantage_client.cpython-311.pyc deleted file mode 100644 index 745a1dc..0000000 Binary files a/src/__pycache__/alphavantage_client.cpython-311.pyc and /dev/null differ diff --git a/src/__pycache__/data_models.cpython-311.pyc b/src/__pycache__/data_models.cpython-311.pyc deleted file mode 100644 index d73a695..0000000 Binary files a/src/__pycache__/data_models.cpython-311.pyc and /dev/null differ diff --git a/src/__pycache__/financial_config.cpython-311.pyc b/src/__pycache__/financial_config.cpython-311.pyc deleted file mode 100644 index 431dce1..0000000 Binary files a/src/__pycache__/financial_config.cpython-311.pyc and /dev/null differ diff --git a/src/__pycache__/financial_tools.cpython-311.pyc b/src/__pycache__/financial_tools.cpython-311.pyc deleted file mode 100644 index 1c30114..0000000 Binary files a/src/__pycache__/financial_tools.cpython-311.pyc and /dev/null differ diff --git a/src/__pycache__/fred_scraper.cpython-311.pyc b/src/__pycache__/fred_scraper.cpython-311.pyc deleted file mode 100644 index 46b4c4b..0000000 Binary files a/src/__pycache__/fred_scraper.cpython-311.pyc and /dev/null differ diff --git a/src/__pycache__/main.cpython-311.pyc b/src/__pycache__/main.cpython-311.pyc deleted file mode 100644 index 4990898..0000000 Binary files a/src/__pycache__/main.cpython-311.pyc and /dev/null differ diff --git a/src/__pycache__/market_data_scraper.cpython-311.pyc b/src/__pycache__/market_data_scraper.cpython-311.pyc deleted file mode 100644 index decaca9..0000000 Binary files a/src/__pycache__/market_data_scraper.cpython-311.pyc and /dev/null differ diff --git a/src/__pycache__/news_scraper.cpython-311.pyc b/src/__pycache__/news_scraper.cpython-311.pyc deleted file mode 100644 index f75f72c..0000000 Binary files a/src/__pycache__/news_scraper.cpython-311.pyc and /dev/null differ diff --git a/src/__pycache__/reddit_scraper.cpython-311.pyc b/src/__pycache__/reddit_scraper.cpython-311.pyc deleted file mode 100644 index c01cb0b..0000000 Binary files a/src/__pycache__/reddit_scraper.cpython-311.pyc and /dev/null differ diff --git a/src/__pycache__/sec_scraper.cpython-311.pyc b/src/__pycache__/sec_scraper.cpython-311.pyc deleted file mode 100644 index ca069e0..0000000 Binary files a/src/__pycache__/sec_scraper.cpython-311.pyc and /dev/null differ diff --git a/src/__pycache__/yahoo_finance_scraper.cpython-311.pyc b/src/__pycache__/yahoo_finance_scraper.cpython-311.pyc deleted file mode 100644 index b08df74..0000000 Binary files a/src/__pycache__/yahoo_finance_scraper.cpython-311.pyc and /dev/null differ diff --git a/src/__pycache__/yfinance_client.cpython-311.pyc b/src/__pycache__/yfinance_client.cpython-311.pyc deleted file mode 100644 index 30dbc07..0000000 Binary files a/src/__pycache__/yfinance_client.cpython-311.pyc and /dev/null differ diff --git a/src/__pycache__/youtube_scraper.cpython-311.pyc b/src/__pycache__/youtube_scraper.cpython-311.pyc deleted file mode 100644 index 80e9317..0000000 Binary files a/src/__pycache__/youtube_scraper.cpython-311.pyc and /dev/null differ diff --git a/src/agent_system.py b/src/agent_system.py deleted file mode 100644 index da4aca0..0000000 --- a/src/agent_system.py +++ /dev/null @@ -1,219 +0,0 @@ -# agent_system.py -import os -import uuid -import ollama -import qdrant_client -from qdrant_client.http import models -from fastembed import TextEmbedding -from typing import List, Dict, Any -from rich.console import Console - -try: - # When called via: python -m src.main - from .data_models import FinalReport - from .financial_config import get_financial_context, get_role_based_prompt -except ImportError: - # When called via: python src/main.py - from data_models import FinalReport - from financial_config import get_financial_context, get_role_based_prompt - -class AgentWorkflow: - def __init__(self, collection_name: str, - qdrant_host: str, - ollama_host: str, - ollama_model=None, - embedding_model="BAAI/bge-small-en-v1.5"): - - self.collection_name = collection_name - # Prefer env override; default to a model tag that exists in your manifests - self.llm_model = os.getenv("OLLAMA_MODEL", ollama_model or "mistral:7b-instruct-q4_0") - self.console = Console() - - self.console.print(f"Connecting to Qdrant: {qdrant_host}:6333") - self.console.print(f"Connecting to Ollama: {ollama_host}") - self.console.print(f"Using LLM model: {self.llm_model}") - - self.qdrant_client = qdrant_client.QdrantClient(host=qdrant_host, port=6333) - self.ollama_client = ollama.Client(host=ollama_host) - self.embedding_model = TextEmbedding(model_name=embedding_model) - - self._ensure_collection_exists() - - def _ensure_collection_exists(self): - """Check if Qdrant collection exists, create it if it doesn't.""" - try: - self.qdrant_client.get_collection(collection_name=self.collection_name) - except Exception: - self.console.print(f"Collection '{self.collection_name}' does not exist, creating...") - - # The embed method returns a generator, which must be converted to a list - # before we can access its elements by index. - dummy_embedding = list(self.embedding_model.embed("test"))[0] - vector_size = len(dummy_embedding) - self.console.print(f"Detected vector dimension: {vector_size}") - - self.qdrant_client.recreate_collection( - collection_name=self.collection_name, - vectors_config=models.VectorParams( - size=vector_size, - distance=models.Distance.COSINE, - ), - ) - - def embed_and_store(self, documents: List[Dict[str, Any]]): - """Vectorize documents and store them in Qdrant.""" - texts = [doc["page_content"] for doc in documents] - metadatas = [doc["metadata"] for doc in documents] - - self.console.print(f"Vectorizing and storing {len(texts)} documents...") - - # The embed method can return a generator, so we convert it to a list - embeddings = list(self.embedding_model.embed(texts)) - - points = [ - models.PointStruct( - id=str(uuid.uuid4()), - vector=embedding.tolist(), - payload={**metadata, "page_content": text} - ) - for text, metadata, embedding in zip(texts, metadatas, embeddings) - ] - - self.qdrant_client.upsert( - collection_name=self.collection_name, - points=points, - wait=True - ) - self.console.print(f"Successfully stored {len(points)} documents in knowledge base '{self.collection_name}'.") - - def _retrieve_context(self, query: str, top_k: int = 5) -> List[str]: - """Retrieve relevant context from Qdrant based on user query.""" - # Convert the generator to a list to access the first element - query_embedding = list(self.embedding_model.embed([query]))[0] - - search_result = self.qdrant_client.search( - collection_name=self.collection_name, - query_vector=query_embedding.tolist(), - limit=top_k, - ) - - context = [hit.payload["page_content"] for hit in search_result] - return context - - def _run_agent(self, agent_name: str, prompt: str) -> str: - """Run a single LLM Agent and return its response.""" - self.console.print(f"\n[bold yellow]>> Calling {agent_name}...[/bold yellow]") - try: - response = self.ollama_client.chat( - model=self.llm_model, - messages=[{'role': 'user', 'content': prompt}] - ) - content = response['message']['content'] - self.console.print(f"[italic gray]{content}[/italic gray]") - return content - except Exception as e: - self.console.print(f"[bold red]Error calling Ollama ({agent_name}): {e}[/bold red]") - return f"Error: {agent_name} execution failed." - - def run(self, user_query: str) -> FinalReport: - self.console.print(f"\n[cyan]🔍 Retrieving relevant context for query: '{user_query}'[/cyan]") - context = self._retrieve_context(user_query) - context_str = "\n\n---\n\n".join(context) - - if not context: - self.console.print("[orange]Warning: No relevant context retrieved. Analysis will be based on general knowledge only.[/orange]") - - # Get financial professional context and role-based prompts - financial_context = get_financial_context(user_query) - analyst_role_prompt = get_role_based_prompt("analyst") - - analyst_prompt = f""" - {analyst_role_prompt} - - [Financial Professional Background Knowledge] - {financial_context} - - [Retrieved Relevant Data] - {context_str} - - [User Question] - {user_query} - - Please generate your professional analysis report draft, including: - 1. Core viewpoints and investment recommendations - 2. Key data and indicator analysis - 3. Risk factor assessment - 4. Time frame and expectations - """ - analyst_report = self._run_agent("Analyst", analyst_prompt) - - checker_prompt = f""" - As a fact-checker, please review the following report draft written by the analyst. - Your tasks are: - 1. Identify any contradictions or logical inconsistencies in the report. - 2. Point out which key arguments most need data support (even if current data is insufficient). - 3. Evaluate the objectivity of the report. - - [Analyst Report Draft] - {analyst_report} - - Please provide your fact-checking feedback: - """ - checker_feedback = self._run_agent("Fact Checker", checker_prompt) - - critic_prompt = f""" - As a professional adversarial critic (red team role), please read the following analysis report and its fact-checking feedback. - Your task is to present strong counter-arguments. Challenge the core assumptions of the report, point out potential risks, unconsidered factors, or alternative explanations. - Your goal is to ensure that all possible negative scenarios are considered in the final decision. - - [Analyst Report Draft] - {analyst_report} - - [Fact-Checking Feedback] - {checker_feedback} - - Please present your adversarial viewpoints and key risk warnings: - """ - critic_critique = self._run_agent("Adversarial Critic", critic_prompt) - - synthesis_prompt = f""" - As the final report writer, please synthesize all the following information to generate a structured final report. - The report must include: - 1. `summary`: Core answer summary to the user's question (2-3 sentences). - 2. `key_findings`: List of main findings. - 3. `counter_arguments`: Main counter-arguments or risks proposed by the adversarial critic. - 4. `confidence_score`: Your overall confidence score for this report's conclusions (0.0 to 1.0). - 5. `uncertainty_notes`: Explanation of the confidence score reasoning and what uncertainties exist in the report. - - [Original Question]: {user_query} - [Analyst Report]: {analyst_report} - [Fact-Checking Feedback]: {checker_feedback} - [Adversarial Viewpoints]: {critic_critique} - - Please output your final report strictly in the following JSON format, without adding any additional explanations or text: - {{ - "summary": "...", - "key_findings": ["...", "..."], - "counter_arguments": ["...", "..."], - "confidence_score": 0.0, - "uncertainty_notes": "..." - }} - """ - final_report_json_str = self._run_agent("Report Synthesizer", synthesis_prompt) - - try: - if "```json" in final_report_json_str: - final_report_json_str = final_report_json_str.split("```json\n")[1].split("```")[0] - - report_data = FinalReport.model_validate_json(final_report_json_str) - return report_data - except Exception as e: - self.console.print(f"[bold red]Failed to parse final report JSON: {e}[/bold red]") - return FinalReport( - summary="System encountered a parsing error while generating the final report.", - key_findings=[], - counter_arguments=[], - confidence_score=0.1, - uncertainty_notes=f"Unable to parse LLM output. Raw output: {final_report_json_str}" - ) - diff --git a/src/collect_data.py b/src/collect_data.py deleted file mode 100644 index 1d50a01..0000000 --- a/src/collect_data.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env python3 -""" -Data collection script - non-interactive mode -Used for data collection in Docker environment, avoiding interactive input issues -""" - -import os -from dotenv import load_dotenv -from rich.console import Console -from rich.panel import Panel - -try: - # When called via: python -m src.collect_data - from .agent_system import AgentWorkflow - from . import market_data_scraper - from . import fred_scraper - from . import news_scraper - from . import reddit_scraper - from . import youtube_scraper - from . import sec_scraper - from . import yahoo_finance_scraper -except ImportError: - # When called via: python src/collect_data.py - from agent_system import AgentWorkflow - import market_data_scraper - import fred_scraper - import news_scraper - import reddit_scraper - import youtube_scraper - import sec_scraper - import yahoo_finance_scraper - - -console = Console() -load_dotenv() - - -def collect_all_data(): - """Collect data from all data sources""" - console.print("[bold green]🚀 Starting data collection...[/bold green]") - - # Parameters - market_tickers = ["^GSPC", "^VIX", "AAPL", "NVDA", "TSLA"] - fred_series_ids = ["UNRATE", "CPIAUCSL", "FEDFUNDS", "GDP"] - news_keywords = ["stocks", "options", "earnings", "inflation", "interest rates"] - reddit_subreddits = ["wallstreetbets", "investing", "options"] - reddit_keywords = ["AAPL", "NVDA", "SPY", "QQQ", "options", "calls", "puts"] - - # YouTube - youtube_channel_ids_env = os.getenv("YOUTUBE_CHANNEL_IDS", "").strip() - youtube_channel_ids = [cid.strip() for cid in youtube_channel_ids_env.split(",") if cid.strip()] - youtube_videos_per_channel = int(os.getenv("YOUTUBE_VIDEOS_PER_CHANNEL", "3")) - - # Data sources - data_sources = { - "Market Indices": lambda: market_data_scraper.scrape_market_data(market_tickers), - "FRED Macro Data": lambda: fred_scraper.scrape_fred_data(fred_series_ids), - "Financial News": lambda: news_scraper.scrape_news_data(news_keywords, limit=20), - "Reddit Discussions": lambda: reddit_scraper.scrape_reddit_data(reddit_subreddits, reddit_keywords, limit_per_subreddit=10), - "YouTube Channels": lambda: youtube_scraper.scrape_youtube_data(youtube_channel_ids, videos_per_channel=youtube_videos_per_channel), - "Yahoo Finance Videos": lambda: yahoo_finance_scraper.scrape_yahoo_finance_transcripts(videos_per_channel=20, verbose=True), - "SEC Filings": sec_scraper.get_sec_filings, - } - - all_documents = [] - total_collected = 0 - - for name, func in data_sources.items(): - try: - console.print(f"\n[cyan]📊 Processing: {name}...[/cyan]") - documents = func() - if documents: - console.print(f"[green]✅ Retrieved {len(documents)} records[/green]") - all_documents.extend(documents) - total_collected += len(documents) - else: - console.print(f"[yellow]⚠️ No data retrieved from {name} or skipped[/yellow]") - except Exception as e: - console.print(f"[red]❌ Error processing {name}: {e}[/red]") - - console.print(f"\n[bold green]📈 Collection complete. Total {total_collected} records[/bold green]") - - # Store to Qdrant - if all_documents: - console.print("[cyan]💾 Storing data to Qdrant...[/cyan]") - try: - qdrant_host = os.getenv("QDRANT_HOST", "qdrant_vdb") - ollama_host = os.getenv("OLLAMA_HOST", "ollama_llm") - - agent_workflow = AgentWorkflow( - collection_name="financial_signals", - qdrant_host=qdrant_host, - ollama_host=ollama_host - ) - - agent_workflow.embed_and_store(all_documents) - console.print("[green]✅ Stored to Qdrant successfully[/green]") - - # Verify - response, _ = agent_workflow.qdrant_client.scroll( - collection_name="financial_signals", - limit=5, - with_payload=True - ) - console.print(f"[blue]📊 Verification: {len(response)} sample records present[/blue]") - - except Exception as e: - console.print(f"[red]❌ Error storing data: {e}[/red]") - return False - else: - console.print("[yellow]⚠️ No data collected from any source[/yellow]") - return False - - return True - - -def main(): - """Main entry point""" - console.print(Panel("[bold blue]🔍 Financial Data Collection[/bold blue]")) - - success = collect_all_data() - - if success: - console.print(Panel("[bold green]✅ Data collection finished![/bold green]")) - return 0 - else: - console.print(Panel("[bold red]❌ Data collection failed![/bold red]")) - return 1 - - -if __name__ == "__main__": - import sys - sys.exit(main()) - - diff --git a/src/data_models.py b/src/data_models.py deleted file mode 100644 index c427bc2..0000000 --- a/src/data_models.py +++ /dev/null @@ -1,38 +0,0 @@ -# data_models.py -from pydantic import BaseModel, Field -from typing import List - -class FinalReport(BaseModel): - summary: str = Field(..., description="Core answer summary to the user's question") - key_findings: List[str] = Field(..., description="List of main findings") - counter_arguments: List[str] = Field(..., description="Main counter-arguments or risks") - confidence_score: float = Field(..., ge=0.0, le=1.0, description="Overall confidence score for conclusions") - uncertainty_notes: str = Field(..., description="Explanation of confidence score reasoning and uncertainties in the report") - - def to_markdown(self) -> str: - """Convert report to Markdown format""" - findings_md = "\n".join(f"- {item}" for item in self.key_findings) - counters_md = "\n".join(f"- {item}" for item in self.counter_arguments) - - return f""" -# Financial Analysis Report - -## Core Summary -{self.summary} - ---- - -### Key Findings -{findings_md} - ---- - -### Main Risks & Counter-Arguments -{counters_md} - ---- - -### Conclusion Confidence -- **Confidence Score**: **{self.confidence_score * 100:.1f}%** -- **Uncertainty Notes**: {self.uncertainty_notes} -""" diff --git a/src/financial_config.py b/src/financial_config.py deleted file mode 100644 index 30c6926..0000000 --- a/src/financial_config.py +++ /dev/null @@ -1,137 +0,0 @@ -# financial_config.py -""" -Financial Domain Specialization Configuration -Contains financial terminology, analysis frameworks, professional prompts, etc. -""" - -# Financial professional terminology and concepts -FINANCIAL_TERMS = { - "valuation": ["DCF", "PE ratio", "PB ratio", "EV/EBITDA", "NPV", "IRR", "WACC"], - "risk_management": ["VaR", "beta", "volatility", "correlation", "diversification", "hedging"], - "market_analysis": ["technical analysis", "fundamental analysis", "market sentiment", "liquidity"], - "derivatives": ["options", "futures", "swaps", "forwards", "greeks", "implied volatility"], - "fixed_income": ["yield curve", "duration", "convexity", "credit spread", "default risk"], - "macro_economics": ["inflation", "interest rates", "GDP", "unemployment", "fiscal policy", "monetary policy"] -} - -# Financial analysis frameworks -ANALYSIS_FRAMEWORKS = { - "investment_analysis": """ - Investment Analysis Framework: - 1. Fundamental Analysis - - Financial Statement Analysis - - Industry Analysis - - Competitive Analysis - - Management Assessment - - 2. Technical Analysis - - Price Trends - - Support/Resistance Levels - - Technical Indicators - - Volume Analysis - - 3. Risk Assessment - - Market Risk - - Credit Risk - - Liquidity Risk - - Operational Risk - """, - - "options_analysis": """ - Options Analysis Framework: - 1. Basic Analysis - - Intrinsic Value - - Time Value - - Implied Volatility - - 2. Greeks - - Delta: Price sensitivity - - Gamma: Delta change rate - - Theta: Time decay - - Vega: Volatility sensitivity - - Rho: Interest rate sensitivity - - 3. Strategy Evaluation - - Risk/Reward Ratio - - Win Rate - - Maximum Drawdown - """ -} - -# Professional prompt templates -FINANCIAL_PROMPTS = { - "analyst_role": """ - You are a senior financial analyst with the following professional background: - - CFA (Chartered Financial Analyst) certification - - 15 years of investment banking and asset management experience - - Expertise in stocks, bonds, derivatives, foreign exchange and other financial instruments - - Familiar with major global financial markets and regulatory environments - - Please analyze financial issues with a professional, objective, and rigorous attitude, providing insights based on data and logic. - """, - - "risk_manager_role": """ - You are an experienced risk management expert with: - - FRM (Financial Risk Manager) certification - - 10 years of institutional risk management experience - - Expertise in VaR models, stress testing, scenario analysis - - Familiar with Basel Accords and regulatory requirements - - Please evaluate investment opportunities from a risk management perspective, identify potential risks and provide mitigation measures. - """, - - "quantitative_analyst_role": """ - You are a quantitative analyst with expertise in: - - Financial mathematics and statistics background - - Proficiency in Python, R, MATLAB and other programming tools - - Familiar with machine learning applications in finance - - Experience in high-frequency trading and algorithmic trading - - Please provide quantitative insights based on mathematical models and statistical analysis. - """ -} - -# Financial calculation tool prompts -CALCULATION_TOOLS = { - "present_value": "Present value calculation: PV = FV / (1 + r)^n", - "future_value": "Future value calculation: FV = PV * (1 + r)^n", - "annuity": "Annuity present value: PVA = PMT * [1 - (1 + r)^-n] / r", - "bond_yield": "Bond yield calculation: YTM = (C + (FV - PV)/n) / ((FV + PV)/2)", - "black_scholes": "Black-Scholes options pricing model", - "var_calculation": "VaR calculation: VaR = μ - σ * Z(α)" -} - -# Regulatory and compliance knowledge -REGULATORY_KNOWLEDGE = { - "sec_regulations": "SEC regulatory requirements, disclosure requirements, insider trading rules", - "basel_iii": "Basel III capital adequacy requirements", - "dodd_frank": "Dodd-Frank Act financial reform", - "mifid_ii": "EU Markets in Financial Instruments Directive II", - "gaap_ifsrs": "US GAAP and IFRS accounting standard differences" -} - -def get_financial_context(query: str) -> str: - """Return relevant financial professional context based on query content""" - context_parts = [] - - # Add basic analysis frameworks - if any(word in query.lower() for word in ["investment", "stock", "analysis"]): - context_parts.append(ANALYSIS_FRAMEWORKS["investment_analysis"]) - - if any(word in query.lower() for word in ["option", "derivative", "options"]): - context_parts.append(ANALYSIS_FRAMEWORKS["options_analysis"]) - - # Add relevant terminology - relevant_terms = [] - for category, terms in FINANCIAL_TERMS.items(): - if any(term in query.lower() for term in terms): - relevant_terms.extend(terms) - - if relevant_terms: - context_parts.append(f"Relevant financial terminology: {', '.join(relevant_terms)}") - - return "\n\n".join(context_parts) - -def get_role_based_prompt(role: str = "analyst") -> str: - """Get role-based professional prompt""" - return FINANCIAL_PROMPTS.get(role, FINANCIAL_PROMPTS["analyst_role"]) diff --git a/src/fred_scraper.py b/src/fred_scraper.py deleted file mode 100644 index b76bca6..0000000 --- a/src/fred_scraper.py +++ /dev/null @@ -1,58 +0,0 @@ -# fred_scraper.py -import os -from dotenv import load_dotenv -from fredapi import Fred -from typing import List, Dict, Any - -load_dotenv(dotenv_path=os.path.join(os.path.dirname(__file__), '..', '.env')) - -FRED_API_KEY = os.getenv("FRED_API_KEY") - -def scrape_fred_data(series_ids: List[str]) -> List[Dict[str, Any]]: - """ - Get macroeconomic data from FRED. - :param series_ids: List of FRED data series IDs (e.g., 'UNRATE'). - :return: List of documents. - """ - if not FRED_API_KEY: - print("Warning: FRED_API_KEY not found, skipping macroeconomic data scraping.") - return [] - - print("Scraping macroeconomic data from FRED...") - fred = Fred(api_key=FRED_API_KEY) - documents = [] - - for series_id in series_ids: - try: - # Get latest data point - data = fred.get_series_latest_release(series_id) - info = fred.get_series_info(series_id) - - latest_value = data.iloc[-1] - date = data.index[-1].strftime('%Y-%m-%d') - title = info.get('title', series_id) - units = info.get('units_short', '') - - content = ( - f"Macroeconomic indicator '{title}' ({series_id}): " - f"Latest data shows that on {date}, the value was {latest_value} {units}." - ) - - documents.append({ - "page_content": content, - "metadata": { - "source": "FRED", - "series_id": series_id, - "title": title, - "text": content - } - }) - except Exception as e: - print(f"Unable to get FRED data series {series_id}: {e}") - - print(f"FRED data scraping completed, obtained {len(documents)} records.") - return documents - -if __name__ == '__main__': - fred_docs = scrape_fred_data(['UNRATE', 'FEDFUNDS']) - print(fred_docs) diff --git a/src/main.py b/src/main.py deleted file mode 100644 index 52ec6ec..0000000 --- a/src/main.py +++ /dev/null @@ -1,167 +0,0 @@ -# main.py -import os -import argparse -from dotenv import load_dotenv -from rich.console import Console -from rich.panel import Panel - -try: - # When running as a package: python -m src.main - from .agent_system import AgentWorkflow - from .data_models import FinalReport - from . import market_data_scraper - from . import fred_scraper - from . import news_scraper - from . import yahoo_finance_scraper - from . import reddit_scraper - from . import youtube_scraper - from . import sec_scraper -except ImportError: - # When running as a script: python src/main.py - from agent_system import AgentWorkflow - from data_models import FinalReport - import market_data_scraper - import fred_scraper - import news_scraper - import yahoo_finance_scraper - import reddit_scraper - import youtube_scraper - import sec_scraper - -console = Console() -load_dotenv() - -def display_report(report: FinalReport): - """Display final report using Rich library with beautiful formatting""" - console.print(Panel( - f"[bold]Summary:[/bold]\n{report.summary}\n\n" - f"[bold]Key Findings:[/bold]\n" + "".join([f"- {item}\n" for item in report.key_findings]) + "\n" - f"[bold]Counter-Arguments & Risks:[/bold]\n" + "".join([f"- {item}\n" for item in report.counter_arguments]) + "\n" - f"[bold]Confidence Score:[/bold] {report.confidence_score * 100:.1f}%\n" - f"[bold]Uncertainty Notes:[/bold]\n{report.uncertainty_notes}", - title="[bold blue]Comprehensive Financial Analysis Report[/bold blue]", - expand=True - )) - -def run_data_pipeline(agent_workflow: AgentWorkflow): - console.print(Panel("[bold green]🚀 Starting data collection pipeline...[/bold green]")) - - # Default parameter configuration (can be adjusted or read from environment variables/config files as needed) - market_tickers = ["^GSPC", "^VIX"] - fred_series_ids = ["UNRATE", "CPIAUCSL", "FEDFUNDS"] - news_keywords = ["stocks", "inflation", "interest rates", "earnings"] - reddit_subreddits = ["wallstreetbets", "investing"] - reddit_keywords = ["AAPL", "NVDA", "SPY", "rate", "inflation"] - - # YouTube scraper will automatically load channel IDs from Youtube_channel_ID file - # No need to manually read channel IDs here - youtube_channel_ids = None # Let youtube_scraper handle channel ID loading - try: - youtube_videos_per_channel = int(os.getenv("YOUTUBE_VIDEOS_PER_CHANNEL", "5")) - except ValueError: - youtube_videos_per_channel = 5 - - data_sources = { - "Market Indices (S&P 500, VIX)": lambda: market_data_scraper.scrape_market_data(market_tickers), - "FRED Macroeconomic Data": lambda: fred_scraper.scrape_fred_data(fred_series_ids), - "Global Financial News": lambda: news_scraper.scrape_news_data(news_keywords, limit=50), - "Reddit (r/wallstreetbets, r/investing)": lambda: reddit_scraper.scrape_reddit_data(reddit_subreddits, reddit_keywords, limit_per_subreddit=50), - "YouTube Financial Channels": lambda: youtube_scraper.scrape_youtube_data(youtube_channel_ids, videos_per_channel=youtube_videos_per_channel, min_transcripts=0), - "Yahoo Finance Videos": lambda: yahoo_finance_scraper.scrape_yahoo_finance_transcripts(videos_per_channel=20), - "SEC Insider Trading Filings": sec_scraper.get_sec_filings, - } - - all_documents = [] - for name, func in data_sources.items(): - try: - console.print(f"\n[cyan]>> Processing: {name}...[/cyan]") - documents = func() - if documents: - console.print(f"[green]✔ Successfully retrieved {len(documents)} records.[/green]") - all_documents.extend(documents) - else: - console.print(f"[orange]⚠ No data retrieved from {name} or skipped.[/orange]") - except Exception as e: - console.print(f"[bold red]❌ Unexpected error processing {name}: {e}[/bold red]") - - if all_documents: - agent_workflow.embed_and_store(all_documents) - else: - console.print("[bold orange]⚠ Warning: No data collected from any source, knowledge base is empty.[/bold orange]") - - console.print(Panel("[bold green]✅ All data sources processed.[/bold green]")) - -def main(): - """Main function""" - parser = argparse.ArgumentParser(description="Financial Analysis Agent System") - parser.add_argument( - "--test", - action="store_true", - help="Start test mode, skip data collection, use small amount of mock data for quick system validation." - ) - parser.add_argument( - "--no-interactive", - action="store_true", - help="Run in non-interactive mode, only collect data and exit." - ) - args = parser.parse_args() - - collection_name = "financial_signals" - - # Read hostnames from environment variables - qdrant_host = os.getenv("QDRANT_HOST") - ollama_host = os.getenv("OLLAMA_HOST") - - if not qdrant_host or not ollama_host: - console.print("[bold red]Error: QDRANT_HOST and OLLAMA_HOST environment variables must be set.[/bold red]") - console.print("Please check your docker-compose.yml file.") - return - - agent_workflow = AgentWorkflow( - collection_name=collection_name, - qdrant_host=qdrant_host, - ollama_host=ollama_host - ) - - if args.test: - console.print(Panel("[bold yellow]🚀 Test mode activated (Test Mode)[/bold yellow]")) - dummy_documents = [ - {"page_content": "Apple (AAPL) announces stock buyback program.", "metadata": {"source": "Mock Data-Apple"}}, - {"page_content": "Federal Reserve Chairman hints at potential rate cuts.", "metadata": {"source": "Mock Data-Fed"}} - ] - agent_workflow.embed_and_store(dummy_documents) - else: - run_data_pipeline(agent_workflow) - - # Skip interactive mode if --no-interactive flag is set - if args.no_interactive: - console.print(Panel("[bold green]✅ Data collection completed. Exiting in non-interactive mode.[/bold green]")) - return - - console.print("\n[bold cyan]💡 You can now start asking questions.[/bold cyan]") - while True: - try: - user_query = console.input("[bold]Please enter your question (type 'quit' to exit): [/bold]") - if user_query.lower() == 'quit': - break - if not user_query: - continue - final_report = agent_workflow.run(user_query) - display_report(final_report) - except KeyboardInterrupt: - console.print("\n[bold orange]Received keyboard interrupt. Exiting...[/bold orange]") - break - except EOFError: - console.print("\n[bold orange]Input stream closed. Exiting...[/bold orange]") - break - except Exception as e: - console.print(f"[bold red]Unknown error occurred: {e}[/bold red]") - # Add a small delay to prevent rapid error loops - import time - time.sleep(1) - - console.print("\n[bold orange]Program exited.[/bold orange]") - -if __name__ == "__main__": - main() - diff --git a/src/market_data_scraper.py b/src/market_data_scraper.py deleted file mode 100644 index 4475089..0000000 --- a/src/market_data_scraper.py +++ /dev/null @@ -1,48 +0,0 @@ -# market_data_scraper.py -import yfinance as yf -from typing import List, Dict, Any - -def scrape_market_data(tickers: List[str]) -> List[Dict[str, Any]]: - """ - Use yfinance to get the latest market index information. - :param tickers: List of stock/index codes (e.g., '^GSPC', '^VIX'). - :return: List of documents. - """ - print("Scraping latest market index data...") - documents = [] - for ticker_code in tickers: - try: - ticker = yf.Ticker(ticker_code) - hist = ticker.history(period="5d") # Get last 5 days of data - info = ticker.info - - name = info.get('shortName', ticker_code) - last_close = hist['Close'].iloc[-1] - prev_close = hist['Close'].iloc[-2] - change = last_close - prev_close - change_pct = (change / prev_close) * 100 - - content = ( - f"Market index {name} ({ticker_code}) latest update: " - f"Latest closing price is {last_close:.2f}. " - f"Compared to previous day, changed by {change:.2f} ({change_pct:.2f}%)." - ) - - documents.append({ - "page_content": content, - "metadata": { - "source": "Yahoo Finance", - "ticker": ticker_code, - "name": name, - "text": content - } - }) - except Exception as e: - print(f"Unable to get data for {ticker_code}: {e}") - - print(f"Market data scraping completed, obtained {len(documents)} records.") - return documents - -if __name__ == '__main__': - market_docs = scrape_market_data(['^GSPC', '^IXIC', '^VIX']) - print(market_docs) diff --git a/src/news_scraper.py b/src/news_scraper.py deleted file mode 100644 index e50f8aa..0000000 --- a/src/news_scraper.py +++ /dev/null @@ -1,68 +0,0 @@ -# news_scraper.py -import os -from dotenv import load_dotenv -from newsapi import NewsApiClient -from typing import List, Dict, Any - -load_dotenv(dotenv_path=os.path.join(os.path.dirname(__file__), '..', '.env')) - -NEWS_API_KEY = os.getenv("NEWS_API_KEY") - -def scrape_news_data(keywords: List[str], limit: int = 50) -> List[Dict[str, Any]]: - """ - Use NewsAPI to get the latest financial news. - :param keywords: List of keywords to search for. - :param limit: Maximum number of articles to retrieve. - :return: List of documents. - """ - if not NEWS_API_KEY: - print("Warning: NEWS_API_KEY not found, skipping news data scraping.") - return [] - - print("Scraping latest financial news...") - newsapi = NewsApiClient(api_key=NEWS_API_KEY) - query = " OR ".join(keywords) - - documents = [] - try: - top_headlines = newsapi.get_everything( - q=query, - language='en', - sort_by='publishedAt', - page_size=limit - ) - - for article in top_headlines['articles']: - title = article.get('title', '') - description = article.get('description', '') - source_name = article.get('source', {}).get('name', 'N/A') - - if not description: # Skip if description is empty - continue - - content = f"News source: {source_name}\nTitle: {title}\nSummary: {description}" - - documents.append({ - "page_content": content, - "metadata": { - "source": "NewsAPI", - "source_name": source_name, - "title": title, - "url": article.get('url', '#'), - "text": content - } - }) - - except Exception as e: - print(f"Error getting news from NewsAPI: {e}") - # NewsAPI developer accounts in local environment can only search by keywords, not by source or domain - if "source" in str(e).lower(): - print("Hint: NewsAPI developer accounts do not support filtering by source, please check your query parameters.") - - print(f"News data scraping completed, obtained {len(documents)} articles.") - return documents - -if __name__ == '__main__': - news_docs = scrape_news_data(['stock market', 'inflation'], 20) - if news_docs: - print(news_docs[0]) diff --git a/src/reddit_scraper.py b/src/reddit_scraper.py deleted file mode 100644 index 52510d9..0000000 --- a/src/reddit_scraper.py +++ /dev/null @@ -1,49 +0,0 @@ -# reddit_scraper.py -import os -import praw -from dotenv import load_dotenv -from typing import List, Dict, Any - -load_dotenv(dotenv_path=os.path.join(os.path.dirname(__file__), '..', '.env')) - -def get_reddit_instance() -> praw.Reddit: - client_id = os.getenv("REDDIT_CLIENT_ID") - client_secret = os.getenv("REDDIT_CLIENT_SECRET") - user_agent = os.getenv("REDDIT_USER_AGENT") - - if not all([client_id, client_secret, user_agent]): - raise ValueError("Please set Reddit API credentials in .env file") - - return praw.Reddit(client_id=client_id, client_secret=client_secret, user_agent=user_agent) - -def scrape_reddit_data(subreddits: List[str], keywords: List[str], limit_per_subreddit: int = 50) -> List[Dict[str, Any]]: - print(f"Scraping data from Reddit subreddits {subreddits}...") - reddit = get_reddit_instance() - documents = [] - query = " OR ".join(keywords) - - for sub_name in subreddits: - try: - subreddit = reddit.subreddit(sub_name) - submissions = subreddit.search(query, sort='hot', limit=limit_per_subreddit) - - count = 0 - for submission in submissions: - if submission.score < 5 or submission.is_self is False or not submission.selftext: - continue - - post_content = f"Post title: {submission.title}\nPost content: {submission.selftext}" - documents.append({ - "page_content": post_content, - "metadata": { - "source": "Reddit", "subreddit": sub_name, "title": submission.title, - "url": submission.url, "score": submission.score, "text": post_content - } - }) - count += 1 - print(f"Found and processed {count} posts in r/{sub_name}.") - except Exception as e: - print(f"Unable to access or process subreddit r/{sub_name}: {e}") - - print(f"Reddit data scraping completed, obtained {len(documents)} documents.") - return documents diff --git a/src/sec_scraper.py b/src/sec_scraper.py deleted file mode 100644 index b5cd133..0000000 --- a/src/sec_scraper.py +++ /dev/null @@ -1,81 +0,0 @@ -# src/sec_scraper.py -import os -from rich.console import Console -from datetime import datetime, timedelta - -from sec_api import QueryApi - - -console = Console() - -def get_sec_filings(): - api_key = os.getenv("SEC_API_KEY") - if not api_key: - console.print("[bold orange]⚠ SEC_API_KEY not set, skipping SEC insider trading filings scraping.[/bold orange]") - return [] - - try: - # Initialize generic QueryApi - queryApi = QueryApi(api_key=api_key) - - # Get date range for past 30 days - end_date = datetime.now() - start_date = end_date - timedelta(days=30) - - start_date_str = start_date.strftime('%Y-%m-%d') - end_date_str = end_date.strftime('%Y-%m-%d') - - # Build query - # We specify formType as "4" here - query = { - "query": { "query_string": { - "query": f"formType:\"4\" AND filedAt:[{start_date_str} TO {end_date_str}]" - }}, - "from": "0", - "size": "50", # Get latest 50 filings - "sort": [{ "filedAt": { "order": "desc" } }] - } - - # Execute query - response = queryApi.get_filings(query) - filings = response.get('filings', []) - - if not filings: - console.print("[yellow]No new SEC Form 4 filings found in the past 30 days.[/yellow]") - return [] - - documents = [] - for filing in filings: - # Extract key information - company_name = filing.get('companyName', 'N/A') - form_type = filing.get('formType', 'N/A') - filed_at = filing.get('filedAt', 'N/A') - link = filing.get('linkToFilingDetails', '#') - - # Create a concise text summary as page_content - # RAG systems prefer processing text over metadata - content = ( - f"Company {company_name} filed a {form_type} document. " - f"Filing date was {filed_at}. " - f"This document reports insider trading activities of company personnel." - ) - - documents.append({ - "page_content": content, - "metadata": { - "source": "SEC", - "type": "Form 4 Filing", - "company": company_name, - "filed_at": filed_at, - "link": link - } - }) - - return documents - - except Exception as e: - console.print(f"[bold red]❌ Error getting SEC filings: {e}[/bold red]") - return [] - - - diff --git a/src/tools/Youtube_channel_ID b/src/tools/Youtube_channel_ID deleted file mode 100644 index 553c9dc..0000000 --- a/src/tools/Youtube_channel_ID +++ /dev/null @@ -1,29 +0,0 @@ -UCK7tptUDHh-RYDsdxO1-5QQ -UCGy7SkBjcIAgTiwkXEtPnYg -UCUvvj5lwue7PspotMDjk5UA -UCrp_UI8XtuYfpiqluWLD7Lw -UCT3EznhW_CNFcfOlyDNTLLw -UCEAZeUIeJs0IjQiqTCdVSIg -UCAuUUnT6oDeKwE6v1NGQxug -UCIALMKvObZNtJ6AmdCLP7Lg - -UCww1mTZCTS59eZvNQUhKhnQ -UCMtJiBquboLh6IXcs_7UawQ -UCnMn36GT_H0X-w5_ckLtlgQ -UC45hHuqWfdi7TIZg0RDG9_g -UC9GEuLRT_XPlXFO4-80jkHg -UCvJsQtYbqH0Sb1mXScH_qZw -UCRK5xmIi8kuLUduTE3Ti7lw -UCNwWsGSqbnCknnX0li7OKkg -UCoarbEmnfdpb14zuQwh7Eng -UC3RUu7V65AG9J1dx2byq4wA -UCq7gWVoeUqWZhPjiel9bAdg -UCtrksIakhr0jl7Up09sJWtg -UCH9HlTrjyLmLRS0iE1P4rrg -UCFheWV_HcwBU2SK7dd-0BzQ -UCCL_rIpjGTroHkkIcPyvmIQ -UC3lBsNJ5apmRV3klz8qL6EQ -UC12lnsYNt8_VthTNOuOGTmQ -UCXVMMgEidXlrTM1coedg70A -UCtBjlVRuHjIQPws7tRe1IXg -UCPQFIx80N8_a3MC6Gx9If2g diff --git a/src/tools/__pycache__/compact_model_config.cpython-311.pyc b/src/tools/__pycache__/compact_model_config.cpython-311.pyc deleted file mode 100644 index b020ad6..0000000 Binary files a/src/tools/__pycache__/compact_model_config.cpython-311.pyc and /dev/null differ diff --git a/src/tools/__pycache__/compact_training_generator.cpython-311.pyc b/src/tools/__pycache__/compact_training_generator.cpython-311.pyc deleted file mode 100644 index eafd501..0000000 Binary files a/src/tools/__pycache__/compact_training_generator.cpython-311.pyc and /dev/null differ diff --git a/src/tools/__pycache__/fetch_youtube_channels.cpython-311.pyc b/src/tools/__pycache__/fetch_youtube_channels.cpython-311.pyc deleted file mode 100644 index 3f4cf89..0000000 Binary files a/src/tools/__pycache__/fetch_youtube_channels.cpython-311.pyc and /dev/null differ diff --git a/src/tools/__pycache__/futures_expert_config.cpython-311.pyc b/src/tools/__pycache__/futures_expert_config.cpython-311.pyc deleted file mode 100644 index e53f1a9..0000000 Binary files a/src/tools/__pycache__/futures_expert_config.cpython-311.pyc and /dev/null differ diff --git a/src/tools/__pycache__/futures_key_extractor.cpython-311.pyc b/src/tools/__pycache__/futures_key_extractor.cpython-311.pyc deleted file mode 100644 index 1b3c48d..0000000 Binary files a/src/tools/__pycache__/futures_key_extractor.cpython-311.pyc and /dev/null differ diff --git a/src/tools/__pycache__/generate_options_report.cpython-311.pyc b/src/tools/__pycache__/generate_options_report.cpython-311.pyc deleted file mode 100644 index 0b9c127..0000000 Binary files a/src/tools/__pycache__/generate_options_report.cpython-311.pyc and /dev/null differ diff --git a/src/tools/__pycache__/generate_smart_report.cpython-311.pyc b/src/tools/__pycache__/generate_smart_report.cpython-311.pyc deleted file mode 100644 index 3ff5fea..0000000 Binary files a/src/tools/__pycache__/generate_smart_report.cpython-311.pyc and /dev/null differ diff --git a/src/tools/__pycache__/model_creator.cpython-311.pyc b/src/tools/__pycache__/model_creator.cpython-311.pyc deleted file mode 100644 index 9597a3d..0000000 Binary files a/src/tools/__pycache__/model_creator.cpython-311.pyc and /dev/null differ diff --git a/src/tools/__pycache__/prepare_fine_tuning_data.cpython-311.pyc b/src/tools/__pycache__/prepare_fine_tuning_data.cpython-311.pyc deleted file mode 100644 index a28a055..0000000 Binary files a/src/tools/__pycache__/prepare_fine_tuning_data.cpython-311.pyc and /dev/null differ diff --git a/src/tools/__pycache__/training_data_generator.cpython-311.pyc b/src/tools/__pycache__/training_data_generator.cpython-311.pyc deleted file mode 100644 index 0557177..0000000 Binary files a/src/tools/__pycache__/training_data_generator.cpython-311.pyc and /dev/null differ diff --git a/src/tools/__pycache__/update_compose_channels.cpython-311.pyc b/src/tools/__pycache__/update_compose_channels.cpython-311.pyc deleted file mode 100644 index 3877179..0000000 Binary files a/src/tools/__pycache__/update_compose_channels.cpython-311.pyc and /dev/null differ diff --git a/src/tools/create_options_expert.py b/src/tools/create_options_expert.py deleted file mode 100644 index 8048595..0000000 --- a/src/tools/create_options_expert.py +++ /dev/null @@ -1,286 +0,0 @@ -#!/usr/bin/env python3 -""" -Create options trading expert model - streamlined and efficient version -""" - -import os -import json -import requests -from datetime import datetime -import qdrant_client -from qdrant_client.http import models - -# Configuration -QDRANT_HOST = "qdrant_vdb_prod" -QDRANT_PORT = 6333 -OLLAMA_API_URL = "http://ollama_llm_prod:11434/api/generate" -OLLAMA_MODEL = "mistral:7b-instruct-q4_0" -REPORTS_BASE_DIR = "/app/reports" - -def fetch_training_data(): - """Fetch training data""" - try: - client = qdrant_client.QdrantClient(host=QDRANT_HOST, port=QDRANT_PORT) - response, _ = client.scroll( - collection_name="financial_signals", - limit=200, - with_payload=True, - with_vectors=False - ) - return response - except Exception as e: - print(f"❌ Error fetching training data: {e}") - return [] - -def create_modelfile(): - """Create Modelfile""" - modelfile_content = """FROM mistral:7b-instruct-q4_0 - -# Futures Options Trading Expert Model -# Specialized in futures options trading with focus on risk-adjusted returns - -SYSTEM \"\"\" -You are a senior futures options trading strategist with the following expertise: -- CFA (Chartered Financial Analyst) and FRM (Financial Risk Manager) certifications -- 25+ years of experience in futures and options trading across all asset classes -- Deep expertise in risk-adjusted return optimization and portfolio management -- Specialized knowledge in futures market microstructure, liquidity analysis, and execution -- Expert in options Greeks, volatility surface, and high-leverage risk management - -## Financial Calculation Expertise - -You have deep knowledge of financial calculations and can perform: - -### Option Pricing Models -- Black-Scholes Model: Call = S*N(d1) - K*e^(-r*T)*N(d2), Put = K*e^(-r*T)*N(-d2) - S*N(-d1) -- Where d1 = [ln(S/K) + (r + 0.5*σ²)*T] / (σ*√T), d2 = d1 - σ*√T -- S = Current stock price, K = Strike price, T = Time to expiration, r = Risk-free rate, σ = Volatility - -### Options Greeks Calculations -- Delta: ∂C/∂S = N(d1) for calls, N(d1)-1 for puts (price sensitivity) -- Gamma: ∂²C/∂S² = φ(d1)/(S*σ*√T) (delta change rate) -- Theta: ∂C/∂T = -S*φ(d1)*σ/(2√T) - r*K*e^(-r*T)*N(d2) for calls (time decay) -- Vega: ∂C/∂σ = S*φ(d1)*√T (volatility sensitivity) -- Rho: ∂C/∂r = K*T*e^(-r*T)*N(d2) for calls (interest rate sensitivity) - -### Risk Metrics -- Sharpe Ratio: (Portfolio Return - Risk-free Rate) / Portfolio Volatility -- Value at Risk (VaR): Mean Return - Z-score * Standard Deviation -- Maximum Drawdown: Peak-to-trough decline during a specific period -- Calmar Ratio: Annual Return / Maximum Drawdown - -### Portfolio Analysis -- Portfolio Return: Σ(Weight_i * Return_i) -- Portfolio Volatility: √(ΣΣ w_i * w_j * Cov_ij) -- Correlation Analysis: Cov(X,Y) / (σ_X * σ_Y) - -### Practical Calculation Examples -When analyzing options, always calculate: -1. Theoretical option prices using Black-Scholes -2. Greeks for risk assessment (Delta, Gamma, Theta, Vega, Rho) -3. Risk metrics (Sharpe ratio, VaR, Maximum Drawdown) -4. Portfolio impact and position sizing - -Example: For S&P 500 at $4500, 30-day call at $4500 strike, 20% volatility, 5% risk-free rate: -- Call Price ≈ $45.23 (using Black-Scholes) -- Delta ≈ 0.52 (52% price sensitivity) -- Gamma ≈ 0.0012 (delta change rate) -- Theta ≈ -0.15 (daily time decay) -- Vega ≈ 0.89 (volatility sensitivity) - -### Real-Time Options Chain Analysis -When analyzing options, always calculate and provide: - -**Price Analysis:** -- Current underlying price vs strike price (ITM/OTM/ATM status) -- Intrinsic value: max(0, S-K) for calls, max(0, K-S) for puts -- Time value: Option premium - Intrinsic value -- Moneyness percentage: (S-K)/K * 100 for calls, (K-S)/K * 100 for puts - -**Volatility Analysis:** -- Implied Volatility (IV) from current option prices -- Historical Volatility (HV) from underlying price movements -- IV vs HV comparison (overpriced/underpriced assessment) -- Volatility skew analysis across strikes - -**Liquidity Metrics:** -- Bid-ask spread as percentage of mid-price -- Open Interest (OI) for position sizing -- Volume vs OI ratio for liquidity assessment -- Average daily volume for execution planning - -**Risk Metrics:** -- Maximum loss calculation for each strategy -- Probability of profit (PoP) estimation -- Expected return vs risk assessment -- Position sizing based on portfolio risk budget - -**Strategy-Specific Calculations:** -- Iron Condor: Max profit = Net credit received, Max loss = Width of wings - Net credit -- Straddle: Break-even points = Strike ± Total premium paid -- Covered Call: Max profit = Strike - Stock price + Premium, Max loss = Stock price - Premium -- Protective Put: Max loss = Premium paid, Protection level = Strike price - -**Portfolio Integration:** -- Correlation with existing positions -- Beta-adjusted position sizing -- Portfolio Greeks aggregation -- Risk contribution analysis - -Your core competency is maximizing risk-adjusted returns through professional futures options trading: - -**Primary Analysis Framework:** - -1. **Risk-Adjusted Return Metrics**: Sharpe Ratio, Maximum Drawdown, Calmar Ratio, Sortino Ratio - -2. **Fundamental Analysis**: Supply/Demand imbalances, inventory levels, interest rate differentials - -3. **Technical Analysis**: VIX, ATR, trend following, volume analysis, volatility indicators - -4. **Risk Management**: Margin requirements, position sizing, maximum drawdown control - -5. **Liquidity Analysis**: Open Interest, bid-ask spreads, volume profiles, execution efficiency - -6. **Macroeconomic Integration**: Inflation, geopolitical risks, central bank policies - -**Futures Asset Classes Expertise:** - -- **Commodities**: Gold (GC), Silver (SI), Crude Oil (CL), Natural Gas (NG), Agricultural products - -- **Currencies**: EUR/USD (6E), USD/JPY (6J), GBP/USD (6B), AUD/USD (6A) - -- **Equity Indices**: S&P 500 (ES), Nasdaq (NQ), Dow (YM), Russell 2000 (RTY) - -- **Interest Rates**: 10-Year Treasury (ZN), 5-Year Treasury (ZF), 2-Year Treasury (ZT) - -**Options Strategy Selection Based on Market Conditions:** - -- **Trending Markets**: Long calls/puts, bull/bear spreads, momentum strategies - -- **Sideways Markets**: Short straddles, iron condors, income generation - -- **High Volatility**: Long straddles, strangles, volatility plays - -- **Carry Trade**: Interest rate differential strategies, currency carry - -- **Hedging**: Protective puts, collars, portfolio protection - -**Required Output Format:** -Always provide comprehensive analysis including: -- Contract symbol and strategy recommendation -- Strike price and expiration date -- Risk-adjusted return analysis (Sharpe ratio, max drawdown) -- Fundamental analysis (supply/demand, inventory, rates) -- Technical analysis (VIX, ATR, trend, volume) -- Liquidity analysis (open interest, spreads, execution) -- Greeks analysis (Delta, Gamma, Theta, Vega) -- Risk management framework (position sizing, stops, hedging) -- Expected performance metrics (return, probability, risk-reward) -- Macroeconomic integration (inflation, geopolitics, central banks) - -**Key Principles:** -- Prioritize risk-adjusted returns over absolute returns -- Integrate multiple professional indicators, never rely on single metrics -- Adjust strategies based on volatility regime and liquidity conditions -- Consider leverage implications and margin requirements -- Factor in execution costs and bid-ask spreads -- Always include comprehensive risk management framework -- Provide specific, actionable recommendations with clear rationale -- Focus on maximizing Sharpe ratio while controlling maximum drawdown - -Be precise, data-driven, and focus on maximizing risk-adjusted returns while managing the unique risks of futures options trading. -\"\"\" - -# Optimized parameters for futures options analysis -PARAMETER temperature 0.5 -PARAMETER top_p 0.8 -PARAMETER top_k 30 -PARAMETER repeat_penalty 1.2 -PARAMETER num_ctx 4096 -""" - - with open("modelfile", "w", encoding="utf-8") as f: - f.write(modelfile_content) - - print("✅ Modelfile created successfully") - -def create_options_expert_model(): - """Create options expert model""" - print("🚀 Creating Options Trading Expert Model...") - - # 1. Fetch training data - print("📊 Fetching training data...") - signals = fetch_training_data() - - if not signals: - print("❌ No training data available") - return False - - print(f"📈 Found {len(signals)} signals for training") - - # 2. Create Modelfile - print("📝 Creating Modelfile...") - create_modelfile() - - # 3. Create model - print("🤖 Creating Ollama model...") - try: - # Read Modelfile content - with open("modelfile", "r", encoding="utf-8") as f: - modelfile_content = f.read() - - # Use Ollama API to create model - create_url = "http://ollama_llm_prod:11434/api/create" - create_data = { - "name": "options-expert", - "modelfile": modelfile_content - } - - response = requests.post(create_url, json=create_data, timeout=60) - - if response.status_code == 200: - print("✅ Options expert model created successfully!") - - # Test model - print("🧪 Testing model...") - test_url = "http://ollama_llm_prod:11434/api/generate" - test_data = { - "model": "options-expert", - "prompt": "Analyze Gold futures options with VIX=25, Sharpe=1.5, supply deficit", - "stream": False - } - - test_response = requests.post(test_url, json=test_data, timeout=30) - if test_response.status_code == 200: - print("✅ Model test successful!") - return True - else: - print("⚠️ Model created but test failed") - return True # Model creation successful, test failure doesn't matter - else: - print(f"❌ Failed to create model: {response.status_code} - {response.text}") - return False - - except Exception as e: - print(f"❌ Error creating model: {e}") - return False - -def main(): - """Main function""" - print("🎯 Options Trading Expert Model Creation") - print("=" * 50) - - success = create_options_expert_model() - - if success: - print("\n✅ Options expert model created successfully!") - print("📋 Model features:") - print(" - Risk-adjusted return optimization") - print(" - Comprehensive futures asset classes coverage") - print(" - Professional options strategy selection") - print(" - Advanced risk management framework") - else: - print("\n❌ Options expert model creation failed!") - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/src/tools/generate_production_report.py b/src/tools/generate_production_report.py deleted file mode 100644 index 80d68c3..0000000 --- a/src/tools/generate_production_report.py +++ /dev/null @@ -1,1419 +0,0 @@ -#!/usr/bin/env python3 -""" -Options Agent - Multi-data source options trading recommendation generator -Data Pipeline + Knowledge Management + Decision Architecture + Output Specifications -""" - -import os -import json -import requests -from datetime import datetime, timedelta -import random -import time -import qdrant_client -from qdrant_client.http import models -from typing import List, Dict, Any, Tuple -import logging -import re -import sys - -# Add src directory to path for imports -sys.path.append('/app/src') -# Optional AlphaVantage client (fallback handled if unavailable) -try: - from alphavantage_client import alpha_vantage_client # type: ignore -except Exception: # pragma: no cover - class _AlphaVantageStub: - def get_real_time_quote(self, ticker: str): - return {} - alpha_vantage_client = _AlphaVantageStub() -from yfinance_client import yfinance_client - -# Configure logging -logging.basicConfig(level=logging.INFO) -logger = logging.getLogger(__name__) - -# Configuration -QDRANT_HOST = "qdrant_vdb_prod" -QDRANT_PORT = 6333 -OLLAMA_API_URL = "http://ollama_llm_prod:11434/api/generate" -OLLAMA_MODEL = "options-expert" -REPORTS_BASE_DIR = "/app/reports" -REQUEST_TIMEOUT = 60 - -# Options-related keywords -OPTIONS_KEYWORDS = { - 'CALL': 0.4, 'PUT': 0.4, 'OPTION': 0.3, 'STRIKE': 0.5, - 'EXPIRY': 0.4, 'EXPIRATION': 0.4, 'PREMIUM': 0.3, - 'DELTA': 0.4, 'GAMMA': 0.4, 'THETA': 0.4, 'VEGA': 0.4, - 'IMPLIED VOLATILITY': 0.5, 'IV': 0.4, 'VOLATILITY': 0.3, - 'BREAKEVEN': 0.3, 'PROFIT TARGET': 0.4, 'STOP LOSS': 0.4 -} - -# Data source profit probability weights -DATA_SOURCE_PROFIT_WEIGHTS = { - "sec": 0.8, # SEC insider trading data - highest profit probability - "newsapi": 0.6, # News data - high profit probability - "fred": 0.7, # Macroeconomic data - medium profit probability - "market_data": 0.7, # Market data - high profit probability - "reddit": 0.3, # Social media - low profit probability - "youtube": 0.4, # YouTube - low profit probability - "yahoo finance": 0.5 # Yahoo Finance - medium profit probability -} - -# Options categories for intelligent recommendation based on database content -OPTIONS_CATEGORIES = { - "Major Index ETFs": { - "tickers": ["SPY", "QQQ", "IWM", "DIA", "VTI", "VEA", "VWO", "EFA", "EEM", "IEFA"], - "keywords": ["spy", "qqq", "iwm", "dia", "s&p 500", "nasdaq", "russell", "dow", "index", "etf", "vti", "vea", "vwo", "efa", "eem", "iefa"], - "description": "Major Index ETFs - Market's most liquid index ETFs" - }, - "Tech Giants": { - "tickers": ["AAPL", "MSFT", "GOOGL", "AMZN", "TSLA", "NVDA", "META", "NFLX", "ADBE", "CRM"], - "keywords": ["apple", "microsoft", "google", "amazon", "tesla", "nvidia", "meta", "netflix", "adobe", "salesforce", "tech", "technology", "faanmg"], - "description": "Tech Giants - Leading technology companies with high options liquidity" - }, - "Financial Sector": { - "tickers": ["JPM", "BAC", "WFC", "GS", "MS", "C", "BLK", "AXP", "USB", "PNC"], - "keywords": ["jpmorgan", "bank of america", "wells fargo", "goldman sachs", "morgan stanley", "citigroup", "blackrock", "american express", "us bancorp", "pnc", "bank", "financial", "finance"], - "description": "Financial Sector - Major banks and financial institutions" - }, - "Energy Sector": { - "tickers": ["XOM", "CVX", "COP", "EOG", "PXD", "MPC", "VLO", "PSX", "KMI", "SLB"], - "keywords": ["exxon", "chevron", "conocophillips", "eog", "pioneer", "marathon", "valero", "phillips 66", "kinder morgan", "schlumberger", "oil", "energy", "crude", "petroleum"], - "description": "Energy Sector - Oil and energy companies with active options trading" - }, - "Healthcare Sector": { - "tickers": ["JNJ", "PFE", "UNH", "ABBV", "MRK", "TMO", "ABT", "DHR", "BMY", "AMGN"], - "keywords": ["johnson", "pfizer", "unitedhealth", "abbvie", "merck", "thermo fisher", "abbott", "danaher", "bristol myers", "amgen", "healthcare", "pharmaceutical", "medical", "health"], - "description": "Healthcare Sector - Pharmaceutical and healthcare companies" - }, - "Consumer Goods": { - "tickers": ["WMT", "PG", "KO", "PEP", "COST", "HD", "MCD", "SBUX", "NKE", "TGT"], - "keywords": ["walmart", "procter", "coca-cola", "pepsi", "costco", "home depot", "mcdonalds", "starbucks", "nike", "target", "consumer", "retail"], - "description": "Consumer Goods - Major consumer and retail companies" - }, - "Industrial Sector": { - "tickers": ["BA", "CAT", "GE", "HON", "UPS", "RTX", "LMT", "MMM", "DE", "EMR"], - "keywords": ["boeing", "caterpillar", "general electric", "honeywell", "ups", "raytheon", "lockheed martin", "3m", "deere", "emerson", "industrial", "manufacturing"], - "description": "Industrial Sector - Major industrial and manufacturing companies" - }, - "Commodity ETFs": { - "tickers": ["GLD", "SLV", "USO", "UNG", "DBA", "DBC", "IAU", "SIVR", "UCO", "BOIL"], - "keywords": ["gold", "silver", "oil", "natural gas", "agriculture", "commodity", "precious metal", "gld", "slv", "uso", "ung"], - "description": "Commodity ETFs - Gold, Silver, Oil and other commodity ETFs" - }, - "Volatility Products": { - "tickers": ["VIX", "VXX", "UVXY", "SVXY", "TVIX", "VIXY", "VXXB", "VIXM", "VXZ", "VIX9D"], - "keywords": ["vix", "volatility", "fear index", "volatility index", "vxx", "uvxy", "svxy", "trix"], - "description": "Volatility Products - VIX and volatility-related instruments" - } -} - -class OptionsDataPipeline: - """Options data pipeline - focused on options-related data""" - - def __init__(self, qdrant_client): - self.qdrant = qdrant_client - - def fetch_options_signals(self) -> List[models.Record]: - """Fetch options-related signals from Qdrant""" - try: - response, _ = self.qdrant.scroll( - collection_name="financial_signals", - limit=100, - with_payload=True, - with_vectors=False - ) - - - options_signals = [] - for signal in response: - content = signal.payload.get('page_content', '').upper() - if any(keyword in content for keyword in OPTIONS_KEYWORDS.keys()): - options_signals.append(signal) - - logger.info(f"Fetched {len(options_signals)} options-related signals from {len(response)} total signals") - return options_signals - except Exception as e: - logger.error(f"Error fetching options signals: {e}") - return [] - - def calculate_profit_score(self, signal: models.Record) -> float: - """计算期权盈利概率得分""" - content = signal.payload.get('page_content', '').upper() - source = signal.payload.get('source', '').lower() - - score = 0.0 - - # 1) Data source profit weight (40%) - source_weight = DATA_SOURCE_PROFIT_WEIGHTS.get(source, 0.2) - score += source_weight * 0.4 - - # 2) Options keyword density (30%) - keyword_score = 0.0 - for keyword, weight in OPTIONS_KEYWORDS.items(): - if keyword in content: - keyword_score += weight - - normalized_keyword_score = min(keyword_score / sum(OPTIONS_KEYWORDS.values()), 1.0) - score += normalized_keyword_score * 0.3 - - # 3) Options code pattern detection (20%) - option_patterns = [ - r'\b[A-Z]{2,5}\s+\d+[CP]\b', # AAPL 150C, SPY 450P - r'\$\d+\.?\d*\s+[CP]\b', # $150 C, $450 P - r'STRIKE\s+\$?\d+', # STRIKE $150 - r'EXPIR[EY]\s+\d{1,2}/\d{1,2}', # EXPIRY 12/15 - ] - - pattern_score = 0.0 - for pattern in option_patterns: - if re.search(pattern, content): - pattern_score += 0.25 - - score += pattern_score * 0.2 - - # 4) Explicit options terminology presence (10%) - option_code_score = 0.0 - if any(pattern in content for pattern in ['CALL', 'PUT', 'OPTION', 'STRIKE', 'EXPIR']): - option_code_score = 1.0 - - score += option_code_score * 0.1 - - return min(score, 1.0) - - def select_best_options_signals(self, signals: List[models.Record], target_count: int = 8) -> List[models.Record]: - """Select best options signals by computed profit score""" - # 计算每个信号的盈利得分 - scored_signals = [] - for signal in signals: - profit_score = self.calculate_profit_score(signal) - scored_signals.append((profit_score, signal)) - - # 按盈利得分排序 - scored_signals.sort(key=lambda x: x[0], reverse=True) - - # 选择前N个信号 - selected = [signal for _, signal in scored_signals[:target_count]] - - logger.info(f"Selected {len(selected)} best options signals from {len(signals)} total") - return selected - -class OptionsKnowledgeManager: - """Options knowledge management backed by Qdrant vector DB""" - - def __init__(self, qdrant_client): - self.qdrant = qdrant_client - - def get_options_context(self, underlying: str) -> List[Dict[str, Any]]: - """Get options-related context for a specific underlying""" - try: - response, _ = self.qdrant.scroll( - collection_name="financial_signals", - limit=50, - with_payload=True, - with_vectors=False - ) - - # Filter signals that mention the underlying and options terms - relevant_signals = [] - for signal in response: - content = signal.payload.get("page_content", "").upper() - if (underlying.upper() in content and - any(keyword in content for keyword in OPTIONS_KEYWORDS.keys())): - relevant_signals.append(signal.payload) - - return relevant_signals - except Exception as e: - logger.error(f"Options context error: {e}") - return [] - -class OptionsDecisionArchitecture: - """Options decision architecture - ReAct-based multi-agent system""" - - def __init__(self): - self.analyst = OptionsAnalyst() - self.checker = OptionsFactChecker() - self.critic = OptionsAdversarialCritic() - self.synthesizer = OptionsSynthesizer() - self.uncertainty_quantifier = UncertaintyQuantifier() - self.schema_validator = SchemaValidator() - - def process_options_signal(self, signal_data: Dict[str, Any]) -> Dict[str, Any]: - """Process an options signal using the ReAct protocol""" - # ReAct loop: Reason -> Act -> Observe - max_iterations = 3 - current_state = { - "signal_data": signal_data, - "analysis": None, - "validation": None, - "counter_arguments": [], - "uncertainty_metrics": {}, - "iteration": 0 - } - - for iteration in range(max_iterations): - current_state["iteration"] = iteration - - # 1) REASON: Analyst synthesizes signal - if current_state["analysis"] is None: - current_state["analysis"] = self.analyst.analyze_options_signal(signal_data) - logger.info(f"ReAct Iteration {iteration}: Analyst synthesized signal") - - # 2) ACT: Fact checker validates analysis - if current_state["validation"] is None: - current_state["validation"] = self.checker.validate_options_analysis(current_state["analysis"]) - logger.info(f"ReAct Iteration {iteration}: Checker validated analysis") - - # 3) OBSERVE: Adversarial critic generates counter-arguments - if not current_state["counter_arguments"]: - current_state["counter_arguments"] = self.critic.generate_options_counter_arguments(current_state["analysis"]) - logger.info(f"ReAct Iteration {iteration}: Critic generated {len(current_state['counter_arguments'])} counter-arguments") - - # 4) Uncertainty quantification - current_state["uncertainty_metrics"] = self.uncertainty_quantifier.quantify_uncertainty( - current_state["analysis"], - current_state["validation"], - current_state["counter_arguments"] - ) - - # 5) Determine whether to continue iterating - if self._should_continue_iteration(current_state): - logger.info(f"ReAct Iteration {iteration}: Continuing iteration due to high uncertainty") - continue - else: - logger.info(f"ReAct Iteration {iteration}: Sufficient confidence reached, proceeding to synthesis") - break - - # 6) Final synthesis - final_decision = self.synthesizer.synthesize_options_decision( - current_state["analysis"], - current_state["validation"], - current_state["counter_arguments"], - current_state["uncertainty_metrics"] - ) - - # 7) Schema validation - validated_decision = self.schema_validator.validate_options_decision(final_decision) - - return validated_decision - - def _should_continue_iteration(self, state: Dict[str, Any]) -> bool: - """Decide whether to continue ReAct iterations""" - uncertainty = state["uncertainty_metrics"].get("overall_uncertainty", 0.5) - validation_score = state["validation"].get("validation_score", 0.5) - iteration = state["iteration"] - - # Stop when reaching max iterations (0,1,2) - if iteration >= 2: - return False - - # Continue if uncertainty is high or validation score is low - should_continue = uncertainty > 0.6 or validation_score < 0.7 - - if should_continue: - logger.info(f"ReAct: Continuing iteration due to uncertainty={uncertainty:.2f}, validation={validation_score:.2f}") - else: - logger.info(f"ReAct: Stopping iteration - uncertainty={uncertainty:.2f}, validation={validation_score:.2f}") - - return should_continue - -class UncertaintyQuantifier: - """Uncertainty quantifier implementation""" - - def quantify_uncertainty(self, analysis: Dict[str, Any], validation: Dict[str, Any], counter_arguments: List[str]) -> Dict[str, Any]: - """Quantify uncertainty of the options analysis""" - metrics = {} - - # 1) Signal strength uncertainty - signal_strength = analysis.get("signal_strength", 0.5) - metrics["signal_uncertainty"] = 1.0 - signal_strength - - # 2) Validation uncertainty - validation_score = validation.get("validation_score", 0.5) - metrics["validation_uncertainty"] = 1.0 - validation_score - - # 3) Counter-argument uncertainty - counter_uncertainty = min(len(counter_arguments) * 0.2, 1.0) - metrics["counter_uncertainty"] = counter_uncertainty - - # 4) Data source uncertainty - source = analysis.get("source", "").lower() - source_reliability = { - "sec": 0.9, "newsapi": 0.8, "fred": 0.7, "market_data": 0.8, - "reddit": 0.4, "youtube": 0.5, "yahoo finance": 0.6 - } - source_uncertainty = 1.0 - source_reliability.get(source, 0.5) - metrics["source_uncertainty"] = source_uncertainty - - # 5) Overall uncertainty - overall_uncertainty = ( - metrics["signal_uncertainty"] * 0.3 + - metrics["validation_uncertainty"] * 0.3 + - metrics["counter_uncertainty"] * 0.2 + - metrics["source_uncertainty"] * 0.2 - ) - metrics["overall_uncertainty"] = overall_uncertainty - - # 6) Confidence interval - confidence_interval = self._calculate_confidence_interval(overall_uncertainty) - metrics["confidence_interval"] = confidence_interval - - # 7) Calibration notes - metrics["calibration_notes"] = self._generate_calibration_notes(metrics) - - return metrics - - def _calculate_confidence_interval(self, uncertainty: float) -> Dict[str, float]: - """Compute confidence interval""" - base_confidence = 1.0 - uncertainty - margin_of_error = uncertainty * 0.1 - - return { - "lower_bound": max(0.0, base_confidence - margin_of_error), - "upper_bound": min(1.0, base_confidence + margin_of_error), - "center": base_confidence - } - - def _generate_calibration_notes(self, metrics: Dict[str, Any]) -> List[str]: - """Generate calibration notes""" - notes = [] - - if metrics["overall_uncertainty"] > 0.7: - notes.append("High uncertainty - consider additional data sources") - - if metrics["validation_uncertainty"] > 0.6: - notes.append("Data validation concerns - verify signal quality") - - if metrics["counter_uncertainty"] > 0.5: - notes.append("Multiple counter-arguments - risk assessment needed") - - if metrics["source_uncertainty"] > 0.6: - notes.append("Low-reliability data source - cross-verify information") - - if not notes: - notes.append("Low uncertainty - high confidence in analysis") - - return notes - -class SchemaValidator: - """Schema validator for JSON output""" - - def __init__(self): - self.required_fields = [ - "ticker", "directional_view", "trade_idea", "candidate_strikes", - "tenor", "rationale", "confidence_level", "citations" - ] - - self.valid_directional_views = ["Bullish", "Bearish", "Neutral"] - self.valid_confidence_levels = ["High", "Medium", "Low"] - self.valid_strategy_types = [ - "Buy Call", "Buy Put", "Sell Call", "Sell Put", - "Straddle", "Strangle", "Iron Condor", "Butterfly", - "Covered Call", "Protective Put", "Bull Call Spread", "Bear Put Spread" - ] - - def validate_options_decision(self, decision: Dict[str, Any]) -> Dict[str, Any]: - """Validate JSON schema for the options decision""" - validated = decision.copy() - - # 1) Ensure required fields - for field in self.required_fields: - if field not in validated or not validated[field]: - validated[field] = self._get_default_value(field) - - # 2) Validate enumerated values - validated["directional_view"] = self._validate_directional_view(validated["directional_view"]) - validated["confidence_level"] = self._validate_confidence_level(validated["confidence_level"]) - validated["trade_idea"] = self._validate_strategy_type(validated["trade_idea"]) - - # 3) Coerce data types - validated["candidate_strikes"] = str(validated["candidate_strikes"]) - validated["tenor"] = str(validated["tenor"]) - validated["citations"] = list(validated["citations"]) if isinstance(validated["citations"], list) else [str(validated["citations"])] - - # 4) Add validation metadata - validated["schema_validated"] = True - validated["validation_timestamp"] = datetime.now().isoformat() - - return validated - - def _get_default_value(self, field: str) -> str: - """Get default value for missing field""" - defaults = { - "ticker": "UNKNOWN", - "directional_view": "Neutral", - "trade_idea": "Straddle", - "candidate_strikes": "TBD", - "tenor": (datetime.now() + timedelta(days=30)).strftime("%Y-%m-%d"), - "rationale": "Analysis based on database content", - "confidence_level": "Medium", - "citations": ["Database Analysis"] - } - return defaults.get(field, "N/A") - - def _validate_directional_view(self, view: str) -> str: - """Validate directional view value""" - if view in self.valid_directional_views: - return view - return "Neutral" - - def _validate_confidence_level(self, level: str) -> str: - """Validate confidence level value""" - if level in self.valid_confidence_levels: - return level - return "Medium" - - def _validate_strategy_type(self, strategy: str) -> str: - """Validate strategy type value""" - if strategy in self.valid_strategy_types: - return strategy - return "Straddle" - -class OptionsAnalyst: - """Options analyst - analyze options signals""" - - def analyze_options_signal(self, signal_data: Dict[str, Any]) -> Dict[str, Any]: - """Analyze a single options signal""" - content = signal_data.get("page_content", "") - source = signal_data.get("source", "") - - # Compute signal strength - strength = self._calculate_options_signal_strength(content, source) - - # Extract options-related information - underlying = self._extract_underlying(content) - sentiment = self._analyze_options_sentiment(content) - volatility = self._assess_implied_volatility(content) - strategy_type = self._determine_strategy_type(content, sentiment) - - return { - "signal_strength": strength, - "underlying": underlying, - "sentiment": sentiment, - "volatility": volatility, - "strategy_type": strategy_type, - "source": source, - "content": content[:300] - } - - def _calculate_options_signal_strength(self, content: str, source: str) -> float: - """Compute options signal strength""" - score = 0.0 - content_upper = content.upper() - source_lower = source.lower() - - # Based on data source weights - score += DATA_SOURCE_PROFIT_WEIGHTS.get(source_lower, 0.2) - - # Based on options keywords - keyword_score = 0.0 - for keyword, weight in OPTIONS_KEYWORDS.items(): - if keyword in content_upper: - keyword_score += weight - - normalized_keyword_score = min(keyword_score / sum(OPTIONS_KEYWORDS.values()), 1.0) - score += normalized_keyword_score * 0.4 - - # Based on options code patterns - option_patterns = [ - r'\b[A-Z]{2,5}\s+\d+[CP]\b', - r'\$\d+\.?\d*\s+[CP]\b', - r'STRIKE\s+\$?\d+', - r'EXPIR[EY]\s+\d{1,2}/\d{1,2}', - ] - - pattern_score = 0.0 - for pattern in option_patterns: - if re.search(pattern, content_upper): - pattern_score += 0.25 - - score += pattern_score * 0.3 - - return min(score, 1.0) - - def _extract_underlying(self, content: str) -> str: - """Recommend option category/underlying based on DB content (frequency matching)""" - content_lower = content.lower() - content_upper = content.upper() - - # 1) First, search for explicit option code patterns - option_patterns = [ - r'\b([A-Z]{2,5})\s+\d+[CP]\b', # AAPL 150C, SPY 450P - r'\$([A-Z]{2,5})\b', # $AAPL, $SPY - r'\b([A-Z]{2,5})\s+OPTION\b', # AAPL OPTION - r'\b([A-Z]{2,5})\s+CALL\b', # AAPL CALL - r'\b([A-Z]{2,5})\s+PUT\b', # AAPL PUT - r'\b([A-Z]{2,5})\s+STRIKE\b', # AAPL STRIKE - r'\b([A-Z]{2,5})\s+EXPIR\b', # AAPL EXPIRY - ] - - # Find explicit option patterns - for pattern in option_patterns: - matches = re.findall(pattern, content_upper) - for match in matches: - ticker = match.strip() - # 验证是否在期权类别中 - for category_data in OPTIONS_CATEGORIES.values(): - if ticker in category_data["tickers"]: - logger.info(f"✓ Found explicit ticker {ticker} in content") - return ticker - - # 2) Recommend category based on keyword frequency - category_scores = {} - for category_name, category_data in OPTIONS_CATEGORIES.items(): - score = 0 - matched_keywords = [] - - # Check tickers - for ticker in category_data["tickers"]: - if ticker in content_upper: - score += 2 # higher weight for direct ticker match - matched_keywords.append(ticker) - - # Check keywords - for keyword in category_data["keywords"]: - if keyword in content_lower: - score += 1 - matched_keywords.append(keyword) - - # Check keywords from description - description_words = category_data["description"].lower().split() - for word in description_words: - if len(word) > 3 and word in content_lower: # only match words length > 3 - score += 1 - matched_keywords.append(word) - - if score > 0: - category_scores[category_name] = { - 'score': score, - 'matched_keywords': matched_keywords - } - logger.info(f"✓ Category '{category_name}' scored {score} with keywords: {matched_keywords}") - - # 3) Choose top-scoring category and return one of the most liquid tickers - if category_scores: - best_category = max(category_scores, key=lambda x: category_scores[x]['score']) - best_tickers = OPTIONS_CATEGORIES[best_category]["tickers"] - - # Select among most liquid tickers (typically first 3-5) - top_liquid_tickers = best_tickers[:5] - - import random - selected_ticker = random.choice(top_liquid_tickers) - score_info = category_scores[best_category] - logger.info(f"✓ Selected {selected_ticker} from category '{best_category}' (score: {score_info['score']}, top liquid tickers: {top_liquid_tickers})") - return selected_ticker - - # 4) If no keyword match, find any known tickers mentioned - for category_data in OPTIONS_CATEGORIES.values(): - for ticker in category_data["tickers"]: - if ticker in content_upper: - logger.info(f"✓ Found ticker {ticker} mentioned in content") - return ticker - - # 5) Default to SPY (high-liquidity major index ETF) - logger.info("✓ No specific category matched, defaulting to SPY (most liquid Major Index ETF)") - return 'SPY' - - def get_top_liquid_options_for_category(self, category_name: str, count: int = 5) -> List[str]: - """Get most liquid option underlyings for a category""" - if category_name not in OPTIONS_CATEGORIES: - logger.warning(f"Category '{category_name}' not found, returning default") - return ['SPY'] - - category_data = OPTIONS_CATEGORIES[category_name] - all_tickers = category_data["tickers"] - - # Return top-N most liquid tickers - top_liquid = all_tickers[:count] - logger.info(f"✓ Top {count} liquid options for '{category_name}': {top_liquid}") - return top_liquid - - def _analyze_options_sentiment(self, content: str) -> str: - """Analyze options sentiment""" - content_lower = content.lower() - - # Options-specific sentiment indicators - bullish_indicators = ["call", "bullish", "upside", "breakout", "momentum", "growth"] - bearish_indicators = ["put", "bearish", "downside", "breakdown", "decline", "weakness"] - - bullish_count = sum(1 for indicator in bullish_indicators if indicator in content_lower) - bearish_count = sum(1 for indicator in bearish_indicators if indicator in content_lower) - - if bullish_count > bearish_count: - return "Bullish" - elif bearish_count > bullish_count: - return "Bearish" - else: - return "Neutral" - - def _assess_implied_volatility(self, content: str) -> str: - """Assess implied volatility""" - content_lower = content.lower() - - if any(term in content_lower for term in ["high iv", "high volatility", "volatile", "vix high"]): - return "High" - elif any(term in content_lower for term in ["low iv", "low volatility", "stable", "vix low"]): - return "Low" - else: - return "Medium" - - def _determine_strategy_type(self, content: str, sentiment: str) -> str: - """Determine strategy type - risk-averse preference""" - content_lower = content.lower() - - # Risk-averse preference: favor lower-risk, stable-return strategies - - # 1) Based on explicit strategy keywords - if "straddle" in content_lower or "strangle" in content_lower: - return "Straddle" # risk-averse: prefer Straddle over Strangle - elif "iron condor" in content_lower or "condor" in content_lower: - return "Iron Condor" # risk-averse: income strategy - elif "butterfly" in content_lower: - return "Butterfly" # risk-averse: limited-risk strategy - elif "covered call" in content_lower: - return "Covered Call" # risk-averse: income strategy - elif "protective put" in content_lower: - return "Protective Put" # risk-averse: protection strategy - - # 2) Sentiment-based selection (risk-averse) - elif sentiment == "Bullish": - # Bullish: favor Covered Call / Bull Call Spread - return "Covered Call" # conservative bullish - elif sentiment == "Bearish": - # Bearish: favor Protective Put - return "Protective Put" - else: - # Neutral: favor Iron Condor (income) - return "Iron Condor" - -class OptionsFactChecker: - """Options fact checker - validate analysis""" - - def validate_options_analysis(self, analysis: Dict[str, Any]) -> Dict[str, Any]: - """Validate options analysis result""" - validation_score = 0.0 - issues = [] - - # Check signal strength - if analysis["signal_strength"] > 0.7: - validation_score += 0.3 - elif analysis["signal_strength"] > 0.4: - validation_score += 0.2 - else: - issues.append("Low options signal strength") - - # Check underlying validity - if analysis["underlying"] and len(analysis["underlying"]) >= 2: - validation_score += 0.3 - else: - issues.append("Invalid underlying symbol") - - # Check strategy type - if analysis["strategy_type"] in ["Buy Call", "Buy Put", "Straddle/Strangle", "Iron Condor", "Butterfly"]: - validation_score += 0.2 - else: - issues.append("Unclear strategy type") - - # Check volatility assessment - if analysis["volatility"] in ["High", "Medium", "Low"]: - validation_score += 0.1 - else: - issues.append("Invalid volatility assessment") - - # Check content length/quality - if len(analysis["content"]) > 150: - validation_score += 0.1 - else: - issues.append("Insufficient content for options analysis") - - return { - "validation_score": min(validation_score, 1.0), - "issues": issues, - "is_valid": validation_score > 0.5 - } - -class OptionsAdversarialCritic: - """Options adversarial critic - generate counter-arguments""" - - def generate_options_counter_arguments(self, analysis: Dict[str, Any]) -> List[str]: - """Generate options counter-arguments""" - counter_arguments = [] - - if analysis["sentiment"] == "Bullish": - counter_arguments.extend([ - "Call options may be overpriced due to high implied volatility", - "Market correction could lead to significant call option losses", - "Time decay may erode call option value even if direction is correct" - ]) - elif analysis["sentiment"] == "Bearish": - counter_arguments.extend([ - "Put options may be expensive due to fear premium", - "Oversold bounce could lead to put option losses", - "Market may have already priced in negative sentiment" - ]) - - if analysis["strategy_type"] == "Straddle/Strangle": - counter_arguments.append("Straddle strategies require significant price movement to be profitable") - - if analysis["volatility"] == "High": - counter_arguments.append("High IV environment makes options expensive and reduces profit potential") - elif analysis["volatility"] == "Low": - counter_arguments.append("Low IV may not provide enough movement for profitable options trades") - - if analysis["signal_strength"] > 0.7: - counter_arguments.append("High signal strength may indicate overconfidence in options strategy") - - return counter_arguments - -class OptionsSynthesizer: - """Options synthesizer - produce final decision""" - - def synthesize_options_decision(self, analysis: Dict[str, Any], validation: Dict[str, Any], counter_arguments: List[str], uncertainty_metrics: Dict[str, Any] = None) -> Dict[str, Any]: - """Synthesize all information into a final options decision""" - # Compute combined confidence - base_confidence = analysis["signal_strength"] - validation_penalty = 0.1 if not validation["is_valid"] else 0 - counter_penalty = len(counter_arguments) * 0.05 - - # Apply uncertainty adjustment - uncertainty_adjustment = 0 - if uncertainty_metrics: - uncertainty_adjustment = uncertainty_metrics.get("overall_uncertainty", 0) * 0.2 - - final_confidence = max(0.1, base_confidence - validation_penalty - counter_penalty - uncertainty_adjustment) - - # Map to confidence level label - if final_confidence > 0.7: - confidence_level = "High" - elif final_confidence > 0.4: - confidence_level = "Medium" - else: - confidence_level = "Low" - - # Use underlying from analysis - underlying = analysis["underlying"] - - # Strategy type - strategy_type = analysis["strategy_type"] - - # Compute strike and expiration - strike_price, expiration_date, current_price = self._calculate_options_parameters(underlying, analysis["sentiment"], analysis["volatility"], final_confidence) - - # Generate textual rationale - rationale = self._generate_options_rationale(analysis, validation, counter_arguments, final_confidence, uncertainty_metrics, underlying, strike_price, current_price) - - # Determine option type label (Call/Put/Straddle) - option_type = self._determine_option_type(analysis["sentiment"], strategy_type) - - # Build decision payload - decision = { - "ticker": underlying, - "directional_view": analysis["sentiment"], - "trade_idea": strategy_type, - "option_type": option_type, # Call/Put/Straddle - "candidate_strikes": f"${strike_price:.2f}", - "strike_price": round(strike_price, 2), - "tenor": expiration_date, - "expiration_date": expiration_date, - "rationale": rationale, - "confidence_level": confidence_level, - "citations": [analysis["source"], "ReAct Multi-Agent Analysis"], - "signal_strength": round(final_confidence, 2), - "validation_score": round(validation["validation_score"], 2), - "counter_arguments": counter_arguments[:2], - "volatility_assessment": analysis["volatility"], - "strategy_type": strategy_type - } - - # Attach uncertainty metrics if available - if uncertainty_metrics: - # 格式化不确定性指标 - formatted_uncertainty = {} - for key, value in uncertainty_metrics.items(): - if isinstance(value, (int, float)): - formatted_uncertainty[key] = round(value, 2) - else: - formatted_uncertainty[key] = value - - decision.update({ - "uncertainty_metrics": formatted_uncertainty, - "confidence_interval": uncertainty_metrics.get("confidence_interval", {}), - "calibration_notes": uncertainty_metrics.get("calibration_notes", []), - "overall_uncertainty": round(uncertainty_metrics.get("overall_uncertainty", 0.5), 2) - }) - - return decision - - def _calculate_options_parameters(self, underlying: str, sentiment: str, volatility: str, confidence: float) -> Tuple[float, str, float]: - """Calculate option parameters using yfinance when possible""" - try: - # 1) Get stock info - stock_info = yfinance_client.get_stock_info(underlying) - current_price = stock_info.get('current_price', 0) - - if current_price == 0: - logger.warning(f"Could not get current price for {underlying}, using fallback") - # Fallback to Alpha Vantage - quote = alpha_vantage_client.get_real_time_quote(underlying) - if quote and '05. price' in quote: - current_price = float(quote['05. price']) - else: - current_price = 100.0 # 默认价格 - - logger.info(f"Current price for {underlying}: ${current_price}") - - # 2) Get options expirations - expirations = yfinance_client.get_options_expirations(underlying) - if not expirations: - logger.warning(f"No options expirations found for {underlying}, generating default") - # Generate default expiration - if volatility == "High": - days_to_expiry = random.randint(15, 30) - elif volatility == "Low": - days_to_expiry = random.randint(45, 60) - else: - days_to_expiry = random.randint(30, 45) - expiration_date = (datetime.now() + timedelta(days=days_to_expiry)).strftime("%Y-%m-%d") - else: - # Pick suitable expiration - if volatility == "High": - # High IV: nearer expirations - expiration_date = expirations[0] if len(expirations) > 0 else expirations[-1] - elif volatility == "Low": - # Low IV: further expirations - expiration_date = expirations[-1] if len(expirations) > 0 else expirations[0] - else: - # Medium IV: mid expirations - mid_index = len(expirations) // 2 - expiration_date = expirations[mid_index] if len(expirations) > mid_index else expirations[0] - - logger.info(f"Selected expiration date for {underlying}: {expiration_date}") - - # 3) Get liquid strikes - liquid_strikes = yfinance_client.get_liquid_strikes(underlying, expiration_date, min_volume=5) - - if not liquid_strikes: - # If none, get ATM strikes - liquid_strikes = yfinance_client.get_atm_strikes(underlying, expiration_date, count=10) - - if not liquid_strikes: - logger.warning(f"No liquid strikes found for {underlying}, generating based on current price") - # Generate strike based on current price - if sentiment == "Bullish": - strike_price = current_price * 1.02 # 2% OTM - elif sentiment == "Bearish": - strike_price = current_price * 0.98 # 2% OTM - else: - strike_price = current_price # ATM - else: - # Choose strike according to sentiment - if sentiment == "Bullish": - # Bullish: slightly above spot - bullish_strikes = [s for s in liquid_strikes if s > current_price] - strike_price = bullish_strikes[0] if bullish_strikes else liquid_strikes[0] - elif sentiment == "Bearish": - # Bearish: slightly below spot - bearish_strikes = [s for s in liquid_strikes if s < current_price] - strike_price = bearish_strikes[-1] if bearish_strikes else liquid_strikes[-1] - else: - # Neutral: nearest to spot - strike_price = min(liquid_strikes, key=lambda x: abs(x - current_price)) - - logger.info(f"Selected strike price for {underlying}: ${strike_price}") - - return round(strike_price, 2), expiration_date, current_price - - except Exception as e: - logger.error(f"Error calculating options parameters for {underlying}: {e}") - # Fallback to simple calculation - base_price = 100.0 - if sentiment == "Bullish": - strike_price = base_price * 1.02 - elif sentiment == "Bearish": - strike_price = base_price * 0.98 - else: - strike_price = base_price - - days_to_expiry = 30 - expiration_date = (datetime.now() + timedelta(days=days_to_expiry)).strftime("%Y-%m-%d") - - return round(strike_price, 2), expiration_date, base_price - - def _determine_option_type(self, sentiment: str, strategy_type: str) -> str: - """Determine final option type label""" - if strategy_type in ["Buy Call", "Bull Call Spread", "Covered Call"]: - return "Call" - elif strategy_type in ["Buy Put", "Bear Put Spread", "Protective Put"]: - return "Put" - elif strategy_type in ["Straddle", "Strangle", "Long Straddle", "Long Strangle"]: - return "Straddle" - elif strategy_type in ["Iron Condor", "Butterfly"]: - return "Spread" - else: - # 根据情绪确定 - if sentiment == "Bullish": - return "Call" - elif sentiment == "Bearish": - return "Put" - else: - return "Straddle" - - def _generate_options_rationale(self, analysis: Dict[str, Any], validation: Dict[str, Any], counter_arguments: List[str], confidence: float, uncertainty_metrics: Dict[str, Any] = None, underlying: str = None, strike_price: float = None, current_price: float = None) -> str: - """生成期权详细理由,包含详细的数据指标""" - rationale_parts = [] - - # 基于信号强度 - if confidence > 0.7: - rationale_parts.append(f"Strong options signal strength ({confidence:.2f}) from {analysis['source']} analysis") - elif confidence > 0.4: - rationale_parts.append(f"Moderate options signal strength ({confidence:.2f}) from {analysis['source']} analysis") - else: - rationale_parts.append(f"Low options signal strength ({confidence:.2f}) from {analysis['source']} analysis") - - # 添加详细的数据指标 - if underlying and strike_price and current_price: - # 计算内在价值和时间价值 - if analysis["sentiment"] == "Bullish": - intrinsic_value = max(0, current_price - strike_price) - moneyness = "ITM" if current_price > strike_price else "OTM" if current_price < strike_price else "ATM" - elif analysis["sentiment"] == "Bearish": - intrinsic_value = max(0, strike_price - current_price) - moneyness = "ITM" if current_price < strike_price else "OTM" if current_price > strike_price else "ATM" - else: - intrinsic_value = 0 - moneyness = "ATM" if abs(current_price - strike_price) / current_price < 0.02 else "OTM" - - # 估算期权价格(简化Black-Scholes) - time_to_expiry = 30 # 假设30天到期 - volatility = 0.25 # 假设25%波动率 - risk_free_rate = 0.05 # 假设5%无风险利率 - - # 简化的期权价格估算 - if analysis["sentiment"] == "Bullish": - estimated_premium = max(intrinsic_value + (current_price * volatility * (time_to_expiry/365)**0.5), 0.5) - elif analysis["sentiment"] == "Bearish": - estimated_premium = max(intrinsic_value + (current_price * volatility * (time_to_expiry/365)**0.5), 0.5) - else: - estimated_premium = current_price * volatility * (time_to_expiry/365)**0.5 * 2 # Straddle - - time_value = max(0, estimated_premium - intrinsic_value) - - # 计算Delta(简化) - if analysis["sentiment"] == "Bullish": - delta = 0.5 + (current_price - strike_price) / (strike_price * 0.1) * 0.3 - delta = max(0.1, min(0.9, delta)) - elif analysis["sentiment"] == "Bearish": - delta = 0.5 - (current_price - strike_price) / (strike_price * 0.1) * 0.3 - delta = max(-0.9, min(-0.1, delta)) - else: - delta = 0.0 # Straddle delta near 0 - - - historical_vol = 0.20 - expected_return = 0.08 - sharpe_ratio = expected_return / historical_vol - - # 计算其他Greeks - gamma = 0.01 # 简化Gamma - theta = -estimated_premium / time_to_expiry # 时间衰减 - vega = current_price * (time_to_expiry/365)**0.5 * 0.01 # 波动率敏感度 - - rationale_parts.append(f"**Price Analysis:** Current price ${current_price:.2f} vs Strike ${strike_price:.2f} ({moneyness})") - rationale_parts.append(f"**Intrinsic Value:** ${intrinsic_value:.2f}, Time Value: ${time_value:.2f}, Estimated Premium: ${estimated_premium:.2f}") - rationale_parts.append(f"**Greeks:** Delta={delta:.3f}, Gamma={gamma:.3f}, Theta={theta:.3f}, Vega={vega:.3f}") - rationale_parts.append(f"**Risk Metrics:** Sharpe Ratio={sharpe_ratio:.2f}, Volatility={volatility:.1%}") - - # 基于期权情绪 - if analysis["sentiment"] == "Bullish": - rationale_parts.append("Bullish sentiment supports call option strategies") - elif analysis["sentiment"] == "Bearish": - rationale_parts.append("Bearish sentiment supports put option strategies") - else: - rationale_parts.append("Neutral sentiment suggests straddle/strangle strategies") - - # 基于波动率 - if analysis["volatility"] == "High": - rationale_parts.append("High implied volatility environment favors short premium strategies") - elif analysis["volatility"] == "Low": - rationale_parts.append("Low implied volatility environment favors long premium strategies") - else: - rationale_parts.append("Medium volatility environment supports balanced options strategies") - - # 基于验证结果 - if validation["is_valid"]: - rationale_parts.append("Fact-checked options analysis confirms data quality") - else: - rationale_parts.append("Some options data quality concerns noted") - - # 基于反论点 - if counter_arguments: - rationale_parts.append(f"Consider {len(counter_arguments)} counter-arguments in options risk assessment") - - # 基于不确定性量化 - if uncertainty_metrics: - overall_uncertainty = uncertainty_metrics.get("overall_uncertainty", 0.5) - if overall_uncertainty > 0.7: - rationale_parts.append("High uncertainty environment - exercise caution in position sizing") - elif overall_uncertainty < 0.3: - rationale_parts.append("Low uncertainty environment - high confidence in strategy") - - # 添加校准注释 - calibration_notes = uncertainty_metrics.get("calibration_notes", []) - if calibration_notes: - rationale_parts.append(f"Risk considerations: {', '.join(calibration_notes[:2])}") - - return ". ".join(rationale_parts) + "." - -class OptionsReportGenerator: - """Options report generator""" - - def __init__(self): - self.qdrant = qdrant_client.QdrantClient(host=QDRANT_HOST, port=QDRANT_PORT) - self.data_pipeline = OptionsDataPipeline(self.qdrant) - self.knowledge_manager = OptionsKnowledgeManager(self.qdrant) - self.decision_architecture = OptionsDecisionArchitecture() - - def generate_daily_options_report(self) -> Dict[str, Any]: - """Generate daily options report""" - logger.info("🚀 Starting options report generation...") - start_time = datetime.now() - - # 1) Data pipeline - fetch options signals - logger.info("📊 Options Data Pipeline: Fetching options-related signals...") - options_signals = self.data_pipeline.fetch_options_signals() - - if not options_signals: - logger.error("❌ No options signals found. Exiting.") - return {"error": "No options signals available"} - - # 2) Select best signals - logger.info("🎯 Selecting best options signals by profit probability...") - best_signals = self.data_pipeline.select_best_options_signals(options_signals, target_count=8) - - # 3) Decision architecture - multi-agent processing - logger.info("🤖 Options Decision Architecture: Processing signals with multi-agent system...") - - # 4) Generate trading ideas - ensure no duplicates, at least 5 - ideas = [] - successful_ideas = 0 - target_ideas = random.randint(5, 10) - min_ideas = 5 # minimum 5 recommendations - used_underlyings = set() # track used underlyings - used_combinations = set() # track used underlying+strategy pairs - - # Load today's recommendations from DB to avoid duplicates - today_recommendations = self._load_today_recommendations() - - for i, signal in enumerate(best_signals): - if successful_ideas >= target_ideas: - break - - profit_score = self.data_pipeline.calculate_profit_score(signal) - logger.info(f"🔄 Processing signal {i+1}/{len(best_signals)} (profit score: {profit_score:.2f})...") - - try: - # Process via ReAct protocol - decision = self.decision_architecture.process_options_signal(signal.payload) - - if decision and decision.get("ticker"): - ticker = decision["ticker"] - strategy = decision.get("trade_idea", "Straddle") - combination = f"{ticker}_{strategy}" - - # Check duplicates (underlying or combination) - if (ticker not in used_underlyings and - combination not in used_combinations and - ticker not in today_recommendations): - - ideas.append(decision) - used_underlyings.add(ticker) - used_combinations.add(combination) - successful_ideas += 1 - logger.info(f"✅ Generated {strategy} for {ticker} (confidence: {decision['confidence_level']})") - else: - logger.info(f"⚠️ Skipping duplicate: {ticker} {strategy}, trying next signal...") - continue - else: - logger.warning(f"⚠️ Failed to generate valid options idea from signal {i+1}") - - except Exception as e: - logger.error(f"❌ Error processing signal {i+1}: {e}") - continue - - # If not enough ideas, try to generate more - if successful_ideas < min_ideas: - logger.info(f"⚠️ Only generated {successful_ideas} ideas, need at least {min_ideas}. Attempting to generate more...") - additional_signals = self.data_pipeline.select_best_options_signals(options_signals, target_count=30) - - for signal in additional_signals[len(best_signals):]: - if successful_ideas >= 10: - break - - try: - decision = self.decision_architecture.process_options_signal(signal.payload) - if decision and decision.get("ticker"): - ticker = decision["ticker"] - strategy = decision.get("trade_idea", "Straddle") - combination = f"{ticker}_{strategy}" - - if (ticker not in used_underlyings and - combination not in used_combinations and - ticker not in today_recommendations): - - ideas.append(decision) - used_underlyings.add(ticker) - used_combinations.add(combination) - successful_ideas += 1 - logger.info(f"✅ Additional: {strategy} for {ticker}") - except Exception as e: - continue - - # If still below minimum, generate default recommendations - if successful_ideas < min_ideas: - logger.info(f"⚠️ Still only {successful_ideas} ideas, generating default recommendations to reach minimum of {min_ideas}...") - default_tickers = ['SPY', 'QQQ', 'AAPL', 'MSFT', 'TSLA', 'NVDA', 'META', 'GOOGL', 'AMZN', 'NFLX'] - - for ticker in default_tickers: - if successful_ideas >= min_ideas: - break - - if ticker not in used_underlyings and ticker not in today_recommendations: - try: - # Create default recommendation - default_decision = { - "ticker": ticker, - "directional_view": "Neutral", - "trade_idea": "Iron Condor", - "option_type": "Spread", - "candidate_strikes": "$100.00", - "strike_price": 100.0, - "tenor": "30 days", - "expiration_date": "2025-11-04", - "rationale": f"Default recommendation for {ticker} based on high liquidity and market activity. Risk-averse strategy suitable for conservative investors.", - "confidence_level": "Medium", - "citations": ["Default Recommendation"], - "signal_strength": 0.5, - "validation_score": 0.7, - "counter_arguments": ["Default recommendation - limited market analysis"], - "volatility_assessment": "Medium", - "strategy_type": "Iron Condor", - "uncertainty_metrics": { - "signal_uncertainty": 0.2, - "validation_uncertainty": 0.2, - "counter_uncertainty": 0.2, - "source_uncertainty": 0.1, - "overall_uncertainty": 0.2, - "confidence_interval": {"lower_bound": 0.6, "upper_bound": 0.8, "center": 0.7}, - "calibration_notes": ["Default recommendation"] - } - } - - # Try to enrich with real data from yfinance - try: - stock_info = yfinance_client.get_stock_info(ticker) - if stock_info and stock_info.get('current_price', 0) > 0: - current_price = stock_info['current_price'] - expirations = yfinance_client.get_options_expirations(ticker) - if expirations: - expiration_date = expirations[0] if len(expirations) > 0 else "2025-11-04" - liquid_strikes = yfinance_client.get_liquid_strikes(ticker, expiration_date, min_volume=5) - if liquid_strikes: - strike_price = min(liquid_strikes, key=lambda x: abs(x - current_price)) - default_decision.update({ - "candidate_strikes": f"${strike_price:.2f}", - "strike_price": round(strike_price, 2), - "expiration_date": expiration_date, - "tenor": expiration_date - }) - except Exception as e: - logger.warning(f"Could not get real data for {ticker}: {e}") - - ideas.append(default_decision) - used_underlyings.add(ticker) - successful_ideas += 1 - logger.info(f"✅ Added default recommendation for {ticker}") - - except Exception as e: - logger.error(f"Error creating default recommendation for {ticker}: {e}") - continue - - # Save today's recommendations - self._save_today_recommendations(used_underlyings) - - # 5) Generate final options report - if ideas: - report = self._create_final_options_report(ideas, start_time, options_signals) - logger.info(f"✅ Successfully generated {len(ideas)} options trading ideas") - else: - logger.error("❌ Failed to generate any valid options ideas") - report = {"error": "No valid options ideas generated"} - - end_time = datetime.now() - execution_time = (end_time - start_time).total_seconds() - logger.info(f"⏱️ Total execution time: {execution_time:.2f} seconds") - - return report - - def _create_final_options_report(self, ideas: List[Dict[str, Any]], start_time: datetime, options_signals: List[models.Record]) -> Dict[str, Any]: - """创建最终期权报告""" - date_str = start_time.strftime("%Y-%m-%d") - report_dir = os.path.join(REPORTS_BASE_DIR, date_str) - - try: - os.makedirs(report_dir, exist_ok=True) - - # 按信号强度排序 - ideas.sort(key=lambda x: x.get("signal_strength", 0), reverse=True) - - # 统计数据源 - data_sources = set() - for signal in options_signals: - data_sources.add(signal.payload.get("source", "unknown")) - - # 创建JSON报告 - json_data = { - "report_date": date_str, - "total_ideas": len(ideas), - "ideas": ideas, - "metadata": { - "generated_at": datetime.now().isoformat(), - "model_used": OLLAMA_MODEL, - "generation_method": "Options Multi-Agent System", - "data_sources": list(data_sources), - "total_options_signals_analyzed": len(options_signals), - "avg_signal_strength": sum(idea.get("signal_strength", 0) for idea in ideas) / len(ideas) if ideas else 0, - "avg_confidence": sum(1 if idea.get("confidence_level") == "High" else 0.5 if idea.get("confidence_level") == "Medium" else 0.1 for idea in ideas) / len(ideas) if ideas else 0, - "strategy_types": list(set(idea.get("strategy_type", "") for idea in ideas)), - "underlyings": list(set(idea.get("ticker", "") for idea in ideas)) - } - } - - # 保存JSON报告 - json_path = os.path.join(report_dir, "options_ideas.json") - with open(json_path, 'w', encoding='utf-8') as f: - json.dump(json_data, f, indent=2, ensure_ascii=False) - - # 创建Markdown报告 - markdown_metadata = { - "report_date": date_str, - "total_ideas": len(ideas), - "data_sources": list(data_sources), - "total_options_signals_analyzed": len(options_signals), - "avg_signal_strength": sum(idea.get("signal_strength", 0) for idea in ideas) / len(ideas) if ideas else 0, - "avg_confidence": sum(1 if idea.get("confidence_level") == "High" else 0.5 if idea.get("confidence_level") == "Medium" else 0.1 for idea in ideas) / len(ideas) if ideas else 0, - "strategy_types": list(set(idea.get("strategy_type", "") for idea in ideas)), - "underlyings": list(set(idea.get("ticker", "") for idea in ideas)) - } - markdown_content = self._create_options_markdown_report(ideas, markdown_metadata) - markdown_path = os.path.join(report_dir, "options_ideas.md") - with open(markdown_path, 'w', encoding='utf-8') as f: - f.write(markdown_content) - - logger.info(f"✅ Options reports saved to: {json_path} and {markdown_path}") - - return { - "success": True, - "ideas": ideas, - "metadata": json_data["metadata"], - "files": { - "json": json_path, - "markdown": markdown_path - } - } - - except Exception as e: - logger.error(f"❌ Error creating options report: {e}") - return {"error": f"Failed to create options report: {e}"} - - def _create_options_markdown_report(self, ideas: List[Dict[str, Any]], metadata: Dict[str, Any]) -> str: - """Create the options report in Markdown format""" - content = f"# Daily Options Trading Ideas - Expert Analysis\n" - content += f"## Report for {metadata.get('report_date', 'Unknown Date')}\n\n" - content += f"**Generated Ideas:** {metadata['total_ideas']}\n" - content += f"**Data Sources:** {', '.join(metadata['data_sources'])}\n" - content += f"**Total Options Signals Analyzed:** {metadata['total_options_signals_analyzed']}\n" - content += f"**Average Signal Strength:** {metadata['avg_signal_strength']:.2f}\n" - content += f"**Average Confidence:** {metadata['avg_confidence']:.2f}\n" - content += f"**Strategy Types:** {', '.join(metadata['strategy_types'])}\n" - content += f"**Underlyings:** {', '.join(metadata['underlyings'])}\n\n" - - for i, idea in enumerate(ideas, 1): - content += f"## Options Idea #{i}\n\n" - content += f"**Ticker:** {idea['ticker']}\n" - content += f"**Directional View:** {idea['directional_view']}\n" - content += f"**Trade Idea:** {idea['trade_idea']}\n" - content += f"**Option Type:** {idea.get('option_type', 'N/A')}\n" - content += f"**Candidate Strike(s):** {idea['candidate_strikes']}\n" - content += f"**Strike Price:** ${idea.get('strike_price', 0):.2f}\n" - content += f"**Expiration Date:** {idea['tenor']}\n" - content += f"**Tenor:** {idea.get('expiration_date', idea['tenor'])}\n" - content += f"**Rationale:** {idea['rationale']}\n" - content += f"**Confidence Level:** {idea['confidence_level']}\n" - content += f"**Citations:** {', '.join(idea['citations'])}\n" - content += f"**Signal Strength:** {idea.get('signal_strength', 0.00):.2f}\n" - content += f"**Validation Score:** {idea.get('validation_score', 0.00):.2f}\n" - content += f"**Volatility Assessment:** {idea.get('volatility_assessment', 'N/A')}\n" - content += f"**Strategy Type:** {idea.get('strategy_type', 'N/A')}\n" - if idea.get('counter_arguments'): - content += f"**Counter-Arguments:** {', '.join(idea['counter_arguments'])}\n" - content += f"**Uncertainty Notes:** {idea.get('uncertainty_notes', 'N/A')}\n\n" - content += "---\n\n" - - return content - - def _load_today_recommendations(self) -> set: - """Load today's recommended tickers""" - try: - today = datetime.now().strftime("%Y-%m-%d") - record_file = os.path.join(REPORTS_BASE_DIR, f"{today}_recommendations.json") - - if os.path.exists(record_file): - with open(record_file, 'r') as f: - data = json.load(f) - return set(data.get("recommended_tickers", [])) - return set() - except Exception as e: - logger.warning(f"Failed to load today's recommendations: {e}") - return set() - - def _save_today_recommendations(self, recommended_tickers: set): - """Save today's recommended tickers""" - try: - today = datetime.now().strftime("%Y-%m-%d") - record_file = os.path.join(REPORTS_BASE_DIR, f"{today}_recommendations.json") - - data = { - "date": today, - "recommended_tickers": list(recommended_tickers), - "timestamp": datetime.now().isoformat() - } - - with open(record_file, 'w') as f: - json.dump(data, f, indent=2) - - logger.info(f"Saved today's recommendations: {list(recommended_tickers)}") - except Exception as e: - logger.warning(f"Failed to save today's recommendations: {e}") - -def main(): - """Main entry point""" - try: - generator = OptionsReportGenerator() - result = generator.generate_daily_options_report() - - if result.get("success"): - print("✅ Options report generation completed successfully!") - print(f"📊 Generated {len(result['ideas'])} high-quality options trading ideas") - print(f"📁 Reports saved to: {result['files']['json']} and {result['files']['markdown']}") - else: - print(f"❌ Options report generation failed: {result.get('error', 'Unknown error')}") - - except Exception as e: - logger.error(f"❌ Fatal error: {e}") - print(f"❌ Fatal error: {e}") - -if __name__ == "__main__": - main() diff --git a/src/yahoo_finance_scraper.py b/src/yahoo_finance_scraper.py deleted file mode 100644 index f640837..0000000 --- a/src/yahoo_finance_scraper.py +++ /dev/null @@ -1,201 +0,0 @@ -import os -import re -import requests -from typing import List, Dict, Any - -from dotenv import load_dotenv - -try: - from youtube_transcript_api import ( - YouTubeTranscriptApi, - TranscriptsDisabled, - NoTranscriptFound, - CouldNotRetrieveTranscript, - ) -except Exception: - YouTubeTranscriptApi = None # type: ignore - TranscriptsDisabled = Exception # type: ignore - NoTranscriptFound = Exception # type: ignore - CouldNotRetrieveTranscript = Exception # type: ignore - - -YAHOO_FINANCE_CHANNEL_ID = "UCEAZeUIeJs0IjQiqTCdVSIg" - - -def list_channel_videos_via_rss(channel_id: str, max_results: int = 20) -> List[Dict[str, str]]: - try: - feed_url = f"https://www.youtube.com/feeds/videos.xml?channel_id={channel_id}" - resp = requests.get(feed_url, timeout=10) - if resp.status_code != 200: - return [] - import xml.etree.ElementTree as ET - root = ET.fromstring(resp.text) - ns = { - 'atom': 'http://www.w3.org/2005/Atom', - 'yt': 'http://www.youtube.com/xml/schemas/2015', - 'media': 'http://search.yahoo.com/mrss/' - } - videos: List[Dict[str, str]] = [] - for entry in root.findall('atom:entry', ns)[:max_results]: - vid_el = entry.find('yt:videoId', ns) - title_el = entry.find('atom:title', ns) - # media:group/media:description may hold a lightweight description - desc_el = entry.find('media:group/media:description', ns) - if vid_el is not None and title_el is not None: - videos.append({ - 'video_id': vid_el.text, - 'title': title_el.text, - 'description': (desc_el.text if desc_el is not None else '') - }) - return videos - except Exception: - return [] - - -def clean_text(text: str) -> str: - if not text: - return "" - cleaned = text.lower() - cleaned = re.sub(r"\[.*?\]", "", cleaned) - cleaned = re.sub(r"\(.*?\)", "", cleaned) - cleaned = re.sub(r"\d+:\d+", "", cleaned) - cleaned = re.sub(r"[^\w\s]", " ", cleaned) - cleaned = re.sub(r"\s+", " ", cleaned).strip() - return cleaned - - -def fetch_transcript_best_effort(video_id: str) -> Dict[str, Any]: - if YouTubeTranscriptApi is None: - return {} - - def _fetch_text(t) -> str: - items = t.fetch() - return " ".join([it.get("text", "") if isinstance(it, dict) else getattr(it, "text", "") for it in items]) - - try: - transcripts = YouTubeTranscriptApi.list_transcripts(video_id) - # 1) Manual EN - try: - t = transcripts.find_manually_created_transcript(["en", "en-US", "en-GB"]) - text = _fetch_text(t) - if len(text) > 50: - return {"method": "manual_en", "text": text} - except (NoTranscriptFound,): - pass - # 2) Auto EN - try: - t = transcripts.find_generated_transcript(["en", "en-US", "en-GB"]) - text = _fetch_text(t) - if len(text) > 50: - return {"method": "auto_en", "text": text} - except (NoTranscriptFound,): - pass - # 3) Translate others to EN - try: - langs = [tr.language_code for tr in transcripts] - except Exception: - langs = [] - for pref in ("manual_other_to_en", "auto_other_to_en"): - try: - tr = transcripts.find_manually_created_transcript(langs) if pref.startswith("manual") else transcripts.find_generated_transcript(langs) - tr_en = tr.translate('en') - text = _fetch_text(tr_en) - if len(text) > 50: - return {"method": pref, "text": text} - except (NoTranscriptFound, CouldNotRetrieveTranscript): - continue - # 4) Any available - for tr in transcripts: - try: - text = _fetch_text(tr) - if len(text) > 50: - return {"method": "any_available", "text": text} - except Exception: - continue - return {} - except TranscriptsDisabled: - return {} - except Exception: - return {} - - -def scrape_yahoo_finance_transcripts(videos_per_channel: int = 20, verbose: bool = True) -> List[Dict[str, Any]]: - """Fetch Yahoo Finance videos via RSS, pull transcripts, clean and build documents. - - Returns empty list if no transcripts are available or dependency is missing. - """ - load_dotenv(dotenv_path=os.path.join(os.path.dirname(__file__), '..', '.env')) - - videos = list_channel_videos_via_rss(YAHOO_FINANCE_CHANNEL_ID, max_results=videos_per_channel) - if verbose: - print(f"Yahoo Finance RSS videos fetched: {len(videos)}") - documents: List[Dict[str, Any]] = [] - for v in videos: - vid = v.get('video_id', '') - title = v.get('title', '') - description = v.get('description', '') - data = fetch_transcript_best_effort(vid) - if not data or not data.get('text'): - # Fallback: store title + description so we still add lightweight context - if verbose: - print(f" - No transcript for video {vid} ({title[:60]}...) - saving fallback") - fallback_text = clean_text(description) if description else '' - page = f"Video title: {title}\n\nDescription: {fallback_text}" if fallback_text else f"Video title: {title}" - documents.append({ - "page_content": page, - "metadata": { - "source": "YahooFinance", - "channel_id": YAHOO_FINANCE_CHANNEL_ID, - "title": title, - "url": f"https://www.youtube.com/watch?v={vid}", - "text": page, - "raw_text": description, - "cleaned_text": fallback_text, - "transcript_method": "fallback_description" - } - }) - continue - raw_text = data['text'] - cleaned = clean_text(raw_text) - if len(cleaned) < 20: - # Use description if transcript is too short - if verbose: - print(f" - Transcript too short for {vid} ({len(cleaned)} chars) - saving description fallback") - fallback_text = clean_text(description) if description else '' - page = f"Video title: {title}\n\nDescription: {fallback_text}" if fallback_text else f"Video title: {title}" - documents.append({ - "page_content": page, - "metadata": { - "source": "YahooFinance", - "channel_id": YAHOO_FINANCE_CHANNEL_ID, - "title": title, - "url": f"https://www.youtube.com/watch?v={vid}", - "text": page, - "raw_text": description, - "cleaned_text": fallback_text, - "transcript_method": "fallback_description" - } - }) - continue - content = f"Video title: {title}\n\nCleaned transcript: {cleaned}" - documents.append({ - "page_content": content, - "metadata": { - "source": "YahooFinance", - "channel_id": YAHOO_FINANCE_CHANNEL_ID, - "title": title, - "url": f"https://www.youtube.com/watch?v={vid}", - "text": content, - "raw_text": raw_text, - "cleaned_text": cleaned, - "transcript_method": data.get('method', '') - } - }) - return documents - - -if __name__ == "__main__": - docs = scrape_yahoo_finance_transcripts(videos_per_channel=20) - print(f"Collected {len(docs)} Yahoo Finance documents") - - diff --git a/src/yfinance_client.py b/src/yfinance_client.py deleted file mode 100644 index 5aaf032..0000000 --- a/src/yfinance_client.py +++ /dev/null @@ -1,491 +0,0 @@ -import yfinance as yf -import logging -from typing import Dict, Any, List, Optional -from datetime import datetime, timedelta -import pandas as pd -import os -import json -import time -from googleapiclient.discovery import build -from googleapiclient.errors import HttpError - -logger = logging.getLogger(__name__) - -class YFinanceClient: - """Yahoo Finance client for real options chain data""" - - def __init__(self): - self.session = None - - def get_stock_info(self, symbol: str) -> Dict[str, Any]: - """Get basic stock information""" - try: - ticker = yf.Ticker(symbol) - info = ticker.info - - return { - 'symbol': symbol, - 'current_price': info.get('currentPrice', info.get('regularMarketPrice', 0)), - 'bid': info.get('bid', 0), - 'ask': info.get('ask', 0), - 'volume': info.get('volume', 0), - 'market_cap': info.get('marketCap', 0), - 'sector': info.get('sector', 'Unknown'), - 'industry': info.get('industry', 'Unknown') - } - except Exception as e: - logger.error(f"Error getting stock info for {symbol}: {e}") - return {} - - def get_options_expirations(self, symbol: str) -> List[str]: - """Get available options expiration dates""" - try: - ticker = yf.Ticker(symbol) - expirations = ticker.options - - if not expirations: - logger.warning(f"No options expirations found for {symbol}") - return [] - - # Convert to string format and sort - exp_dates = [str(exp) for exp in expirations] - exp_dates.sort() - - logger.info(f"Found {len(exp_dates)} expiration dates for {symbol}") - return exp_dates - - except Exception as e: - logger.error(f"Error getting options expirations for {symbol}: {e}") - return [] - - def get_options_chain(self, symbol: str, expiration_date: str = None) -> Dict[str, Any]: - """Get options chain for a symbol""" - try: - ticker = yf.Ticker(symbol) - - # Get available expirations if not provided - if not expiration_date: - expirations = ticker.options - if not expirations: - logger.warning(f"No options available for {symbol}") - return {} - # Use the nearest expiration - expiration_date = str(expirations[0]) - - # Get options chain - options_chain = ticker.option_chain(expiration_date) - - if options_chain is None: - logger.warning(f"No options chain found for {symbol} on {expiration_date}") - return {} - - calls = options_chain.calls - puts = options_chain.puts - - # Process calls - calls_data = [] - if not calls.empty: - for _, row in calls.iterrows(): - calls_data.append({ - 'strike': float(row['strike']), - 'bid': float(row['bid']) if pd.notna(row['bid']) else 0, - 'ask': float(row['ask']) if pd.notna(row['ask']) else 0, - 'last_price': float(row['lastPrice']) if pd.notna(row['lastPrice']) else 0, - 'volume': int(row['volume']) if pd.notna(row['volume']) else 0, - 'open_interest': int(row['openInterest']) if pd.notna(row['openInterest']) else 0, - 'implied_volatility': float(row['impliedVolatility']) if pd.notna(row['impliedVolatility']) else 0 - }) - - # Process puts - puts_data = [] - if not puts.empty: - for _, row in puts.iterrows(): - puts_data.append({ - 'strike': float(row['strike']), - 'bid': float(row['bid']) if pd.notna(row['bid']) else 0, - 'ask': float(row['ask']) if pd.notna(row['ask']) else 0, - 'last_price': float(row['lastPrice']) if pd.notna(row['lastPrice']) else 0, - 'volume': int(row['volume']) if pd.notna(row['volume']) else 0, - 'open_interest': int(row['openInterest']) if pd.notna(row['openInterest']) else 0, - 'implied_volatility': float(row['impliedVolatility']) if pd.notna(row['impliedVolatility']) else 0 - }) - - return { - 'symbol': symbol, - 'expiration_date': expiration_date, - 'calls': calls_data, - 'puts': puts_data, - 'total_calls': len(calls_data), - 'total_puts': len(puts_data) - } - - except Exception as e: - logger.error(f"Error getting options chain for {symbol}: {e}") - return {} - - def get_liquid_strikes(self, symbol: str, expiration_date: str = None, option_type: str = 'both', min_volume: int = 10) -> List[float]: - """Get liquid strike prices based on volume and open interest""" - try: - options_chain = self.get_options_chain(symbol, expiration_date) - if not options_chain: - return [] - - liquid_strikes = [] - - if option_type in ['call', 'both']: - for call in options_chain.get('calls', []): - if call['volume'] >= min_volume or call['open_interest'] >= min_volume: - liquid_strikes.append(call['strike']) - - if option_type in ['put', 'both']: - for put in options_chain.get('puts', []): - if put['volume'] >= min_volume or put['open_interest'] >= min_volume: - liquid_strikes.append(put['strike']) - - # Remove duplicates and sort - liquid_strikes = sorted(list(set(liquid_strikes))) - logger.info(f"Found {len(liquid_strikes)} liquid strikes for {symbol}") - - return liquid_strikes - - except Exception as e: - logger.error(f"Error getting liquid strikes for {symbol}: {e}") - return [] - - def get_atm_strikes(self, symbol: str, expiration_date: str = None, count: int = 5) -> List[float]: - """Get at-the-money and near-the-money strikes""" - try: - # Get current stock price - stock_info = self.get_stock_info(symbol) - current_price = stock_info.get('current_price', 0) - - if current_price == 0: - logger.warning(f"Could not get current price for {symbol}") - return [] - - # Get options chain - options_chain = self.get_options_chain(symbol, expiration_date) - if not options_chain: - return [] - - all_strikes = [] - - # Collect all strikes - for call in options_chain.get('calls', []): - all_strikes.append(call['strike']) - for put in options_chain.get('puts', []): - all_strikes.append(put['strike']) - - if not all_strikes: - return [] - - # Remove duplicates and sort - all_strikes = sorted(list(set(all_strikes))) - - # Find strikes around current price - atm_strikes = [] - for strike in all_strikes: - if abs(strike - current_price) / current_price <= 0.1: # Within 10% of current price - atm_strikes.append(strike) - - # Sort by distance from current price - atm_strikes.sort(key=lambda x: abs(x - current_price)) - - # Return top N strikes - return atm_strikes[:count] - - except Exception as e: - logger.error(f"Error getting ATM strikes for {symbol}: {e}") - return [] - - def get_volatility_data(self, symbol: str) -> Dict[str, float]: - """Get volatility data for a symbol""" - try: - ticker = yf.Ticker(symbol) - info = ticker.info - - return { - 'implied_volatility': info.get('impliedVolatility', 0), - 'beta': info.get('beta', 0), - '52_week_high': info.get('fiftyTwoWeekHigh', 0), - '52_week_low': info.get('fiftyTwoWeekLow', 0), - 'average_volume': info.get('averageVolume', 0) - } - - except Exception as e: - logger.error(f"Error getting volatility data for {symbol}: {e}") - return {} - -# Initialize global client -yfinance_client = YFinanceClient() - -# YouTube API Configuration -YOUTUBE_API_KEY = "AIzaSyD1hA6jbyKxj6x3m96FM87Dci_MBttsHBY" - -# Financial keywords for channel search -FINANCIAL_KEYWORDS = [ - "finance", "investing", "stock market", "trading", "economics", - "business", "money", "investment", "stocks", "crypto", "bitcoin", - "financial advice", "wealth", "retirement", "portfolio", "dividend", - "options trading", "forex", "real estate investing", "personal finance", - "financial education", "market analysis", "financial news", "banking", - "insurance", "tax", "budgeting", "saving", "debt", "credit" -] - -def get_youtube_service(): - """Initialize YouTube API service""" - try: - youtube = build('youtube', 'v3', developerKey=YOUTUBE_API_KEY) - return youtube - except Exception as e: - print(f"Error initializing YouTube API: {e}") - return None - -def search_channels_by_keyword(youtube, keyword: str, max_results: int = 50) -> List[Dict[str, Any]]: - """Search for channels by keyword""" - channels = [] - - try: - # Search for channels - search_response = youtube.search().list( - part='snippet', - q=keyword, - type='channel', - maxResults=max_results, - order='relevance' - ).execute() - - channel_ids = [] - for item in search_response.get('items', []): - channel_id = item['id']['channelId'] - channel_ids.append(channel_id) - - if not channel_ids: - return channels - - # Get detailed channel information - channels_response = youtube.channels().list( - part='snippet,statistics', - id=','.join(channel_ids) - ).execute() - - for channel in channels_response.get('items', []): - stats = channel.get('statistics', {}) - snippet = channel.get('snippet', {}) - - # Parse statistics - subscriber_count = int(stats.get('subscriberCount', 0)) - view_count = int(stats.get('viewCount', 0)) - video_count = int(stats.get('videoCount', 0)) - - channel_info = { - 'channel_id': channel['id'], - 'title': snippet.get('title', ''), - 'description': snippet.get('description', ''), - 'subscriber_count': subscriber_count, - 'view_count': view_count, - 'video_count': video_count, - 'published_at': snippet.get('publishedAt', ''), - 'country': snippet.get('country', ''), - 'keywords': keyword, - 'relevance_score': 0 # Will be calculated later - } - - channels.append(channel_info) - - except HttpError as e: - print(f"HTTP Error searching for keyword '{keyword}': {e}") - except Exception as e: - print(f"Error searching for keyword '{keyword}': {e}") - - return channels - -def calculate_relevance_score(channel: Dict[str, Any]) -> float: - """Calculate relevance score based on financial content indicators""" - score = 0.0 - title = channel.get('title', '').lower() - description = channel.get('description', '').lower() - - # Financial keywords in title (higher weight) - financial_title_keywords = [ - 'finance', 'investing', 'trading', 'stocks', 'market', 'money', - 'business', 'economics', 'wealth', 'investment', 'crypto', 'bitcoin' - ] - - for keyword in financial_title_keywords: - if keyword in title: - score += 3.0 - - # Financial keywords in description - financial_desc_keywords = [ - 'financial', 'investment', 'trading', 'stocks', 'market analysis', - 'personal finance', 'wealth building', 'portfolio', 'dividend', - 'options', 'forex', 'real estate', 'retirement planning' - ] - - for keyword in financial_desc_keywords: - if keyword in description: - score += 1.0 - - # Penalty for non-financial content - non_financial_keywords = ['gaming', 'music', 'entertainment', 'comedy', 'vlog'] - for keyword in non_financial_keywords: - if keyword in title or keyword in description: - score -= 2.0 - - return max(0, score) - -def fetch_financial_channels(min_channels: int = 50) -> List[Dict[str, Any]]: - """Fetch financial channels with detailed information""" - print(f"🔍 Fetching financial YouTube channels (target: {min_channels})...") - - youtube = get_youtube_service() - if not youtube: - print("❌ Failed to initialize YouTube API") - return [] - - all_channels = [] - processed_keywords = set() - - # Search for channels using different financial keywords - for keyword in FINANCIAL_KEYWORDS: - if len(all_channels) >= min_channels * 2: # Get more than needed for filtering - break - - if keyword in processed_keywords: - continue - - print(f"📊 Searching for keyword: '{keyword}'...") - channels = search_channels_by_keyword(youtube, keyword, max_results=50) - - for channel in channels: - # Calculate relevance score - channel['relevance_score'] = calculate_relevance_score(channel) - - # Only include channels with some financial relevance - if channel['relevance_score'] > 0: - all_channels.append(channel) - - processed_keywords.add(keyword) - - # Rate limiting - YouTube API has quotas - time.sleep(0.1) - - # Remove duplicates based on channel_id - unique_channels = {} - for channel in all_channels: - channel_id = channel['channel_id'] - if channel_id not in unique_channels: - unique_channels[channel_id] = channel - else: - # Keep the one with higher relevance score - if channel['relevance_score'] > unique_channels[channel_id]['relevance_score']: - unique_channels[channel_id] = channel - - # Convert back to list - unique_channels_list = list(unique_channels.values()) - - # Sort by relevance score, then by subscriber count, then by view count - unique_channels_list.sort( - key=lambda x: (x['relevance_score'], x['subscriber_count'], x['view_count']), - reverse=True - ) - - # Take top channels - top_channels = unique_channels_list[:min_channels] - - print(f"✅ Found {len(unique_channels_list)} unique financial channels") - print(f"📈 Selected top {len(top_channels)} channels by relevance and popularity") - - return top_channels - -def save_channels_to_markdown(channels: List[Dict[str, Any]], filename: str = "Youtube_channel_ID.md"): - """Save channels to markdown file""" - try: - # Get the directory of the current file - current_dir = os.path.dirname(os.path.abspath(__file__)) - file_path = os.path.join(current_dir, 'tools', filename) - - with open(file_path, 'w', encoding='utf-8') as f: - f.write("# Financial YouTube Channels\n\n") - f.write("Auto-generated list of financial YouTube channels sorted by relevance score, subscriber count, and view count.\n\n") - f.write(f"**Generated on:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n") - f.write(f"**Total Channels:** {len(channels)}\n\n") - - # Statistics - total_subscribers = sum(ch['subscriber_count'] for ch in channels) - total_views = sum(ch['view_count'] for ch in channels) - avg_relevance = sum(ch['relevance_score'] for ch in channels) / len(channels) - - f.write("## Statistics\n\n") - f.write(f"- **Total Subscribers:** {total_subscribers:,}\n") - f.write(f"- **Total Views:** {total_views:,}\n") - f.write(f"- **Average Relevance Score:** {avg_relevance:.2f}\n\n") - - f.write("## Channel List\n\n") - f.write("| # | Channel ID | Title | Subscribers | Views | Relevance |\n") - f.write("|---|------------|-------|-------------|-------|----------|\n") - - for i, channel in enumerate(channels, 1): - channel_id = channel['channel_id'] - title = channel['title'] - subscribers = channel['subscriber_count'] - views = channel['view_count'] - relevance = channel['relevance_score'] - - f.write(f"| {i} | `{channel_id}` | {title} | {subscribers:,} | {views:,} | {relevance:.1f} |\n") - - f.write("\n## Raw Channel IDs\n\n") - f.write("Copy these IDs for use in YouTube scraper:\n\n") - - for channel in channels: - channel_id = channel['channel_id'] - title = channel['title'] - f.write(f"`{channel_id}` \n") - - print(f"💾 Saved {len(channels)} channels to {file_path}") - return file_path - - except Exception as e: - print(f"❌ Error saving channels to markdown: {e}") - return None - -def update_youtube_channel_ids(): - """Main function to fetch and save YouTube channel IDs""" - print("🚀 YouTube Financial Channels Fetcher") - print("=" * 50) - - # Fetch financial channels - channels = fetch_financial_channels(min_channels=50) - - if not channels: - print("❌ No channels found") - return None - - # Print summary - print(f"\n🏆 Top 10 Financial Channels:") - print("=" * 80) - - for i, channel in enumerate(channels[:10], 1): - title = channel['title'] - channel_id = channel['channel_id'] - subscribers = channel['subscriber_count'] - views = channel['view_count'] - relevance = channel['relevance_score'] - - print(f"{i:2d}. {title}") - print(f" ID: {channel_id}") - print(f" Subscribers: {subscribers:,}") - print(f" Total Views: {views:,}") - print(f" Relevance Score: {relevance:.1f}") - print() - - # Save to markdown file - file_path = save_channels_to_markdown(channels, "Youtube_channel_ID.md") - - if file_path: - print(f"✅ Successfully created YouTube channel ID file: {file_path}") - return file_path - else: - print("❌ Failed to create YouTube channel ID file") - return None diff --git a/src/youtube_scraper.py b/src/youtube_scraper.py deleted file mode 100644 index 3ab0523..0000000 --- a/src/youtube_scraper.py +++ /dev/null @@ -1,734 +0,0 @@ -# youtube_scraper.py -import os -import re -import string -from dotenv import load_dotenv -from typing import List, Dict, Any -from collections import Counter -import logging -import requests - -# Delayed import to avoid environment issues -try: - from googleapiclient.discovery import build - from youtube_transcript_api import ( - YouTubeTranscriptApi, - TranscriptsDisabled, - NoTranscriptFound, - NoTranscriptAvailable, - CouldNotRetrieveTranscript, - TooManyRequests, - ) - YOUTUBE_APIS_AVAILABLE = True -except ImportError as e: - print(f"Warning: YouTube APIs not available: {e}") - YOUTUBE_APIS_AVAILABLE = False - build = None - YouTubeTranscriptApi = None - TranscriptsDisabled = Exception - NoTranscriptFound = Exception - NoTranscriptAvailable = Exception - CouldNotRetrieveTranscript = Exception - TooManyRequests = Exception - -# Setup logging -logging.basicConfig(level=logging.INFO) -logger = logging.getLogger(__name__) - -load_dotenv(dotenv_path=os.path.join(os.path.dirname(__file__), '..', '.env')) - -YOUTUBE_API_KEY = os.getenv("YOUTUBE_API_KEY") - -# Financial keywords tracking -FINANCIAL_KEYWORDS = [ - # Macroeconomics - "inflation", "deflation", "recession", "recovery", "growth", "gdp", "unemployment", - "interest rates", "fed", "federal reserve", "monetary policy", "fiscal policy", - - # Market indicators - "vix", "volatility", "spy", "qqq", "dow", "nasdaq", "s&p 500", "market cap", - "pe ratio", "earnings", "revenue", "profit", "loss", "dividend", - - # Investment strategies - "options", "calls", "puts", "strike", "expiration", "premium", "delta", "gamma", - "stocks", "bonds", "etf", "mutual fund", "portfolio", "diversification", - - # Market sentiment - "bullish", "bearish", "neutral", "optimistic", "pessimistic", "fear", "greed", - "market sentiment", "investor confidence", "risk appetite", - - # Industry terms - "earnings beat", "earnings miss", "guidance", "upgrade", "downgrade", - "buy", "sell", "hold", "strong buy", "strong sell", "outperform", "underperform" -] - -# Data cleaning patterns -CLEANING_PATTERNS = [ - (r'\[.*?\]', ''), # remove content in square brackets - (r'\(.*?\)', ''), # remove content in parentheses - (r'\d+:\d+', ''), # remove timestamps - (r'[^\w\s]', ' '), # remove punctuation - (r'\s+', ' '), # collapse multiple spaces -] - -def get_channel_videos_via_rss(channel_id: str, max_results: int = 10) -> List[Dict[str, str]]: - """Fallback: fetch recent videos via YouTube RSS feed (no API key needed).""" - try: - feed_url = f"https://www.youtube.com/feeds/videos.xml?channel_id={channel_id}" - resp = requests.get(feed_url, timeout=10) - if resp.status_code != 200: - return [] - import xml.etree.ElementTree as ET - root = ET.fromstring(resp.text) - ns = { - 'atom': 'http://www.w3.org/2005/Atom', - 'yt': 'http://www.youtube.com/xml/schemas/2015' - } - items: List[Dict[str, str]] = [] - for entry in root.findall('atom:entry', ns)[:max_results]: - vid_el = entry.find('yt:videoId', ns) - title_el = entry.find('atom:title', ns) - if vid_el is not None and title_el is not None: - items.append({'video_id': vid_el.text, 'title': title_el.text}) - return items - except Exception: - return [] - - -def get_channel_videos(channel_id: str, max_results: int = 10) -> List[Dict[str, str]]: - if not YOUTUBE_APIS_AVAILABLE or not YOUTUBE_API_KEY: - # Fallback: try RSS feed to list videos without Data API - videos = get_channel_videos_via_rss(channel_id, max_results=max_results) - if videos: - print(f"Info: Using RSS feed for channel {channel_id} ({len(videos)} videos)") - return videos - # If RSS also fails, keep previous warnings - if not YOUTUBE_APIS_AVAILABLE: - print("Warning: YouTube APIs not available, skipping YouTube data scraping.") - if not YOUTUBE_API_KEY: - print("Warning: YOUTUBE_API_KEY not set, skipping YouTube data scraping.") - return [] - - try: - # Disable discovery cache to avoid warnings - youtube = build('youtube', 'v3', developerKey=YOUTUBE_API_KEY, cache_discovery=False) - except Exception as e: - print(f"Error initializing YouTube API: {e}") - return [] - - try: - # Check that the channel exists - request = youtube.channels().list(part="contentDetails", id=channel_id) - response = request.execute() - - # Ensure response contains items - if 'items' not in response or not response['items']: - print(f"Warning: Channel {channel_id} not found or has no content") - return [] - - playlist_id = response['items'][0]['contentDetails']['relatedPlaylists']['uploads'] - - # Fetch videos from the uploads playlist - request = youtube.playlistItems().list(part="snippet,contentDetails", playlistId=playlist_id, maxResults=max_results) - response = request.execute() - - # Ensure response contains items - if 'items' not in response: - print(f"Warning: No videos found in playlist for channel {channel_id}") - return [] - - return [ - { - 'video_id': item['contentDetails']['videoId'], - 'title': item['snippet'].get('title', ''), - 'description': item['snippet'].get('description', '') - } - for item in response.get('items', []) - ] - - except Exception as e: - print(f"Error getting videos for channel {channel_id}: {e}") - # Provide more details for API quota errors - if "quotaExceeded" in str(e): - print("YouTube API quota exceeded. Please try again later or check your API usage.") - elif "forbidden" in str(e).lower(): - print(f"Access forbidden for channel {channel_id}. Channel may be private or restricted.") - return [] - - -def filter_videos_with_captions(api_key: str, videos: List[Dict[str, str]]) -> List[Dict[str, str]]: - """Use YouTube Data API v3 to keep only videos that declare captions available. - This improves transcript hit rate but is not perfect. - """ - if build is None or not videos or not api_key: - return videos - try: - youtube = build('youtube', 'v3', developerKey=api_key, cache_discovery=False) - filtered: List[Dict[str, str]] = [] - for i in range(0, len(videos), 50): - batch = videos[i:i+50] - ids = ",".join(v['video_id'] for v in batch) - resp = youtube.videos().list(part="contentDetails,snippet", id=ids).execute() - details = {it['id']: it for it in resp.get('items', [])} - for v in batch: - it = details.get(v['video_id']) - if not it: - continue - caption_flag = (it.get('contentDetails', {}).get('caption') == 'true') - is_live = it.get('snippet', {}).get('liveBroadcastContent') in ('live', 'upcoming') - if caption_flag and not is_live: - filtered.append(v) - return filtered or videos - except Exception: - return videos - - -def video_has_transcript(video_id: str) -> bool: - """Quick check if any transcript is available via list_transcripts.""" - if YouTubeTranscriptApi is None: - return False - try: - transcripts = YouTubeTranscriptApi.list_transcripts(video_id) - for _ in transcripts: - return True - return False - except Exception: - return False - -def clean_transcript_text(text: str) -> str: - """ - Clean transcript text: remove timestamps, punctuation issues, and common ASR artifacts - """ - if not text: - return "" - - # Apply cleaning patterns - cleaned_text = text.lower() - for pattern, replacement in CLEANING_PATTERNS: - cleaned_text = re.sub(pattern, replacement, cleaned_text) - - # Remove common auto-generated subtitle artifacts - common_errors = [ - r'\b(um|uh|ah|er|mm|hmm)\b', # filler words - r'\b(you know|like|so|well|right)\b', # colloquialisms - r'\b(transcriber|speaker|narrator)\b', # transcriber tag - r'\b\[.*?\]\b', # square bracket content - r'\b\(.*?\)\b', # parenthesis content - ] - - for error_pattern in common_errors: - cleaned_text = re.sub(error_pattern, '', cleaned_text) - - # Final cleanup - cleaned_text = re.sub(r'\s+', ' ', cleaned_text).strip() - - return cleaned_text - -def extract_financial_keywords(text: str) -> Dict[str, int]: - """ - keywords - """ - if not text: - return {} - - text_lower = text.lower() - keyword_counts = {} - - for keyword in FINANCIAL_KEYWORDS: - # Count keywords Frequency - count = len(re.findall(r'\b' + re.escape(keyword.lower()) + r'\b', text_lower)) - if count > 0: - keyword_counts[keyword] = count - - return keyword_counts - -def analyze_transcript_sentiment(text: str) -> Dict[str, Any]: - """ - Analyze market sentiment of the transcript - """ - if not text: - return {"sentiment": "neutral", "confidence": 0.0} - - text_lower = text.lower() - - # Bullish keywords - bullish_keywords = ["bullish", "optimistic", "growth", "recovery", "strong", "beat", "upgrade", "buy"] - # Bearish keywords - bearish_keywords = ["bearish", "pessimistic", "decline", "weak", "miss", "downgrade", "sell", "crash"] - - bullish_count = sum(1 for keyword in bullish_keywords if keyword in text_lower) - bearish_count = sum(1 for keyword in bearish_keywords if keyword in text_lower) - - total_sentiment_words = bullish_count + bearish_count - - if total_sentiment_words == 0: - return {"sentiment": "neutral", "confidence": 0.0} - - bullish_ratio = bullish_count / total_sentiment_words - - if bullish_ratio > 0.6: - sentiment = "bullish" - elif bullish_ratio < 0.4: - sentiment = "bearish" - else: - sentiment = "neutral" - - confidence = abs(bullish_ratio - 0.5) * 2 # confidence in [0,1] - - return { - "sentiment": sentiment, - "confidence": confidence, - "bullish_score": bullish_count, - "bearish_score": bearish_count - } - -def get_transcript_with_fallback(video_id: str) -> Dict[str, Any]: - """ - Get transcript prioritizing list_transcripts with language selection, translation, and backoff - """ - if not YOUTUBE_APIS_AVAILABLE: - print(f" ❌ YouTube APIs not available for video {video_id}") - return None - - def _fetch_text_from_transcript(transcript_obj) -> str: - try: - items = transcript_obj.fetch() - return " ".join([it["text"] if isinstance(it, dict) else getattr(it, "text", "") for it in items]) - except TooManyRequests: - - import time - for delay in (1, 2, 4): - time.sleep(delay) - try: - items = transcript_obj.fetch() - return " ".join([it["text"] if isinstance(it, dict) else getattr(it, "text", "") for it in items]) - except TooManyRequests: - continue - raise - - try: - transcripts = YouTubeTranscriptApi.list_transcripts(video_id) - - - try: - t = transcripts.find_manually_created_transcript(["en", "en-US", "en-GB"]) - raw_text = _fetch_text_from_transcript(t) - if raw_text and len(raw_text) > 50: - return process_transcript_data(raw_text, video_id, "manual_en") - except (NoTranscriptFound, NoTranscriptAvailable): - pass - - - try: - t = transcripts.find_generated_transcript(["en", "en-US", "en-GB"]) - raw_text = _fetch_text_from_transcript(t) - if raw_text and len(raw_text) > 50: - return process_transcript_data(raw_text, video_id, "auto_en") - except (NoTranscriptFound, NoTranscriptAvailable): - pass - - - try: - available_languages = [tr.language_code for tr in transcripts] - except Exception: - available_languages = [] - - for pref in ("manual_other_to_en", "auto_other_to_en"): - try: - if pref.startswith("manual"): - tr = transcripts.find_manually_created_transcript(available_languages) - else: - tr = transcripts.find_generated_transcript(available_languages) - tr_en = tr.translate("en") - raw_text = _fetch_text_from_transcript(tr_en) - if raw_text and len(raw_text) > 50: - return process_transcript_data(raw_text, video_id, pref) - except (NoTranscriptFound, NoTranscriptAvailable, CouldNotRetrieveTranscript) as e: - - print(f" ⚠️ {pref} failed for {video_id}: {e}") - continue - - - try: - for tr in transcripts: - try: - raw_text = _fetch_text_from_transcript(tr) - if raw_text and len(raw_text) > 50: - return process_transcript_data(raw_text, video_id, "any_available") - except Exception: - continue - except Exception: - pass - - print(f" ❌ No usable transcripts for video {video_id}") - return None - - except TranscriptsDisabled: - print(f" ❌ Transcripts disabled for video {video_id}") - return None - except TooManyRequests: - print(f" ⚠️ Rate limited when listing transcripts for {video_id}; retrying with backoff") - import time - for delay in (1, 2, 4): - time.sleep(delay) - try: - return get_transcript_with_fallback(video_id) - except TooManyRequests: - continue - print(f" ❌ Rate limit persists for {video_id}") - return None - except (NoTranscriptFound, NoTranscriptAvailable) as e: - print(f" ❌ No transcript available for video {video_id}: {e}") - return None - except CouldNotRetrieveTranscript as e: - print(f" ⚠️ Could not retrieve transcript for {video_id}: {e}; trying alternatives...") - return try_alternative_transcript_methods(video_id) - except Exception as e: - error_msg = str(e) - if "blocked" in error_msg.lower() or "ip" in error_msg.lower(): - print(f" ⚠️ IP blockage suspected for {video_id}, trying alternative methods...") - return try_alternative_transcript_methods(video_id) - elif "not found" in error_msg.lower(): - print(f" ❌ Video not found: {video_id}") - return None - elif "quota" in error_msg.lower(): - print(f" ❌ API quota exceeded for video {video_id}") - return None - else: - print(f" ❌ Error getting transcript for video {video_id}: {error_msg}") - return None - - -def try_alternative_transcript_methods(video_id: str) -> Dict[str, Any]: - """ - Try alternative transcript methods (language enumeration, translation, backoff) - """ - languages_to_try = ['en', 'en-US', 'en-GB', 'hi', 'es', 'de', 'fr', 'ja', 'ko', 'zh-Hans', 'zh-Hant'] - - - for lang in languages_to_try: - try: - lst = YouTubeTranscriptApi.get_transcript(video_id, languages=[lang]) - raw_text = " ".join([it["text"] if isinstance(it, dict) else getattr(it, "text", "") for it in lst]) - if raw_text and len(raw_text) > 50: - print(f" ✅ Got transcript using language={lang} for video {video_id}") - method = f"direct_{lang}" - if lang.startswith('en'): - return process_transcript_data(raw_text, video_id, method) - - try: - transcripts = YouTubeTranscriptApi.list_transcripts(video_id) - tr = transcripts.find_manually_created_transcript([lang]) if lang else None - if not tr: - tr = transcripts.find_generated_transcript([lang]) - tr_en = tr.translate('en') - text_en = " ".join([it["text"] if isinstance(it, dict) else getattr(it, "text", "") for it in tr_en.fetch()]) - if text_en and len(text_en) > 50: - return process_transcript_data(text_en, video_id, f"translate_{lang}_to_en") - except Exception: - return process_transcript_data(raw_text, video_id, method) - except Exception as e: - print(f" ⚠️ language={lang} failed for {video_id}: {e}") - - - try: - import time - for delay in (1, 2, 4): - time.sleep(delay) - try: - transcripts = YouTubeTranscriptApi.list_transcripts(video_id) - for tr in transcripts: - try: - items = tr.fetch() - raw_text = " ".join([it["text"] if isinstance(it, dict) else getattr(it, "text", "") for it in items]) - if raw_text and len(raw_text) > 50: - return process_transcript_data(raw_text, video_id, f"retry_any_available_{delay}s") - except Exception: - continue - except TooManyRequests: - continue - except Exception as e: - print(f" ⚠️ Backoff retry failed for {video_id}: {e}") - - print(f" ❌ All alternative methods failed for video {video_id}") - return None - - -def process_transcript_data(raw_text: str, video_id: str, method: str) -> Dict[str, Any]: - """ - Process transcript data - """ - # Cleaning - cleaned_text = clean_transcript_text(raw_text) - - if not cleaned_text or len(cleaned_text) < 50: - print(f" ❌ Transcript too short for video {video_id} ({len(cleaned_text) if cleaned_text else 0} chars)") - return None - - keyword_counts = extract_financial_keywords(cleaned_text) - - sentiment_analysis = analyze_transcript_sentiment(cleaned_text) - - return { - "raw_text": raw_text, - "cleaned_text": cleaned_text, - "keyword_counts": keyword_counts, - "sentiment_analysis": sentiment_analysis, - "word_count": len(cleaned_text.split()), - "financial_relevance": len(keyword_counts) / len(FINANCIAL_KEYWORDS) if FINANCIAL_KEYWORDS else 0, - "transcript_method": method - } - - -def get_transcript(video_id: str) -> Dict[str, Any]: - """ - Get video transcript, clean and analyze it, with detailed error messages - """ - return get_transcript_with_fallback(video_id) - -def analyze_channel_topics(documents: List[Dict[str, Any]]) -> Dict[str, Any]: - """ - Analyze channel topics and keyword frequency - """ - if not documents: - return {} - - # 合并所有关键词计数 - all_keywords = Counter() - sentiment_scores = {"bullish": 0, "bearish": 0, "neutral": 0} - total_financial_relevance = 0 - - for doc in documents: - metadata = doc.get("metadata", {}) - if "keyword_counts" in metadata: - for keyword, count in metadata["keyword_counts"].items(): - all_keywords[keyword] += count - - if "sentiment_analysis" in metadata: - sentiment = metadata["sentiment_analysis"].get("sentiment", "neutral") - sentiment_scores[sentiment] += 1 - - if "financial_relevance" in metadata: - total_financial_relevance += metadata["financial_relevance"] - - # calculate financial_relevance - avg_financial_relevance = total_financial_relevance / len(documents) if documents else 0 - - return { - "top_keywords": dict(all_keywords.most_common(20)), - "sentiment_distribution": sentiment_scores, - "average_financial_relevance": avg_financial_relevance, - "total_videos_analyzed": len(documents) - } - -def load_channel_ids_from_file(file_path: str = None) -> List[str]: - """ - Load channel IDs from the Youtube_channel_ID file - """ - if file_path is None: - # Default file path - current_dir = os.path.dirname(os.path.abspath(__file__)) - file_path = os.path.join(current_dir, 'tools', 'Youtube_channel_ID') - - channel_ids = [] - - if os.path.exists(file_path): - try: - with open(file_path, 'r', encoding='utf-8') as f: - for line in f: - line = line.strip() - # Strip comment part - if '