A quantitative analysis system that tracks ESG-related news sentiment and analyzes its impact on short-term stock returns.
ESG Pulse is an automated agent that:
- Tracks ESG news for user-defined stock portfolios
- Analyzes sentiment using FinBERT (financial sentiment analysis)
- Calculates abnormal returns using market model regression
- Quantifies impact through multi-factor regression analysis
- Provides insights on ESG sentiment's effect on stock performance
Portfolio Input → News Ingestion → Sentiment Analysis → Market Data → Regression → Insights
- Frontend: Streamlit dashboard for portfolio input and results visualization
- Backend: Python scripts for data processing and analysis
- NLP: FinBERT for ESG sentiment scoring
- Analytics: Multi-factor regression (sentiment + momentum + market factors)
- Automation: n8n workflows for end-to-end orchestration
Our analysis of 118 observations shows:
- Momentum Impact: Highly significant (p = 0.001) - strong positive effect on returns
- ESG Sentiment: Not statistically significant in current sample
- Model Performance: R-squared = 9.2%, F-statistic = 5.827 (p = 0.00389)
- Python 3.8+
- Git
# Clone the repository
git clone https://github.com/yourusername/esg-sentiment-agent.git
cd esg-sentiment-agent
# Install dependencies
pip install -r requirements.txt
# Set up environment variables
cp .env.example .env
# Edit .env with your API keys- GNews API: For ESG news fetching
- Yahoo Finance: For stock price data (free)
-
Run the Streamlit Dashboard:
streamlit run dashboards/app.py
-
Input Your Portfolio:
- Enter stock tickers (e.g., AAPL, MSFT, TSLA)
- Click "Save Portfolio"
-
Run Analysis:
# Fetch ESG news python src/ingestion.py # Score sentiment python models/sentiment_model.py # Generate market features python src/ingestion.py # (switch to market features mode) # Run regression analysis python models/regression_model.py
esg-sentiment-agent/
├── dashboards/ # Streamlit dashboard
├── data/ # CSV files (portfolio, news, features)
├── models/ # ML models (sentiment, regression)
├── src/ # Core processing scripts
├── n8n/ # Automation workflows
├── notebooks/ # Jupyter notebooks for analysis
└── requirements.txt # Python dependencies
GNEWS_API_KEY=your_gnews_api_key- Edit
data/user_portfolio.csvor use the Streamlit interface - Supported tickers: Any stock available on Yahoo Finance
- ✅ Portfolio management
- ✅ ESG news ingestion
- ✅ Sentiment analysis (FinBERT)
- ✅ Market data collection
- ✅ Abnormal return calculation
- ✅ Multi-factor regression
- ✅ Results visualization
- 🔄 Real-time alerts
- 📊 Interactive dashboards
- 🤖 Automated scheduling
- 📱 Mobile notifications
- 🌐 Web API endpoints
- Estimation Window: T-80 to T-6 days
- Event Window: T-3 to T+3 days
- Benchmark: S&P 500 returns
- Model: OLS regression with CAPM-style market model
- Model: FinBERT (ProsusAI/finbert)
- Categories: Positive, Neutral, Negative
- Features: Sentiment score, sentiment label
abnormal_return ~ sentiment_score + momentum + vix + sector_dummies
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- FinBERT: For financial sentiment analysis
- Yahoo Finance: For market data
- GNews: For ESG news aggregation
- Streamlit: For the interactive dashboard
- Project Link: https://github.com/yourusername/esg-sentiment-agent
- Issues: https://github.com/yourusername/esg-sentiment-agent/issues
Built with ❤️ for ESG-conscious investors
import os
import pandas as pd
import streamlit as st
if os.path.exists('data/market_features.csv'):
df = pd.read_csv('data/market_features.csv')
st.header('Abnormal Returns by Sentiment Category')
df['sentiment_category'] = pd.cut(df['sentiment_score'], bins=[-float('inf'), 0.3, 0.7, float('inf')], labels=['Negative', 'Neutral', 'Positive'])
st.write(df.groupby('sentiment_category')['abnormal_return'].agg(['mean', 'std', 'count']))
st.header('Distribution of Abnormal Returns')
st.hist = st.pyplot()
df['abnormal_return'].hist(bins=30)
st.pyplot(st.hist)