news mcp
All checks were successful
MT5 Helm GitOps Deploy / build-and-deploy (push) Has been skipped
All checks were successful
MT5 Helm GitOps Deploy / build-and-deploy (push) Has been skipped
This commit is contained in:
parent
0ee2854133
commit
c53cb5aae3
2 changed files with 47 additions and 5 deletions
|
|
@ -132,8 +132,8 @@ class MockBridge(MT5Bridge):
|
|||
"trade_mode": "DEMO",
|
||||
}
|
||||
|
||||
async def symbols(self) -> List[str]:
|
||||
return self.SYMBOLS
|
||||
async def symbols(self, search: Optional[str] = None) -> List[str]:
|
||||
return [x for x in self.SYMBOLS if not search or search.upper() in x]
|
||||
|
||||
async def symbol_info(self, symbol: str) -> Dict[str, Any]:
|
||||
if symbol not in self.BASE_PRICES:
|
||||
|
|
@ -367,15 +367,53 @@ class LiveBridge(MT5Bridge):
|
|||
"trade_mode": "DEMO" if info.trade_mode == 0 else "REAL",
|
||||
}
|
||||
|
||||
async def symbols(self) -> List[str]:
|
||||
async def symbols(self, search: Optional[str] = None) -> List[str]:
|
||||
await self.ensure()
|
||||
if search:
|
||||
syms = self.mt5.symbols_get(group=f"*{search}*")
|
||||
return [s.name for s in syms] if syms else []
|
||||
syms = self.mt5.symbols_get()
|
||||
if syms is None:
|
||||
return []
|
||||
return [s.name for s in syms if s.visible]
|
||||
|
||||
def _resolve(self, symbol: str) -> str:
|
||||
"""Broker-Symbolnamen finden und in der Marktübersicht aktivieren.
|
||||
PU Prime u.a. hängen Suffixe an (z.B. XAUUSD -> XAUUSD.s), und Symbole
|
||||
ausserhalb der Marktübersicht liefern keine Ticks.
|
||||
Reihenfolge: SYMBOL_MAP (bots.env) -> exakter Name -> Name mit Suffix."""
|
||||
cache = getattr(self, "_symbol_cache", None)
|
||||
if cache is None:
|
||||
cache = self._symbol_cache = {}
|
||||
for pair in os.getenv("SYMBOL_MAP", "").split(","):
|
||||
if "=" in pair:
|
||||
k, v = pair.split("=", 1)
|
||||
cache[k.strip().upper()] = v.strip() # z.B. XAUUSD=XAUUSD.s
|
||||
key = symbol.upper()
|
||||
name = cache.get(key)
|
||||
if name is None:
|
||||
# Endpunkte schreiben Symbole gross ("XAUUSD.S"), der Broker-Name ist aber
|
||||
# case-sensitiv ("XAUUSD.s") -> über den Basisnamen suchen, Gross/Klein egal
|
||||
base = key.split(".")[0]
|
||||
cands = [c.name for c in (self.mt5.symbols_get(group=f"*{base}*") or [])]
|
||||
exact = [n for n in cands if n.upper() == key]
|
||||
prefixed = sorted((n for n in cands if n.upper().startswith(base)), key=len)
|
||||
if exact:
|
||||
name = exact[0]
|
||||
elif prefixed:
|
||||
name = prefixed[0]
|
||||
else:
|
||||
raise HTTPException(404, f"Symbol {symbol} not found at broker")
|
||||
if name != symbol:
|
||||
log.info(f"Symbol {symbol} -> {name} (broker name)")
|
||||
cache[key] = name
|
||||
if not self.mt5.symbol_select(name, True):
|
||||
log.warning(f"symbol_select({name}) failed: {self.mt5.last_error()}")
|
||||
return name
|
||||
|
||||
async def symbol_info(self, symbol: str) -> Dict[str, Any]:
|
||||
await self.ensure()
|
||||
symbol = self._resolve(symbol)
|
||||
info = self.mt5.symbol_info(symbol)
|
||||
if info is None:
|
||||
raise HTTPException(404, f"Symbol {symbol} not found")
|
||||
|
|
@ -395,6 +433,7 @@ class LiveBridge(MT5Bridge):
|
|||
|
||||
async def ohlc(self, symbol: str, timeframe: str, bars: int, start_pos: int = 0) -> List[Dict]:
|
||||
await self.ensure()
|
||||
symbol = self._resolve(symbol)
|
||||
import pandas as pd
|
||||
|
||||
# Check if seconds timeframe
|
||||
|
|
@ -440,6 +479,7 @@ class LiveBridge(MT5Bridge):
|
|||
to_ts: Unix timestamp Ende
|
||||
"""
|
||||
await self.ensure()
|
||||
symbol = self._resolve(symbol)
|
||||
import pandas as pd
|
||||
from datetime import datetime, timezone
|
||||
|
||||
|
|
@ -575,6 +615,7 @@ class LiveBridge(MT5Bridge):
|
|||
comment: str = "") -> Dict[str, Any]:
|
||||
"""Open a market order."""
|
||||
await self.ensure()
|
||||
symbol = self._resolve(symbol)
|
||||
|
||||
# Get symbol info for filling
|
||||
info = self.mt5.symbol_info(symbol)
|
||||
|
|
@ -688,6 +729,7 @@ class LiveBridge(MT5Bridge):
|
|||
|
||||
async def tick(self, symbol: str) -> Dict[str, Any]:
|
||||
await self.ensure()
|
||||
symbol = self._resolve(symbol)
|
||||
tick = self.mt5.symbol_info_tick(symbol)
|
||||
if tick is None:
|
||||
raise HTTPException(404, f"No tick for {symbol}")
|
||||
|
|
@ -839,8 +881,8 @@ async def account():
|
|||
|
||||
|
||||
@app.get("/symbols")
|
||||
async def symbols():
|
||||
syms = await bridge.symbols()
|
||||
async def symbols(search: Optional[str] = Query(None, description="z.B. XAU – sucht in ALLEN Broker-Symbolen")):
|
||||
syms = await bridge.symbols(search) if search else await bridge.symbols()
|
||||
return {"count": len(syms), "symbols": syms}
|
||||
|
||||
|
||||
|
|
|
|||
BIN
mt5-stack.zip
BIN
mt5-stack.zip
Binary file not shown.
Loading…
Reference in a new issue