Initial commit: Gold Trading Simulator with AI-powered analysis
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
import httpx
|
||||
from typing import List, Dict
|
||||
from datetime import datetime, timedelta
|
||||
from app.schemas.schemas import PriceData
|
||||
|
||||
|
||||
class GoldAPIService:
|
||||
"""
|
||||
Multi-source gold price service using free APIs:
|
||||
- FXRatesAPI for historical XAU/USD data (no API key needed)
|
||||
- GoldPrice.org for real-time spot prices
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.fxrates_base_url = "https://api.fxratesapi.com"
|
||||
self.goldprice_url = "https://data-asg.goldprice.org/dbXRates/USD"
|
||||
|
||||
async def get_gold_daily_data(
|
||||
self, output_size: str = "compact"
|
||||
) -> List[PriceData]:
|
||||
"""
|
||||
Fetch daily gold (XAU/USD) price data from FXRatesAPI
|
||||
|
||||
Args:
|
||||
output_size: 'compact' (~100 days) or 'full' (~1 year)
|
||||
|
||||
Returns:
|
||||
List of PriceData objects with actual XAU/USD prices
|
||||
"""
|
||||
# Calculate date range
|
||||
end_date = datetime.now()
|
||||
if output_size == "full":
|
||||
start_date = end_date - timedelta(days=365)
|
||||
else:
|
||||
start_date = end_date - timedelta(days=100)
|
||||
|
||||
params = {
|
||||
"start_date": start_date.strftime("%Y-%m-%d"),
|
||||
"end_date": end_date.strftime("%Y-%m-%d"),
|
||||
"base": "XAU",
|
||||
"currencies": "USD",
|
||||
}
|
||||
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(
|
||||
f"{self.fxrates_base_url}/timeseries", params=params
|
||||
)
|
||||
response.raise_for_status()
|
||||
data = response.json()
|
||||
|
||||
if not data.get("success") or "rates" not in data:
|
||||
raise ValueError(f"Invalid API response: {data}")
|
||||
|
||||
rates = data["rates"]
|
||||
price_data = []
|
||||
|
||||
for date_str, rate_data in rates.items():
|
||||
# Parse the ISO timestamp
|
||||
dt = datetime.fromisoformat(date_str.replace("Z", "+00:00"))
|
||||
timestamp = int(dt.timestamp())
|
||||
|
||||
# FXRatesAPI gives us XAU price in USD (1 oz gold = X USD)
|
||||
price = rate_data["USD"]
|
||||
|
||||
# Since we don't have OHLC from this API, we'll use the close price
|
||||
# for all values (this is a limitation of free APIs)
|
||||
price_data.append(
|
||||
PriceData(
|
||||
time=timestamp,
|
||||
open=price,
|
||||
high=price * 1.002, # Add small variance for visual effect
|
||||
low=price * 0.998,
|
||||
close=price,
|
||||
)
|
||||
)
|
||||
|
||||
# Sort by time (oldest first)
|
||||
price_data.sort(key=lambda x: x.time)
|
||||
return price_data
|
||||
|
||||
async def get_gold_intraday_data(
|
||||
self, interval: str = "15min", output_size: str = "compact"
|
||||
) -> List[PriceData]:
|
||||
"""
|
||||
Fallback to daily data for intraday (free APIs don't provide intraday)
|
||||
Or fetch current price and simulate recent data points
|
||||
"""
|
||||
# For free tier, we'll return simulated intraday data based on current price
|
||||
current_price = await self.get_current_gold_price()
|
||||
|
||||
price_data = []
|
||||
now = datetime.now()
|
||||
|
||||
# Generate last 24 hours of data points
|
||||
intervals = {
|
||||
"1min": 60,
|
||||
"5min": 5 * 60,
|
||||
"15min": 15 * 60,
|
||||
"30min": 30 * 60,
|
||||
"60min": 60 * 60,
|
||||
}
|
||||
|
||||
interval_seconds = intervals.get(interval, 15 * 60)
|
||||
points = 100 if output_size == "compact" else 500
|
||||
|
||||
for i in range(points):
|
||||
timestamp = int((now - timedelta(seconds=interval_seconds * i)).timestamp())
|
||||
# Add small random variance (±0.5%)
|
||||
variance = 1.0 + ((i % 10 - 5) * 0.001)
|
||||
price = current_price * variance
|
||||
|
||||
price_data.append(
|
||||
PriceData(
|
||||
time=timestamp,
|
||||
open=price,
|
||||
high=price * 1.001,
|
||||
low=price * 0.999,
|
||||
close=price,
|
||||
)
|
||||
)
|
||||
|
||||
price_data.sort(key=lambda x: x.time)
|
||||
return price_data
|
||||
|
||||
async def get_current_gold_price(self) -> float:
|
||||
"""Get current spot gold price from FXRatesAPI (free, no API key)"""
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(
|
||||
f"{self.fxrates_base_url}/latest",
|
||||
params={"base": "XAU", "currencies": "USD"}
|
||||
)
|
||||
response.raise_for_status()
|
||||
data = response.json()
|
||||
|
||||
if not data.get("success") or "rates" not in data:
|
||||
raise ValueError(f"Invalid API response: {data}")
|
||||
|
||||
# Get current XAU/USD price
|
||||
return float(data["rates"]["USD"])
|
||||
|
||||
|
||||
gold_api_service = GoldAPIService()
|
||||
Reference in New Issue
Block a user