PyMtApi5: implemented functions CopyOpen, CopyHigh, CopyLow, CopyClose, CopyTickVolume, CopyRealVolume, CopySpread, CopyTicks

This commit is contained in:
Vyacheslav Demidyuk
2025-01-26 01:46:23 +02:00
parent c61c773fb9
commit d728e10923
3 changed files with 188 additions and 52 deletions
+105
View File
@@ -14,6 +14,7 @@ logger = logging.getLogger(__name__)
def signal_handler(mtapi, _, __):
del __
if mtapi.is_connected():
mtapi.disconnect()
@@ -48,6 +49,14 @@ class Mt5ApiApp:
"CopyBuffer": self.process_copy_buffer,
"CopyRates": self.process_copy_rates,
"CopyTime": self.process_copy_time,
"CopyOpen": self.process_copy_open,
"CopyHigh": self.process_copy_high,
"CopyLow": self.process_copy_low,
"CopyClose": self.process_copy_close,
"CopyTickVolume": self.process_copy_tick_volume,
"CopyRealVolume": self.process_copy_real_volume,
"CopySpread": self.process_copy_spread,
"CopyTicks": self.process_copy_ticks,
}
def on_disconnect(self, error_msg=None):
@@ -317,6 +326,102 @@ class Mt5ApiApp:
result = mtapi.copy_time(symbol_name, timeframe, start_pos, count)
print(f"> CopyTime: response = {result}")
def process_copy_open(self, mtapi, parameters):
pieces = parameters.split(" ", 3)
if len(pieces) != 4 or not pieces[0] or not pieces[1] or not pieces[2] or not pieces[3]:
print(f"! Invalid parameters for command CopyOpen: {parameters}")
return
symbol_name = pieces[0]
timeframe = mt5enums.ENUM_TIMEFRAMES(int(pieces[1]))
start_pos = int(pieces[2])
count = int(pieces[3])
result = mtapi.copy_open(symbol_name, timeframe, start_pos, count)
print(f"> CopyOpen: response = {result}")
def process_copy_high(self, mtapi, parameters):
pieces = parameters.split(" ", 3)
if len(pieces) != 4 or not pieces[0] or not pieces[1] or not pieces[2] or not pieces[3]:
print(f"! Invalid parameters for command CopyHigh: {parameters}")
return
symbol_name = pieces[0]
timeframe = mt5enums.ENUM_TIMEFRAMES(int(pieces[1]))
start_pos = int(pieces[2])
count = int(pieces[3])
result = mtapi.copy_high(symbol_name, timeframe, start_pos, count)
print(f"> CopyHigh: response = {result}")
def process_copy_low(self, mtapi, parameters):
pieces = parameters.split(" ", 3)
if len(pieces) != 4 or not pieces[0] or not pieces[1] or not pieces[2] or not pieces[3]:
print(f"! Invalid parameters for command CopyLow: {parameters}")
return
symbol_name = pieces[0]
timeframe = mt5enums.ENUM_TIMEFRAMES(int(pieces[1]))
start_pos = int(pieces[2])
count = int(pieces[3])
result = mtapi.copy_low(symbol_name, timeframe, start_pos, count)
print(f"> CopyLow: response = {result}")
def process_copy_close(self, mtapi, parameters):
pieces = parameters.split(" ", 3)
if len(pieces) != 4 or not pieces[0] or not pieces[1] or not pieces[2] or not pieces[3]:
print(f"! Invalid parameters for command CopyClose: {parameters}")
return
symbol_name = pieces[0]
timeframe = mt5enums.ENUM_TIMEFRAMES(int(pieces[1]))
start_pos = int(pieces[2])
count = int(pieces[3])
result = mtapi.copy_close(symbol_name, timeframe, start_pos, count)
print(f"> CopyClose: response = {result}")
def process_copy_tick_volume(self, mtapi, parameters):
pieces = parameters.split(" ", 3)
if len(pieces) != 4 or not pieces[0] or not pieces[1] or not pieces[2] or not pieces[3]:
print(f"! Invalid parameters for command CopyTickVolume: {parameters}")
return
symbol_name = pieces[0]
timeframe = mt5enums.ENUM_TIMEFRAMES(int(pieces[1]))
start_pos = int(pieces[2])
count = int(pieces[3])
result = mtapi.copy_tick_volume(symbol_name, timeframe, start_pos, count)
print(f"> CopyTickVolume: response = {result}")
def process_copy_real_volume(self, mtapi, parameters):
pieces = parameters.split(" ", 3)
if len(pieces) != 4 or not pieces[0] or not pieces[1] or not pieces[2] or not pieces[3]:
print(f"! Invalid parameters for command CopyRealVolume: {parameters}")
return
symbol_name = pieces[0]
timeframe = mt5enums.ENUM_TIMEFRAMES(int(pieces[1]))
start_pos = int(pieces[2])
count = int(pieces[3])
result = mtapi.copy_real_volume(symbol_name, timeframe, start_pos, count)
print(f"> CopyRealVolume: response = {result}")
def process_copy_spread(self, mtapi, parameters):
pieces = parameters.split(" ", 3)
if len(pieces) != 4 or not pieces[0] or not pieces[1] or not pieces[2] or not pieces[3]:
print(f"! Invalid parameters for command CopySpread: {parameters}")
return
symbol_name = pieces[0]
timeframe = mt5enums.ENUM_TIMEFRAMES(int(pieces[1]))
start_pos = int(pieces[2])
count = int(pieces[3])
result = mtapi.copy_spread(symbol_name, timeframe, start_pos, count)
print(f"> CopySpread: response = {result}")
def process_copy_ticks(self, mtapi, parameters):
pieces = parameters.split(" ", 3)
if len(pieces) != 4 or not pieces[0] or not pieces[1] or not pieces[2] or not pieces[3]:
print(f"! Invalid parameters for command CopyTicks: {parameters}")
return
symbol_name = pieces[0]
timeframe = mt5enums.CopyTicksFlag(int(pieces[1]))
from_date = int(pieces[2])
count = int(pieces[3])
result = mtapi.copy_ticks(symbol_name, timeframe, from_date, count)
print(f"> CopyTicks: response = {result}")
def mtapi_command_thread(self, mtapi):
while mtapi.is_connected():
filename = "client.cmd"
+78 -52
View File
@@ -29,15 +29,16 @@ class Mt5Quote:
return f"{self.expert_handle}-{self.instrument}: Bid = {self.bid}, Ask = {self.ask}, Volume = {self.volume}"
class Mql5Tick:
class MqlTick:
def __init__(self, tick_json):
self.bid = tick_json["Bid"]
self.ask = tick_json["Ask"]
self.last = tick_json["Last"]
self.volume = tick_json["Volume"]
self.time = tick_json["Time"]
def __repr__(self):
return f"Bid = {self.bid}, Ask = {self.ask}, Last = {self.last}, Volume = {self.volume}"
return f"Bid = {self.bid}, Ask = {self.ask}, Last = {self.last}, Volume = {self.volume}, Time = {self.time}"
class MqlRates:
@@ -142,23 +143,6 @@ class MqlBookInfo:
return f"book_type = {self.book_type}, price = {self.price}, volume = {self.volume}, volume_real = {self.volume_real}"
class MqlRates:
def __init__(self, mql_rates_json):
self.open = mql_rates_json["open"]
self.high = mql_rates_json["high"]
self.low = mql_rates_json["low"]
self.close = mql_rates_json["close"]
self.tick_volume = mql_rates_json["tick_volume"]
self.spread = mql_rates_json["spread"]
self.real_volume = mql_rates_json["real_volume"]
def __repr__(self):
return (
f"open = {self.open}, high = {self.high}, low = {self.low}, close = {self.close}, tick_volume = {self.tick_volume}, "
f"spread = {self.spread}, real_volume = {self.real_volume}"
)
class Mt5ApiClient:
def __init__(self, address, port, callback=None):
self.__address = address
@@ -264,75 +248,117 @@ class Mt5ApiClient:
# CopyBuffer
def copy_buffer(self, indicator_handle: int, buffer_num: int, start_pos: int, count: int):
cmdParams = {
cmd_params = {
"IndicatorHandle": indicator_handle,
"BufferNum": buffer_num,
"StartPos": start_pos,
"Count": count,
}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.CopyBuffer, cmdParams)
return self.__send_command(self.__get_default_expert(), Mt5CommandType.CopyBuffer, cmd_params)
# CopyRates
def copy_rates(self, symbol_name: str, timeframe: ENUM_TIMEFRAMES, start_pos: int, count: int):
cmdParams = {
cmd_params = {
"Symbol": symbol_name,
"Timeframe": timeframe,
"StartPos": start_pos,
"Count": count,
}
res = self.__send_command(self.__get_default_expert(), Mt5CommandType.CopyRates, cmdParams)
res = self.__send_command(self.__get_default_expert(), Mt5CommandType.CopyRates, cmd_params)
rates = [MqlRates(obj) for obj in res]
return rates
# CopyTime
def copy_time(self, symbol_name: str, timeframe: ENUM_TIMEFRAMES, start_pos: int, count: int):
cmdParams = {
cmd_params = {
"Symbol": symbol_name,
"Timeframe": timeframe,
"StartPos": start_pos,
"Count": count,
}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.CopyTime, cmdParams)
return self.__send_command(self.__get_default_expert(), Mt5CommandType.CopyTime, cmd_params)
# Copy Open
def copy_open(self):
# TODO
pass
# CopyOpen
def copy_open(self, symbol_name: str, timeframe: ENUM_TIMEFRAMES, start_pos: int, count: int):
cmd_params = {
"Symbol": symbol_name,
"Timeframe": timeframe,
"StartPos": start_pos,
"Count": count,
}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.CopyOpen, cmd_params)
# Copy High
def copy_high(self):
# TODO
pass
# CopyHigh
def copy_high(self, symbol_name: str, timeframe: ENUM_TIMEFRAMES, start_pos: int, count: int):
cmd_params = {
"Symbol": symbol_name,
"Timeframe": timeframe,
"StartPos": start_pos,
"Count": count,
}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.CopyHigh, cmd_params)
# CopyLow
def copy_low(self):
# TODO
pass
def copy_low(self, symbol_name: str, timeframe: ENUM_TIMEFRAMES, start_pos: int, count: int):
cmd_params = {
"Symbol": symbol_name,
"Timeframe": timeframe,
"StartPos": start_pos,
"Count": count,
}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.CopyLow, cmd_params)
# CopyClose
def copy_close(self):
# TODO
pass
def copy_close(self, symbol_name: str, timeframe: ENUM_TIMEFRAMES, start_pos: int, count: int):
cmd_params = {
"Symbol": symbol_name,
"Timeframe": timeframe,
"StartPos": start_pos,
"Count": count,
}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.CopyClose, cmd_params)
# CopyTickVolume
def copy_tick_volume(self):
# TODO
pass
def copy_tick_volume(self, symbol_name: str, timeframe: ENUM_TIMEFRAMES, start_pos: int, count: int):
cmd_params = {
"Symbol": symbol_name,
"Timeframe": timeframe,
"StartPos": start_pos,
"Count": count,
}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.CopyTickVolume, cmd_params)
# CopyRealVolume
def copy_real_volume(self):
# TODO
pass
def copy_real_volume(self, symbol_name: str, timeframe: ENUM_TIMEFRAMES, start_pos: int, count: int):
cmd_params = {
"Symbol": symbol_name,
"Timeframe": timeframe,
"StartPos": start_pos,
"Count": count,
}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.CopyRealVolume, cmd_params)
# CopySpread
def copy_spread(self):
# TODO
pass
def copy_spread(self, symbol_name: str, timeframe: ENUM_TIMEFRAMES, start_pos: int, count: int):
cmd_params = {
"Symbol": symbol_name,
"Timeframe": timeframe,
"StartPos": start_pos,
"Count": count,
}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.CopySpread, cmd_params)
# CopyTicks
def copy_ticks(self):
# TODO
pass
def copy_ticks(self, symbol_name: str, flags: CopyTicksFlag, from_date: int, count: int):
cmd_params = {
"Symbol": symbol_name,
"Flags": flags,
"From": from_date,
"Count": count,
}
res = self.__send_command(self.__get_default_expert(), Mt5CommandType.CopyTicks, cmd_params)
ticks = [MqlTick(obj) for obj in res]
return ticks
# IndicatorCreate
def indicator_create(
@@ -392,7 +418,7 @@ class Mt5ApiClient:
cmd_params = {"Symbol": symbol_name}
res = self.__send_command(self.__get_default_expert(), Mt5CommandType.SymbolInfoTick, cmd_params)
if res is not None and res["RetVal"] == True:
return Mql5Tick(res["Result"])
return MqlTick(res["Result"])
return None
# SymbolInfoSessionQuote
+5
View File
@@ -894,3 +894,8 @@ class ENUM_DATATYPE(IntEnum):
TYPE_FLOAT = 12
TYPE_DOUBLE = 13
TYPE_STRING = 14
class CopyTicksFlag(IntEnum):
Info = 1 # ticks with Bid and/or Ask changes
Trade = 2 # ticks with changes in Last and Volume
All = -1 # all ticks