import MetaTrader5 as mt5 import logging import time # ----------------------------- # Logging # ----------------------------- logging.basicConfig(level=logging.INFO, format="%(asctime)s | %(levelname)s | %(message)s") log = logging.getLogger() # ----------------------------- # Initialize MT5 # ----------------------------- if not mt5.initialize(): log.error(f"MT5 initialize failed: {mt5.last_error()}") quit() log.info("Connected to MT5 terminal") # ----------------------------- # Parameters # ----------------------------- SYMBOLS = ["XAUUSD", "USDJPY", "US30", "USTEC"] LOT_SIZE = 0.05 # Full trade lot size PARTIAL_RATIO = 0.5 # Fraction for partial close DEVIATION = 20 # ----------------------------- # Helpers # ----------------------------- def get_tick(symbol): tick = mt5.symbol_info_tick(symbol) if tick is None: log.warning(f"No tick data for {symbol}") return tick def get_min_lot(symbol): info = mt5.symbol_info(symbol) if info is None: return 0.01 return info.volume_min, info.volume_step # ----------------------------- # Open trade function # ----------------------------- def open_trade(symbol, order_type, lot_size): tick = get_tick(symbol) if not tick: return None price = tick.ask if order_type == mt5.ORDER_TYPE_BUY else tick.bid request = { "action": mt5.TRADE_ACTION_DEAL, "symbol": symbol, "volume": lot_size, "type": order_type, "price": price, "deviation": DEVIATION, "magic": 234000, "comment": "HFT open", "type_time": mt5.ORDER_TIME_GTC, "type_filling": mt5.ORDER_FILLING_IOC } result = mt5.order_send(request) if result.retcode != mt5.TRADE_RETCODE_DONE: log.error(f"Trade failed for {symbol}: {result.retcode}") return None log.info(f"Trade opened: {symbol} {order_type} {lot_size} lots, ticket {result.order}") return result.order # ----------------------------- # Partial close function # ----------------------------- def partial_close(symbol, position_ticket, fraction=0.5): info = mt5.symbol_info(symbol) if not info: log.warning(f"{symbol} info unavailable for partial close") return pos = mt5.positions_get(ticket=position_ticket) if not pos: log.warning(f"Position {position_ticket} not found") return pos = pos[0] min_lot, step = info.volume_min, info.volume_step partial_volume = max(min_lot, round(pos.volume * fraction / step) * step) if partial_volume <= 0: log.warning(f"Partial volume too small for {symbol}") return tick = get_tick(symbol) if not tick: return price = tick.bid if pos.type == mt5.ORDER_TYPE_BUY else tick.ask request = { "action": mt5.TRADE_ACTION_DEAL, "symbol": symbol, "volume": partial_volume, "type": mt5.ORDER_TYPE_SELL if pos.type == mt5.ORDER_TYPE_BUY else mt5.ORDER_TYPE_BUY, "position": position_ticket, "price": price, "deviation": DEVIATION, "magic": 234000, "comment": "HFT partial close", "type_time": mt5.ORDER_TIME_GTC, "type_filling": mt5.ORDER_FILLING_IOC } result = mt5.order_send(request) if result.retcode != mt5.TRADE_RETCODE_DONE: log.error(f"Partial close failed for {symbol}: {result.retcode}") else: log.info(f"Partial close executed: {symbol} {partial_volume} lots, ticket {position_ticket}") # ----------------------------- # Example HFT loop # ----------------------------- try: for sym in SYMBOLS: # Randomly open buy or sell import random order_type = random.choice([mt5.ORDER_TYPE_BUY, mt5.ORDER_TYPE_SELL]) ticket = open_trade(sym, order_type, LOT_SIZE) if ticket: time.sleep(1) # simulate holding partial_close(sym, ticket, PARTIAL_RATIO) finally: mt5.shutdown() log.info("MT5 shutdown complete")