Aziz30's picture
Update Interface_Graphique/services/market_service.py
780772f verified
import os
from typing import Optional
import pandas as pd
import datetime as dt
import time
try:
import requests # for Alpha Vantage fallback
except Exception:
requests = None
try:
import yfinance as yf # lightweight polling, near real-time for popular tickers
except Exception:
yf = None
def fetch_candles_yf(symbol: str, period: str = '1d', interval: str = '1m') -> pd.DataFrame:
if yf is None:
raise RuntimeError("yfinance is not installed. Please install yfinance.")
ticker = yf.Ticker(symbol)
df = ticker.history(period=period, interval=interval, auto_adjust=False)
df = df.rename(columns={
'Open': 'Open', 'High': 'High', 'Low': 'Low', 'Close': 'Close', 'Volume': 'Volume'
})
# Ensure index is datetime and sorted
# yfinance can return either Datetime or Date in index/columns. Normalize to Date index
if 'Datetime' in df.columns:
df = df.rename(columns={'Datetime': 'Date'})
df = df.reset_index().rename(columns={'Date': 'Date'})
if 'Date' not in df.columns:
df = df.rename(columns={'index': 'Date'})
df = df.set_index('Date')
df = df.sort_index()
return df[['Open', 'High', 'Low', 'Close']]
def get_returns(symbol):
return [0.01] * 60
def _map_interval_to_alpha_vantage(interval: str) -> Optional[str]:
mapping = {
'1m': '1min',
'5m': '5min',
'15m': '15min',
'60m': '60min'
}
return mapping.get(interval)
def fetch_candles_alpha_vantage(symbol: str, interval: str, api_key: str) -> pd.DataFrame:
if requests is None:
raise RuntimeError("requests n'est pas installé. Veuillez installer requests.")
av_interval = _map_interval_to_alpha_vantage(interval) or '1min'
params = {
'function': 'TIME_SERIES_INTRADAY',
'symbol': symbol,
'interval': av_interval,
'apikey': api_key,
'outputsize': 'compact'
}
url = 'https://www.alphavantage.co/query'
resp = requests.get(url, params=params, timeout=15)
resp.raise_for_status()
data = resp.json()
key = f'Time Series ({av_interval})'
if key not in data:
# Alpha Vantage rate limit or unsupported symbol
raise RuntimeError(f"Alpha Vantage réponse invalide: {list(data.keys())[:3]}")
ts = data[key]
rows = []
for ts_str, ohlc in ts.items():
# parse timestamps as local naive datetime
try:
ts_dt = dt.datetime.fromisoformat(ts_str)
except Exception:
# fallback format
ts_dt = dt.datetime.strptime(ts_str, '%Y-%m-%d %H:%M:%S')
rows.append({
'Date': ts_dt,
'Open': float(ohlc['1. open']),
'High': float(ohlc['2. high']),
'Low': float(ohlc['3. low']),
'Close': float(ohlc['4. close'])
})
df = pd.DataFrame(rows).set_index('Date').sort_index()
return df[['Open', 'High', 'Low', 'Close']]
def fetch_latest_candles(symbol: str, period: str = '1d', interval: str = '1m') -> pd.DataFrame:
# If Alpha Vantage key is present and symbol looks supported, try AV first
av_key = os.getenv('ALPHAVANTAGE_API_KEY')
# Simple heuristic: AV does not support indices like ^GSPC, ^FCHI directly
looks_index = symbol.startswith('^')
if av_key and not looks_index:
try:
return fetch_candles_alpha_vantage(symbol, interval=interval, api_key=av_key)
except Exception:
# fall back to yfinance below
pass
# Retry yfinance a couple of times in case of DNS hiccups
last_err = None
for _ in range(2):
try:
return fetch_candles_yf(symbol, period=period, interval=interval)
except Exception as e:
last_err = e
time.sleep(1.0)
# final raise
raise last_err if last_err else RuntimeError('Unknown data fetch error')