Fix XAU/USD display name, pip value, and invalid symbol validation
- 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 <noreply@anthropic.com>
This commit is contained in:
@@ -48,7 +48,7 @@ CROSS_PAIRS = [
|
|||||||
"EURCHF=X", "CADJPY=X",
|
"EURCHF=X", "CADJPY=X",
|
||||||
]
|
]
|
||||||
|
|
||||||
# Yahoo Finance symbol mapping for display
|
# Symbol display names
|
||||||
SYMBOL_DISPLAY = {
|
SYMBOL_DISPLAY = {
|
||||||
"EURUSD=X": "EUR/USD", "GBPUSD=X": "GBP/USD",
|
"EURUSD=X": "EUR/USD", "GBPUSD=X": "GBP/USD",
|
||||||
"USDJPY=X": "USD/JPY", "USDCHF=X": "USD/CHF",
|
"USDJPY=X": "USD/JPY", "USDCHF=X": "USD/CHF",
|
||||||
@@ -57,6 +57,15 @@ SYMBOL_DISPLAY = {
|
|||||||
"EURJPY=X": "EUR/JPY", "GBPJPY=X": "GBP/JPY",
|
"EURJPY=X": "EUR/JPY", "GBPJPY=X": "GBP/JPY",
|
||||||
"AUDJPY=X": "AUD/JPY", "EURCHF=X": "EUR/CHF",
|
"AUDJPY=X": "AUD/JPY", "EURCHF=X": "EUR/CHF",
|
||||||
"CADJPY=X": "CAD/JPY",
|
"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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -17,7 +17,7 @@ import numpy as np
|
|||||||
import pandas as pd
|
import pandas as pd
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from config import PlatformConfig, Timeframe, SYMBOL_DISPLAY
|
from config import PlatformConfig, Timeframe, SYMBOL_DISPLAY, PIP_VALUES
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -196,10 +196,12 @@ class ForexDataProvider:
|
|||||||
"""Return display name and pip value for a pair."""
|
"""Return display name and pip value for a pair."""
|
||||||
display = SYMBOL_DISPLAY.get(symbol, symbol)
|
display = SYMBOL_DISPLAY.get(symbol, symbol)
|
||||||
is_jpy = "JPY" in 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 {
|
return {
|
||||||
"symbol": symbol,
|
"symbol": symbol,
|
||||||
"display": display,
|
"display": display,
|
||||||
"pip_value": 0.01 if is_jpy else 0.0001,
|
"pip_value": pip_value,
|
||||||
"is_jpy_pair": is_jpy,
|
"is_jpy_pair": is_jpy,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -380,11 +380,16 @@ Examples:
|
|||||||
|
|
||||||
|
|
||||||
def symbol_from_name(name: str) -> str:
|
def symbol_from_name(name: str) -> str:
|
||||||
"""Convert pair name like 'EURUSD' to Yahoo symbol 'EURUSD=X'."""
|
"""
|
||||||
name = name.upper().replace("/", "").replace("_", "")
|
Convert pair name like 'EURUSD' or 'XAUUSD' to internal symbol 'EURUSD=X'.
|
||||||
if not name.endswith("=X"):
|
Returns None for clearly invalid inputs (e.g. timeframe strings like '15M').
|
||||||
name += "=X"
|
"""
|
||||||
return name
|
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]:
|
def run_analysis(args) -> List[SignalReport]:
|
||||||
@@ -413,7 +418,11 @@ def run_analysis(args) -> List[SignalReport]:
|
|||||||
|
|
||||||
# Configure pairs
|
# Configure pairs
|
||||||
if args.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:
|
elif args.all:
|
||||||
config.watch_pairs = MAJOR_PAIRS + CROSS_PAIRS
|
config.watch_pairs = MAJOR_PAIRS + CROSS_PAIRS
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user