|
import yfinance as yf |
|
import pandas as pd |
|
from newsapi import NewsApiClient |
|
import os |
|
from datetime import datetime, timedelta |
|
|
|
def load_api_keys(): |
|
"""Loads API keys directly from environment variables.""" |
|
news_api_key = os.getenv("NEWS_API_KEY") |
|
alpha_vantage_key = os.getenv("ALPHA_VANTAGE_KEY") |
|
if not news_api_key: |
|
print("Warning: NEWS_API_KEY environment variable not found.") |
|
return news_api_key, alpha_vantage_key |
|
|
|
def get_stock_data(ticker, start_date, end_date): |
|
""" |
|
Fetches historical stock data for a given ticker symbol. |
|
|
|
Args: |
|
ticker (str): The stock ticker symbol (e.g., 'AAPL'). |
|
start_date (str): Start date in 'YYYY-MM-DD' format. |
|
end_date (str): End date in 'YYYY-MM-DD' format. |
|
|
|
Returns: |
|
pandas.DataFrame: DataFrame containing historical stock data, or None if an error occurs. |
|
""" |
|
try: |
|
stock = yf.Ticker(ticker) |
|
hist = stock.history(start=start_date, end=end_date) |
|
if hist.empty: |
|
print(f"No data found for {ticker} between {start_date} and {end_date}.") |
|
return None |
|
hist.reset_index(inplace=True) |
|
hist['Date'] = pd.to_datetime(hist['Date']).dt.date |
|
return hist |
|
except Exception as e: |
|
print(f"Error fetching stock data for {ticker}: {e}") |
|
return None |
|
|
|
def get_news_articles(query, from_date, to_date, language='en', sort_by='relevancy', page_size=100): |
|
""" |
|
Fetches news articles related to a query within a date range using NewsAPI. |
|
|
|
Args: |
|
query (str): The search query (e.g., 'Apple stock'). |
|
from_date (str): Start date in 'YYYY-MM-DD' format. |
|
to_date (str): End date in 'YYYY-MM-DD' format. |
|
language (str): Language of the articles (default: 'en'). |
|
sort_by (str): Sorting criteria (default: 'relevancy'). Options: 'relevancy', 'popularity', 'publishedAt'. |
|
page_size (int): Number of results per page (max 100 for developer plan). |
|
|
|
Returns: |
|
list: A list of dictionaries, where each dictionary represents an article, or None if an error occurs. |
|
Returns an empty list if no articles are found. |
|
""" |
|
print(f"Attempting to fetch news with query: '{query}'") |
|
print(f"Date range: {from_date} to {to_date}") |
|
news_api_key, _ = load_api_keys() |
|
if not news_api_key: |
|
print("Error: NewsAPI key not available in environment variables. Cannot fetch news.") |
|
return None |
|
|
|
try: |
|
newsapi = NewsApiClient(api_key=news_api_key) |
|
|
|
|
|
one_month_ago = (datetime.now() - timedelta(days=29)).strftime('%Y-%m-%d') |
|
print(f"One month ago date limit (approx): {one_month_ago}") |
|
if from_date < one_month_ago: |
|
print(f"Warning: NewsAPI free tier limits searches to the past month. Adjusting from_date from {from_date} to {one_month_ago}") |
|
from_date = one_month_ago |
|
|
|
print(f"Calling NewsAPI with: q='{query}', from='{from_date}', to='{to_date}', page_size={page_size}") |
|
all_articles = newsapi.get_everything(q=query, |
|
from_param=from_date, |
|
to=to_date, |
|
language=language, |
|
sort_by=sort_by, |
|
page_size=page_size) |
|
|
|
print(f"NewsAPI response status: {all_articles.get('status')}") |
|
if all_articles['status'] == 'ok': |
|
total_results = all_articles['totalResults'] |
|
print(f"Found {total_results} articles for '{query}'") |
|
if total_results == 0: |
|
print("Warning: NewsAPI returned 0 articles for this query and date range.") |
|
return all_articles['articles'] |
|
else: |
|
error_code = all_articles.get('code') |
|
error_message = all_articles.get('message') |
|
print(f"Error fetching news from NewsAPI. Code: {error_code}, Message: {error_message}") |
|
return None |
|
except Exception as e: |
|
print(f"Exception occurred while connecting to NewsAPI: {e}") |
|
return None |
|
|
|
|
|
def get_alpha_vantage_data(symbol): |
|
"""Placeholder function to fetch data using Alpha Vantage.""" |
|
_, alpha_vantage_key = load_api_keys() |
|
if not alpha_vantage_key: |
|
print("Alpha Vantage API key not found in .env file.") |
|
return None |
|
print(f"Fetching data for {symbol} using Alpha Vantage (implementation pending)...") |
|
|
|
return None |
|
|
|
if __name__ == '__main__': |
|
|
|
ticker = 'AAPL' |
|
end_date = datetime.now().strftime('%Y-%m-%d') |
|
start_date = (datetime.now() - timedelta(days=30)).strftime('%Y-%m-%d') |
|
|
|
print(f"--- Testing Stock Data Fetching ({ticker}) ---") |
|
stock_data = get_stock_data(ticker, start_date, end_date) |
|
if stock_data is not None: |
|
print(f"Successfully fetched {len(stock_data)} rows of stock data.") |
|
print(stock_data.head()) |
|
else: |
|
print("Failed to fetch stock data.") |
|
|
|
print(f"\n--- Testing News Article Fetching ({ticker}) ---") |
|
news_query = f"{ticker} stock" |
|
articles = get_news_articles(news_query, start_date, end_date) |
|
if articles is not None: |
|
print(f"Successfully fetched {len(articles)} articles.") |
|
if articles: |
|
print("First article title:", articles[0]['title']) |
|
else: |
|
print("Failed to fetch news articles.") |
|
|
|
|
|
|