Add EUR/USD support and 4-button Telegram scanner

Add EURUSD pair with dynamic pair info lookup. Telegram bot now shows
4 scan buttons: EUR/USD 15M, EUR/USD 1H, USD/JPY 15M, USD/JPY 1H.
Each indicator displays directional arrows in the message output.
Price formatting adapts per pair (5dp for EUR, 3dp for JPY).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Harwinder
2026-05-10 23:49:36 -04:00
parent 3a09dfd62f
commit 037dec643e
3 changed files with 87 additions and 50 deletions
+12 -11
View File
@@ -1,5 +1,5 @@
"""
ForexBot2 — Data Provider (Twelve Data SDK, USD/JPY only)
ForexBot2 — Data Provider (Twelve Data SDK)
==========================================================
Fetches and validates OHLCV via the official `twelvedata` Python SDK.
"""
@@ -13,7 +13,7 @@ from typing import Dict, Optional
import pandas as pd
from twelvedata import TDClient
from config import PlatformConfig, Timeframe, USDJPY, DISPLAY, PIP_VALUE
from config import PlatformConfig, Timeframe, USDJPY, PAIR_INFO
logger = logging.getLogger(__name__)
@@ -37,6 +37,12 @@ class ForexDataProvider:
Timeframe.W1: "1week",
}
BARS_PER_DAY = {
Timeframe.M1: 1440, Timeframe.M5: 288, Timeframe.M15: 96,
Timeframe.M30: 48, Timeframe.H1: 24, Timeframe.H4: 6,
Timeframe.D1: 1, Timeframe.W1: 0.143,
}
RATE_LIMIT = 8
RATE_WINDOW = 60.0
@@ -103,23 +109,18 @@ class ForexDataProvider:
return None
def get_spread_estimate(self, symbol: str = USDJPY) -> float:
"""Estimate spread from recent M5 H-L median; fallback to 1 pip on JPY."""
try:
df = self.fetch_ohlcv(symbol, Timeframe.M5, lookback_days=1)
if df is not None and not df.empty:
return float((df["High"] - df["Low"]).median())
except Exception:
pass
# Fallback: 1 pip = 0.01 for JPY pairs
return PIP_VALUE
info = PAIR_INFO.get(symbol, PAIR_INFO[USDJPY])
return info["pip_value"]
def get_pair_info(self, symbol: str = USDJPY) -> Dict:
return {
"symbol": symbol,
"display": DISPLAY,
"pip_value": PIP_VALUE,
"is_jpy_pair": True,
}
info = PAIR_INFO.get(symbol, PAIR_INFO[USDJPY])
return {"symbol": symbol, **info}
# ── Private ────────────────────────────────────────────────────