diff --git a/app/cron_egg_price.py b/app/cron_egg_price.py new file mode 100644 index 0000000..b45e319 --- /dev/null +++ b/app/cron_egg_price.py @@ -0,0 +1,108 @@ +import pandas as pd +import requests +from datetime import datetime +from io import StringIO +from dotenv import load_dotenv +import os +import orjson +import numpy as np + +load_dotenv() +FRED_API_KEY = os.getenv("FRED_API_KEY") + + +def numpy_float_handler(obj): + if isinstance(obj, (np.float64, np.float32, np.int64, np.int32)): + return float(obj) + elif isinstance(obj, datetime): + return obj.strftime('%Y-%m-%d') + raise TypeError(f"Type {type(obj)} not serializable") + +def save_json(data): + path = "json/tracker/potus" + os.makedirs(path, exist_ok=True) + with open(f"{path}/egg_price.json", "wb") as file: + file.write(orjson.dumps(data, default=numpy_float_handler)) + +def fetch_fred_egg_prices(): + api_key = FRED_API_KEY + series_id = 'APU0000708111' # FRED series ID for egg prices + url = f'https://api.stlouisfed.org/fred/series/observations?series_id={series_id}&api_key={api_key}&file_type=json' + + try: + response = requests.get(url) + data = response.json() + + # Convert to DataFrame + df = pd.DataFrame(data['observations']) + df['date'] = pd.to_datetime(df['date']) + df['value'] = pd.to_numeric(df['value'], errors='coerce') + + return df[['date', 'value']] + except Exception as e: + print(f"Error fetching data from FRED: {e}") + return None + +def analyze_egg_prices(df): + """ + Analyzes egg price trends and generates statistics + """ + if df is None or df.empty: + return None + + # Calculate basic statistics + stats = { + 'current_price': df['value'].iloc[-1], + 'avg_price': df['value'].mean(), + 'max_price': df['value'].max(), + 'min_price': df['value'].min(), + 'yearly_change': df['value'].iloc[-1] - df['value'].iloc[-13] if len(df) >= 13 else None + } + + # Calculate year-over-year change + df['YoY_change'] = df['value'].pct_change(periods=12) * 100 + + return stats, df + + +def safe_round(value, decimals=2): + try: + return round(float(value), decimals) + except (ValueError, TypeError): + return value + +def main(): + # Fetch data + df = fetch_fred_egg_prices() + + if df is not None: + # Analyze data + stats, df_analyzed = analyze_egg_prices(df) + + data = df_analyzed.to_dict(orient="records") + current_date = datetime.now() + + N_years_ago = current_date.replace(year=current_date.year - 5) + + filtered_data = [ + {**entry, + 'date': entry['date'].strftime('%Y-%m-%d'), + 'price': safe_round(entry['value']), # Apply safe_round to 'value' + 'yoyChange': safe_round(entry['YoY_change']) # Apply safe_round to 'YoY_change' + } + for entry in data if entry['date'] >= N_years_ago + ] + + + res_dict = { + 'currentPrice': round(stats['current_price'],2), + 'avgPrice': round(stats['avg_price'],2), + 'maxPrice': round(stats['max_price'],2), + 'minPrice': round(stats['min_price'],2), + 'history': filtered_data} + + if filtered_data: + save_json(res_dict) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/app/cron_potus_tracker.py b/app/cron_potus_tracker.py index 955fa8b..f5e4d20 100644 --- a/app/cron_potus_tracker.py +++ b/app/cron_potus_tracker.py @@ -193,7 +193,6 @@ async def get_data(): if item['date'] == price_item['date']: item['changesPercentage'] = price_item['changesPercentage'] break - print(city) res_dict = {'returnSince': return_since,'city': city, 'lon': longitude, 'lat': latitude, 'history': data, 'billData': bill_data} save_json(res_dict) diff --git a/app/main.py b/app/main.py index cc73f4b..955c5e1 100755 --- a/app/main.py +++ b/app/main.py @@ -4310,6 +4310,35 @@ async def get_data(api_key: str = Security(get_api_key)): headers={"Content-Encoding": "gzip"} ) +@app.get("/egg-price") +async def get_data(api_key: str = Security(get_api_key)): + cache_key = f"egg-price" + cached_result = redis_client.get(cache_key) + if cached_result: + return StreamingResponse( + io.BytesIO(cached_result), + media_type="application/json", + headers={"Content-Encoding": "gzip"} + ) + + try: + with open(f"json/tracker/potus/egg_price.json", 'rb') as file: + res = orjson.loads(file.read()) + except: + res = {} + + data = orjson.dumps(res) + compressed_data = gzip.compress(data) + + redis_client.set(cache_key, compressed_data) + redis_client.expire(cache_key,60*15) + + return StreamingResponse( + io.BytesIO(compressed_data), + media_type="application/json", + headers={"Content-Encoding": "gzip"} + ) + @app.get("/newsletter") async def get_newsletter():