Gr8/partial.py
2025-09-10 15:02:31 +03:00

131 lines
3.9 KiB
Python

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")