From b348055485b0570762ce6a10850de4582ff7205d Mon Sep 17 00:00:00 2001 From: Taehong Gu Date: Mon, 23 Jun 2025 21:55:08 +0900 Subject: [PATCH] Add bitcoin price predictor for external tool server --- servers/bitcoin-price-predictor/README.md | 42 ++++++ servers/bitcoin-price-predictor/main.py | 132 ++++++++++++++++++ .../bitcoin-price-predictor/requirements.txt | 5 + 3 files changed, 179 insertions(+) create mode 100644 servers/bitcoin-price-predictor/README.md create mode 100644 servers/bitcoin-price-predictor/main.py create mode 100644 servers/bitcoin-price-predictor/requirements.txt diff --git a/servers/bitcoin-price-predictor/README.md b/servers/bitcoin-price-predictor/README.md new file mode 100644 index 0000000..645897c --- /dev/null +++ b/servers/bitcoin-price-predictor/README.md @@ -0,0 +1,42 @@ +# ₿ Bitcoin Price Predictor Server + +Bitcoin price data analysis API server ⚡️ + +📦 Built with: +⚡️ FastAPI • 📊 pandas • 🐍 Python + +--- + +## 📁 Data Requirements + +This server requires `btcusd_1-min_data.csv` to function properly. + +**Download from**: https://www.kaggle.com/datasets/mczielinski/bitcoin-historical-data + +Place the CSV file in this directory before running the server. + +--- + +## 🚀 Quickstart + +```bash +git clone https://github.com/open-webui/openapi-servers +cd openapi-servers/servers/bitcoin-price-predictor + +# Download btcusd_1-min_data.csv and place it here +pip install -r requirements.txt +uvicorn main:app --host 0.0.0.0 --reload +``` + +You're live. 📈💰 + +--- + +## 🛠️ Available Tools + +- `get_price_by_date`: Get Bitcoin price averages for a specific date +- `get_stat_by_date_range`: Get price statistics for a date range +- `get_trend_by_date_range`: Get daily price trends (max 30 days) +- `get_current_date`: Get current date + +🖥️ API Docs: http://localhost:8000/docs diff --git a/servers/bitcoin-price-predictor/main.py b/servers/bitcoin-price-predictor/main.py new file mode 100644 index 0000000..12d693e --- /dev/null +++ b/servers/bitcoin-price-predictor/main.py @@ -0,0 +1,132 @@ +from fastapi import FastAPI, HTTPException +from fastapi.middleware.cors import CORSMiddleware +from pydantic import BaseModel, Field + +import pandas as pd + +from datetime import datetime + +app = FastAPI( + title="Bitcoin Price Predictor", + description="Bitcoin Price Predictor", + version="1.0.0", +) + +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + +bitcoin_price_data = pd.read_csv("btcusd_1-min_data.csv") +bitcoin_price_data["Timestamp"] = pd.to_datetime( + bitcoin_price_data["Timestamp"], unit='s') + + +class BitcoinPriceQueryForm(BaseModel): + date: str = Field( + ..., description="This is desired date time for bitcoin price and time format is YYYY-MM-DD (e.g., 2024-01-01)" + ) + + +class BitcoinPriceTrendQueryForm(BaseModel): + start_date: str = Field( + ..., description="This is desired start date time for bitcoin price trend and time format is YYYY-MM-DD (e.g., 2023-01-01)" + ) + end_date: str = Field( + ..., description="This is desired end date time for bitcoin price trend and time format is YYYY-MM-DD (e.g., 2024-01-01)" + ) + + +class BitcoinPriceStatQueryForm(BaseModel): + start_date: str = Field( + ..., description="This is desired start date time for bitcoin price state and time format is YYYY-MM-DD (e.g., 2023-01-01)" + ) + end_date: str = Field( + ..., description="This is desired end date time for bitcoin price state and time format is YYYY-MM-DD (e.g., 2024-01-01)" + ) + + +@app.post("/get_price_by_date", summary="Get Bitcoin price by date") +async def get_price_by_date(form_data: BitcoinPriceQueryForm): + print(form_data) + start_date = pd.to_datetime(form_data.date) + end_date = start_date + pd.Timedelta(days=1) + + date_query_result = bitcoin_price_data[( + bitcoin_price_data["Timestamp"] >= start_date) & (bitcoin_price_data["Timestamp"] < end_date)] + + if date_query_result.empty: + raise HTTPException( + status_code=404, detail="No data found for the specified date") + + date_query_result_mean = date_query_result.mean( + numeric_only=True) + return date_query_result_mean.to_dict() + + +@app.post("/get_stat_by_date_range", summary="Get Bitcoin price status by date range") +async def get_stat_by_date_range(form_data: BitcoinPriceStatQueryForm): + start_date = pd.to_datetime(form_data.start_date) + end_date = pd.to_datetime(form_data.end_date) + date_query_result = bitcoin_price_data[( + bitcoin_price_data["Timestamp"] >= start_date) & (bitcoin_price_data["Timestamp"] < end_date)] + + if date_query_result.empty: + raise HTTPException( + status_code=404, detail="No data found for the specified date range") + + highest_price = date_query_result["High"].max() + lowest_price = date_query_result["Low"].min() + average_price = date_query_result["Close"].mean() + + return { + "highest_price": highest_price, + "lowest_price": lowest_price, + "average_price": average_price + } + + +@app.post("/get_trend_by_date_range", summary="Get Bitcoin price status by date range") +async def get_trend_by_date_range(form_data: BitcoinPriceTrendQueryForm): + start_date = pd.to_datetime(form_data.start_date) + end_date = pd.to_datetime(form_data.end_date) + date_difference = (end_date - start_date).days + + if date_difference > 30: + raise HTTPException( + status_code=400, detail="Date range ovred 30 days") + + date_query_result = bitcoin_price_data[( + bitcoin_price_data["Timestamp"] >= start_date) & (bitcoin_price_data["Timestamp"] < end_date)] + + if date_query_result.empty: + raise HTTPException( + status_code=404, detail="No data found for the specified date range") + + daily_data = date_query_result.resample('D', on='Timestamp').agg({ + 'Open': 'first', + 'High': 'max', + 'Low': 'min', + 'Close': 'last', + 'Volume': 'sum' + }) + + daily_data = daily_data.dropna() + + result = { + 'Open': daily_data['Open'].tolist(), + 'High': daily_data['High'].tolist(), + 'Low': daily_data['Low'].tolist(), + 'Close': daily_data['Close'].tolist(), + 'Volume': daily_data['Volume'].tolist() + } + + return result + + +@app.get("/get_current_date", summary="Get current date") +async def get_current_date(): + return datetime.now().strftime("%Y-%m-%d") diff --git a/servers/bitcoin-price-predictor/requirements.txt b/servers/bitcoin-price-predictor/requirements.txt new file mode 100644 index 0000000..11effd0 --- /dev/null +++ b/servers/bitcoin-price-predictor/requirements.txt @@ -0,0 +1,5 @@ +fastapi +uvicorn[standard] +pydantic +python-multipart +pandas \ No newline at end of file