Fed-AI-Savant / src /modules /fed_tools.py
RobertoBarrosoLuque
Add chat, orchestrator and tool use
001487b
raw
history blame
8.27 kB
import json
from pathlib import Path
from typing import List, Dict, Any
from datetime import datetime
# Path to the processed meetings data
DATA_DIR = Path(__file__).parents[2] / "data"
MEETINGS_FILE = DATA_DIR / "fed_processed_meetings.json"
def _load_meetings_data() -> List[Dict[str, Any]]:
"""Load processed meetings data from JSON file"""
try:
if MEETINGS_FILE.exists():
with open(MEETINGS_FILE, 'r', encoding='utf-8') as f:
data = json.load(f)
return sorted(data, key=lambda x: x.get('date', ''), reverse=True)
else:
return []
except Exception as e:
return []
def search_meetings(query: str, limit: int = 3) -> Dict[str, Any]:
"""
Search across all FOMC meeting data for relevant information.
Args:
query (str): Search term or phrase to look for in meetings
limit (int): Maximum number of meetings to return (default: 3)
Returns:
Dict containing:
- success (bool): Whether the search succeeded
- query (str): The original search query
- results (List[Dict]): List of matching meetings
- count (int): Number of results returned
- total_matches (int): Total number of meetings that matched
"""
meetings_data = _load_meetings_data()
if not meetings_data:
return {
"success": False,
"error": "No meetings data available",
"results": [],
"count": 0
}
query_lower = query.lower()
scored_meetings = []
for meeting in meetings_data:
score = 0
matched_fields = []
search_fields = {
'date': 2,
'title': 1,
'action': 3,
'rate': 3,
'magnitude': 2,
'forward_guidance': 2,
'economic_outlook': 1,
'market_impact': 1,
'key_economic_factors': 1
}
for field, weight in search_fields.items():
field_value = meeting.get(field, '')
if isinstance(field_value, list):
field_value = ' '.join(field_value)
if field_value and query_lower in str(field_value).lower():
score += weight
matched_fields.append(field)
if score > 0:
scored_meetings.append({
'meeting': meeting,
'score': score,
'matched_fields': matched_fields
})
scored_meetings.sort(key=lambda x: x['score'], reverse=True)
top_results = scored_meetings[:limit]
return {
"success": True,
"query": query,
"results": [result['meeting'] for result in top_results],
"match_details": [{'score': r['score'], 'matched_fields': r['matched_fields']} for r in top_results],
"count": len(top_results),
"total_matches": len(scored_meetings)
}
def get_rate_decision(date: str) -> Dict[str, Any]:
"""
Get details about a specific FOMC meeting's rate decision.
Args:
date (str): Meeting date in YYYY-MM-DD format (e.g., "2025-06-18")
Returns:
Dict containing:
- success (bool): Whether the meeting was found
- meeting (Dict): Complete meeting data if found
- exact_match (bool): True if exact date match, False if closest match
- requested_date (str): The date that was requested
"""
meetings_data = _load_meetings_data()
if not meetings_data:
return {
"success": False,
"error": "No meetings data available"
}
target_meeting = None
for meeting in meetings_data:
if meeting.get('date') == date:
target_meeting = meeting
break
if not target_meeting and date:
try:
target_date = datetime.strptime(date, '%Y-%m-%d')
closest_meeting = None
min_diff = float('inf')
for meeting in meetings_data:
try:
meeting_date = datetime.strptime(meeting.get('date', ''), '%Y-%m-%d')
diff = abs((meeting_date - target_date).days)
if diff < min_diff and diff <= 30:
min_diff = diff
closest_meeting = meeting
except ValueError:
continue
target_meeting = closest_meeting
except ValueError:
pass
if target_meeting:
return {
"success": True,
"requested_date": date,
"meeting": target_meeting,
"exact_match": target_meeting.get('date') == date
}
else:
return {
"success": False,
"error": f"No meeting found for date {date}",
"requested_date": date
}
def compare_meetings(date1: str, date2: str) -> Dict[str, Any]:
"""
Compare two FOMC meetings side by side to analyze differences and similarities.
Args:
date1 (str): First meeting date in YYYY-MM-DD format
date2 (str): Second meeting date in YYYY-MM-DD format
Returns:
Dict containing:
- success (bool): Whether both meetings were found
- meeting1/meeting2 (Dict): Data for each meeting
- differences (Dict): Fields that differ between meetings
- similarities (Dict): Fields that are the same
- factor_analysis (Dict): Analysis of key economic factors
"""
meeting1_result = get_rate_decision(date1)
meeting2_result = get_rate_decision(date2)
if not meeting1_result["success"]:
return {
"success": False,
"error": f"Could not find meeting for {date1}: {meeting1_result.get('error')}"
}
if not meeting2_result["success"]:
return {
"success": False,
"error": f"Could not find meeting for {date2}: {meeting2_result.get('error')}"
}
meeting1 = meeting1_result["meeting"]
meeting2 = meeting2_result["meeting"]
# Compare key fields
comparison = {
"success": True,
"meeting1": {
"date": meeting1.get('date'),
"title": meeting1.get('title'),
"data": meeting1
},
"meeting2": {
"date": meeting2.get('date'),
"title": meeting2.get('title'),
"data": meeting2
},
"differences": {},
"similarities": {}
}
# Compare specific fields
compare_fields = ['action', 'rate', 'magnitude', 'forward_guidance', 'economic_outlook', 'market_impact']
for field in compare_fields:
val1 = meeting1.get(field, '')
val2 = meeting2.get(field, '')
if val1 != val2:
comparison["differences"][field] = {
"meeting1_value": val1,
"meeting2_value": val2
}
else:
comparison["similarities"][field] = val1
# Compare key economic factors
factors1 = set(meeting1.get('key_economic_factors', []))
factors2 = set(meeting2.get('key_economic_factors', []))
comparison["factor_analysis"] = {
"common_factors": list(factors1.intersection(factors2)),
"unique_to_meeting1": list(factors1 - factors2),
"unique_to_meeting2": list(factors2 - factors1)
}
return comparison
def get_latest_meeting() -> Dict[str, Any]:
"""
Get the most recent FOMC meeting data.
Returns:
Dict containing:
- success (bool): Whether data was retrieved successfully
- meeting (Dict): The most recent meeting data
- total_meetings (int): Total number of meetings in database
"""
meetings_data = _load_meetings_data()
if not meetings_data:
return {
"success": False,
"error": "No meetings data available"
}
# Data is already sorted by date (newest first)
latest_meeting = meetings_data[0]
return {
"success": True,
"meeting": latest_meeting,
"total_meetings": len(meetings_data)
}