From 94b93cf1e7b9c4472fb0b22bb2df62e1597ac129 Mon Sep 17 00:00:00 2001 From: Harwinder Date: Mon, 4 May 2026 15:59:34 -0400 Subject: [PATCH] Fix XAU/USD display name, pip value, and invalid symbol validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - config.py: add XAU/USD and XAG/USD to SYMBOL_DISPLAY; add PIP_VALUES map for commodities (gold pip = $0.01, not $0.0001) - data_provider.py: use PIP_VALUES in get_pair_info so gold trade setup shows correct pip counts instead of 269,000 pips for a $27 SL - main.py: validate symbols in symbol_from_name — rejects non-alpha inputs like '15M' with a helpful hint to use --timeframe instead Co-Authored-By: Claude Sonnet 4.6 --- config.py | 11 ++++++++++- data_provider.py | 6 ++++-- main.py | 21 +++++++++++++++------ 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/config.py b/config.py index 8bb648b..f638681 100644 --- a/config.py +++ b/config.py @@ -48,7 +48,7 @@ CROSS_PAIRS = [ "EURCHF=X", "CADJPY=X", ] -# Yahoo Finance symbol mapping for display +# Symbol display names SYMBOL_DISPLAY = { "EURUSD=X": "EUR/USD", "GBPUSD=X": "GBP/USD", "USDJPY=X": "USD/JPY", "USDCHF=X": "USD/CHF", @@ -57,6 +57,15 @@ SYMBOL_DISPLAY = { "EURJPY=X": "EUR/JPY", "GBPJPY=X": "GBP/JPY", "AUDJPY=X": "AUD/JPY", "EURCHF=X": "EUR/CHF", "CADJPY=X": "CAD/JPY", + # Commodities + "XAUUSD=X": "XAU/USD", "XAGUSD=X": "XAG/USD", +} + +# Pip values per symbol (used for trade setup risk/reward in pips) +# Commodities and JPY pairs differ from the standard 0.0001 forex pip +PIP_VALUES = { + "XAUUSD=X": 0.01, # Gold: 1 pip = $0.01 + "XAGUSD=X": 0.001, # Silver: 1 pip = $0.001 } diff --git a/data_provider.py b/data_provider.py index eb824dd..2e3574b 100644 --- a/data_provider.py +++ b/data_provider.py @@ -17,7 +17,7 @@ import numpy as np import pandas as pd import requests -from config import PlatformConfig, Timeframe, SYMBOL_DISPLAY +from config import PlatformConfig, Timeframe, SYMBOL_DISPLAY, PIP_VALUES logger = logging.getLogger(__name__) @@ -196,10 +196,12 @@ class ForexDataProvider: """Return display name and pip value for a pair.""" display = SYMBOL_DISPLAY.get(symbol, symbol) is_jpy = "JPY" in symbol + # Commodity-specific pip values take priority, then JPY pairs, then standard forex + pip_value = PIP_VALUES.get(symbol, 0.01 if is_jpy else 0.0001) return { "symbol": symbol, "display": display, - "pip_value": 0.01 if is_jpy else 0.0001, + "pip_value": pip_value, "is_jpy_pair": is_jpy, } diff --git a/main.py b/main.py index d5a0c5f..46532e3 100644 --- a/main.py +++ b/main.py @@ -380,11 +380,16 @@ Examples: def symbol_from_name(name: str) -> str: - """Convert pair name like 'EURUSD' to Yahoo symbol 'EURUSD=X'.""" - name = name.upper().replace("/", "").replace("_", "") - if not name.endswith("=X"): - name += "=X" - return name + """ + Convert pair name like 'EURUSD' or 'XAUUSD' to internal symbol 'EURUSD=X'. + Returns None for clearly invalid inputs (e.g. timeframe strings like '15M'). + """ + clean = name.upper().replace("/", "").replace("_", "").replace("=X", "") + if not clean.isalpha() or len(clean) < 5: + print(f" Warning: '{name}' is not a valid pair symbol — skipping.") + print(f" Hint: timeframes go in --timeframe (e.g. --timeframe M15), not --pairs.") + return None + return clean + "=X" def run_analysis(args) -> List[SignalReport]: @@ -413,7 +418,11 @@ def run_analysis(args) -> List[SignalReport]: # Configure pairs if args.pairs: - config.watch_pairs = [symbol_from_name(p) for p in args.pairs] + symbols = [symbol_from_name(p) for p in args.pairs] + config.watch_pairs = [s for s in symbols if s is not None] + if not config.watch_pairs: + print(" Error: No valid pair symbols provided. Exiting.") + sys.exit(1) elif args.all: config.watch_pairs = MAJOR_PAIRS + CROSS_PAIRS else: