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",
|
"trade_mode": "DEMO",
|
||||||
}
|
}
|
||||||
|
|
||||||
async def symbols(self) -> List[str]:
|
async def symbols(self, search: Optional[str] = None) -> List[str]:
|
||||||
return self.SYMBOLS
|
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]:
|
async def symbol_info(self, symbol: str) -> Dict[str, Any]:
|
||||||
if symbol not in self.BASE_PRICES:
|
if symbol not in self.BASE_PRICES:
|
||||||
|
|
@ -367,15 +367,53 @@ class LiveBridge(MT5Bridge):
|
||||||
"trade_mode": "DEMO" if info.trade_mode == 0 else "REAL",
|
"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()
|
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()
|
syms = self.mt5.symbols_get()
|
||||||
if syms is None:
|
if syms is None:
|
||||||
return []
|
return []
|
||||||
return [s.name for s in syms if s.visible]
|
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]:
|
async def symbol_info(self, symbol: str) -> Dict[str, Any]:
|
||||||
await self.ensure()
|
await self.ensure()
|
||||||
|
symbol = self._resolve(symbol)
|
||||||
info = self.mt5.symbol_info(symbol)
|
info = self.mt5.symbol_info(symbol)
|
||||||
if info is None:
|
if info is None:
|
||||||
raise HTTPException(404, f"Symbol {symbol} not found")
|
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]:
|
async def ohlc(self, symbol: str, timeframe: str, bars: int, start_pos: int = 0) -> List[Dict]:
|
||||||
await self.ensure()
|
await self.ensure()
|
||||||
|
symbol = self._resolve(symbol)
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
# Check if seconds timeframe
|
# Check if seconds timeframe
|
||||||
|
|
@ -440,6 +479,7 @@ class LiveBridge(MT5Bridge):
|
||||||
to_ts: Unix timestamp Ende
|
to_ts: Unix timestamp Ende
|
||||||
"""
|
"""
|
||||||
await self.ensure()
|
await self.ensure()
|
||||||
|
symbol = self._resolve(symbol)
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
|
|
||||||
|
|
@ -575,6 +615,7 @@ class LiveBridge(MT5Bridge):
|
||||||
comment: str = "") -> Dict[str, Any]:
|
comment: str = "") -> Dict[str, Any]:
|
||||||
"""Open a market order."""
|
"""Open a market order."""
|
||||||
await self.ensure()
|
await self.ensure()
|
||||||
|
symbol = self._resolve(symbol)
|
||||||
|
|
||||||
# Get symbol info for filling
|
# Get symbol info for filling
|
||||||
info = self.mt5.symbol_info(symbol)
|
info = self.mt5.symbol_info(symbol)
|
||||||
|
|
@ -688,6 +729,7 @@ class LiveBridge(MT5Bridge):
|
||||||
|
|
||||||
async def tick(self, symbol: str) -> Dict[str, Any]:
|
async def tick(self, symbol: str) -> Dict[str, Any]:
|
||||||
await self.ensure()
|
await self.ensure()
|
||||||
|
symbol = self._resolve(symbol)
|
||||||
tick = self.mt5.symbol_info_tick(symbol)
|
tick = self.mt5.symbol_info_tick(symbol)
|
||||||
if tick is None:
|
if tick is None:
|
||||||
raise HTTPException(404, f"No tick for {symbol}")
|
raise HTTPException(404, f"No tick for {symbol}")
|
||||||
|
|
@ -839,8 +881,8 @@ async def account():
|
||||||
|
|
||||||
|
|
||||||
@app.get("/symbols")
|
@app.get("/symbols")
|
||||||
async def symbols():
|
async def symbols(search: Optional[str] = Query(None, description="z.B. XAU – sucht in ALLEN Broker-Symbolen")):
|
||||||
syms = await bridge.symbols()
|
syms = await bridge.symbols(search) if search else await bridge.symbols()
|
||||||
return {"count": len(syms), "symbols": syms}
|
return {"count": len(syms), "symbols": syms}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
BIN
mt5-stack.zip
BIN
mt5-stack.zip
Binary file not shown.
Loading…
Reference in a new issue