Mein Punkt ist, dass die Integration von Python mit MT5 nicht vollständig ist. Sie können Indikatorwerte nicht DIREKT abrufen
Speichern von Daten in mql
int i = iBarShift(_Symbol,PERIOD_CURRENT,startTime);
string nm = _Symbol+"_Inputs.csv";
int h = FileOpen(nm,FILE_CSV|FILE_WRITE|FILE_COMMON,";");
double d[2];
while (i > 0) {
d[0]=iСustom(_Symbol,PERIOD_CURRENT,"Ind_1",0,i);
d[1]=iСustom(_Symbol,PERIOD_CURRENT,"Ind_2",0,i);
FileWrite(h,d[0],d[1]);
i--;
}
FileClose(h);
Die Ziele des Themas sind so einfach wie fünf Pfennige: Jeder soll mit dem algorithmischen Handel in Python beginnen können, indem er einfach ein paar Codes kopiert, wie z. B. die Initialisierung der Kommunikation mit dem Terminal, das Anfordern von Kursen, die Aufforderung an den Server, einen Handel zu eröffnen oder zu schließen, usw. usw. Konzentrieren Sie sich ausschließlich auf die Logik, und zwar in einer extrem einfach zu verwendenden Sprache.
Genau... Die Logik ist genau das, was dem algorithmischen Handel fehlt - die Logik, die man braucht, um eine Handelsstrategie zu testen, bevor "alle anderen" Teile des Codes einfügen und in den echten Handel einsteigen
viel Glück bei der Verwirklichung Ihrer "nicht-mythischen" Ziele
Wer keine in Dateien gespeicherten Preise benötigt, wird den Code ein wenig umschreiben und nicht "in Dateien schreiben - aus Dateien lesen", sondern nur die gewünschte Datenstruktur verwenden. Es ist im Wesentlichen nur ein Schaufenster für primitive Dinge, für diejenigen, die bereit sind, die ersten Schritte zu machen.
Diejenigen, die bereits mit Konzepten wie Listen, Tupeln, Wörterbüchern usw. vertraut sind.
Ich schlage vor, die Preisdateien mit der Funktion read_all_files_with_prices zu lesen, die die Funktion read_file_with_prices auslöst, um die Preisdatei jedes Instruments zu lesen.
Die Funktion read_file_with_prices gibt entweder ein Array numpy.ndarray mit Zeilen und Spalten zurück, die der ursprünglichen Preisdatei entsprechen (wenn die Preise erfolgreich gelesen und auf Datenintegrität geprüft wurden, ist jedes Element vom Typ numpy.float64), oder die Zeichenkette "no data", wenn keine oder unvollständige Daten gelesen wurden .
Die Funktion read_all_files_with_prices soll ein Wörterbuch mit Kursen für alle Instrumente zurückgeben. Angenommen, die Schlüssel in diesem Wörterbuch sind die Namen der Instrumente und die Werte sind die Wörterbücher mit Anführungszeichen eines entsprechenden Instruments. In den Wörterbüchern mit Anführungszeichen für ein Symbol sind die Schlüssel Datum_Zeit, die Werte sind Balken (Klasse bar); außerdem schlage ich vor, die Schlüssel :
is_data": Schlüsselwert - True, wenn ein Zitat vorhanden ist, False - wenn beim Lesen aus der Datei "keine Daten" zurückgegeben wurden,
Instrument": Schlüsselwert - Instrument (str);
Preise": Schlüsselwert - Array der Preise nach Instrument (numpy.ndarray)
Kurz gesagt, dies ist die von mir vorgeschlagene Datenstruktur:
Funktionen zum Lesen von Dateien und zum Erstellen der oben genannten Datenstruktur hinzugefügt:
import os, time
import datetimeas dt
from json import loads, dump
from random import randint
import numpy as np
from Classes import date_time, Bar
import Functions
import MetaTrader5 as mt5
N = 1000 # количество отсчётов, сохраняемых в файлах котировок
N_sd_sell_max = 3 # максимальное количество сделок типа sell по одному инструменту
N_sd_buy_max = 3 # максимальное количество сделок типа buy по одному инструменту
volume = 0.01 # объём сделок
account_demo = ['Alpari-MT5-Demo', 12345678, 'password']
work_account = account_demo
work_catalog = 'Z:\\fx_for_forum\\fx\\'
instruments = ['EURUSD_i', 'GBPUSD_i', 'EURGBP_i', 'USDCHF_i', 'USDCAD_i', 'USDJPY_i']
def terminal_init(path_to_terminal, account):
'''
Функция осуществляет соединение с терминалом MT5
'''
if mt5.initialize(path_to_terminal, server=account[0], login=account[1], password=account[2]):
str1 = ' - соединение с терминалом {} билд {} установлено'
print(date_time.now().nice_view, str1.format(mt5.terminal_info().name, mt5.version()[1]))
return True
else:
print(date_time.now().nice_view, ' - соединение с терминалом установить не удалось')
return False
def terminal_done():
'''
Функция завершает соединение с терминалом MT5
'''
try:
mt5.shutdown()
print('\n' + date_time.now().nice_view, ' - соединение с терминалом успешно завершено')
except:
print('\n' + date_time.now().nice_view, ' - соединение с терминалом завершить не удалось')
def dt_stamp_from_M5_view(M5_view):
return date_time(int(M5_view[0:4]), int(M5_view[4:6]), int(M5_view[6:8]), int(M5_view[8:10]), int(M5_view[10:12]))
def pips_definer(instrument):
'''
Функция возвращает величину пипса для инструмента, например для EURUSD - 0.0001, для USDJPY - 0.01
'''
if instrument in ['EURUSD_i', 'GBPUSD_i', 'EURGBP_i', 'USDCHF_i', 'USDCAD_i']:
return0.0001
elif instrument in ['USDJPY_i']:
return0.01else:
return None
def save_prices_to_file(instrument, n=100):
'''
Функция принимает инструмент, количество отсчётов цены n в таймфрейме М5,
и сохраняет в файл (только сформировавшиеся полностью бары, время соответствует времени закрытия (!) бара)
'''
w = pips_definer(instrument)
tochn = int(abs(np.log10(w))+1)
path_file = os.path.join(work_catalog, instrument+'.txt')
bars = mt5.copy_rates_from_pos(instrument, mt5.TIMEFRAME_M5, 0, n+1) # в случае ошибки mt5.copy_rates_from_pos возвращает None
try:
f = open(path_file, 'w')
for i in range(0, n+1):
bar = bars[i]
dt_stamp = date_time.fromtimestamp(bar[0], dt.timezone.utc) + dt.timedelta(hours=1, minutes=5)
open_ = str(round(bar[1], tochn))
high_ = str(round(bar[2], tochn))
low_ = str(round(bar[3], tochn))
close_ = str(round(bar[4], tochn))
if i != n:
f.write(dt_stamp.M5_view + ' ' + open_ + ' ' + high_ + ' ' + low_ + ' ' + close_ + '\n')
f.close()
print(date_time.now().nice_view, ' - котировки {} успешно записаны в файл'.format(instrument))
except:
print(date_time.now().nice_view, ' - котировки {} записать в файл не удалось'.format(instrument))
def read_file_with_prices(catalog, instrument):
'''
Функция принимает каталог, и наименование инструмента, читает в указанном каталоге файл с ценами для указанного инструмента
(формат данных: отсчёт времени в виде строки формата M5_view, open, high, low, close), проверяет цены на целостность данных.
Функция возвращает или массив ndarray (если всё успешно), или строку 'no data' (если данные не прочитались, или неполны)
'''
path_file = os.path.join(catalog, instrument+'.txt')
try:
f = open(path_file, 'r')
ndarray___with_prices_for_instrument = np.loadtxt(f, delimiter=' ', dtype='float64')
f.close()
except:
print(date_time.now().nice_view + ' - Файл с котировками для {} прочитать не удалось'.format(instrument))
return 'no data'
# проверка данных на целостность
timedelta_5 = dt.timedelta(minutes=5)
nx = ndarray___with_prices_for_instrument.shape[0]
for i in range(1, nx):
dt_stamp_i = dt_stamp_from_M5_view(str(int(ndarray___with_prices_for_instrument[i, 0])))
dt_stamp_im1 = dt_stamp_from_M5_view(str(int(ndarray___with_prices_for_instrument[i-1, 0])))
t_delta = dt_stamp_i - dt_stamp_im1
if t_delta != timedelta_5:
if t_delta >= dt.timedelta(hours=47) and t_delta <= dt.timedelta(hours=50):
pass # разрыв данных с вечера пятницы до понедельника
else:
t1 = ' - Котировки для {} неполны, и не будут переданы на выполнение расчётов\nИменно - ошибка при {}'
print((date_time.now().nice_view + t1).format(instrument, dt_stamp_im1.M5_view))
return 'no data'
return ndarray___with_prices_for_instrument
def read_all_files_with_prices(catalog, instruments):
'''
Функция принимает каталог, и список инструментов, читает в указанном каталоге файлы с ценами для указанных инструментов
с использованием функции read_file_with_prices.
Функция возвращает словарь prices_for_all_instruments с котировками по всем инструментам.
В этом словаре ключи - наименования инструментов, значения - словари с котировками по одному соответствующему инструменту.
В словарях с котировками по одному инструменту ключи - отсчёты даты-времени (класс date_time), значения - бары (класс bar),
кроме того предусмотрены ключи:
- 'is_data' - значение по ключу - True, если котировки в наличии, False - если функция чтения из файла вернула 'no data',
- 'instrument' - значение по ключу - инструмент (str);
- 'prices' - значение по ключу - массив котировок по инструменту (numpy.ndarray)
'''
dict___with_prices_for_all_instruments = {}
for instrument in instruments:
w = pips_definer(instrument)
ndarray___with_prices_for_instrument = read_file_with_prices(catalog, instrument)
dict___with_prices_for_instrument = {}
if type(ndarray___with_prices_for_instrument) == type('no data'):
dict___with_prices_for_instrument['is_data'] = False
else:
dict___with_prices_for_instrument['is_data'] = True
dict___with_prices_for_instrument['instrument'] = instrument
dict___with_prices_for_instrument['prices'] = ndarray___with_prices_for_instrument
for i in range(0, ndarray___with_prices_for_instrument.shape[0]):
dt_stamp = dt_stamp_from_M5_view(str(int(ndarray___with_prices_for_instrument[i, 0])))
dict___with_prices_for_instrument[dt_stamp] = Bar(instrument, 5, dt_stamp,
ndarray___with_prices_for_instrument[i, 1],
ndarray___with_prices_for_instrument[i, 3],
ndarray___with_prices_for_instrument[i, 2],
ndarray___with_prices_for_instrument[i, 4], w)
dict___with_prices_for_all_instruments[instrument] = dict___with_prices_for_instrument
return dict___with_prices_for_all_instruments
def main(N):
'''
Главная функция, обеспечивающая в бесконечном цикле связь с терминалом,
сохранение котировок, и запуск функции, осуществляющей торговлю
'''
dt_start = date_time.now()
dt_write = dt_stamp_from_M5_view(dt_start.M5_view) + dt.timedelta(minutes=5, seconds=10)
print('\n' + dt_start.nice_view, ' - начал работу, бездействую до ' + dt_write.nice_view + '\n')
timedelta_sleep = dt_write - date_time.now()
time.sleep(timedelta_sleep.seconds)
while True:
# установка соединения с MetaTrader5
if terminal_init(os.path.join('C:\\', 'Program Files', 'Alpari MT5', 'terminal64.exe'), work_account):
# запись цен в файлы: для всех инструментов, N отсчётов
if (dt.datetime.now() - dt_write) < dt.timedelta(seconds=10):
print('\n' + date_time.now().nice_view + ' - начинаю запись цен в файлы для всех инструментов')
for instrument in instruments:
save_prices_to_file(instrument, N)
# пауза 5 секунд после записи файлов с ценами, возможно необходимых для открытия в Mathcad,
# или ещё зачем, если в них нет нужды, желающие могут переписать код, исключив бессмысленную
# последовательность записи файлов, и затем чтения файлов, сразу сформировав нужную им структуру данных
time.sleep(5)
# определяем значение последнего отсчёта времени, который должен быть в файлах котировок, если они актуальны
# (в выходные дни это будет не так, а в будни, пока рынок открыт - так)
fx_dt_stamp_now = dt_stamp_from_M5_view(date_time.now().M5_view)
print('\n\n'+date_time.now().nice_view, '- начинаю вычисления для отсчёта времени {}'.format(fx_dt_stamp_now.M5_view))
# получаем словарь с ценами для всех инструментов
dict___with_prices_for_all_instruments = read_all_files_with_prices(work_catalog, instruments)
# демонстрация актуальности котировок,
# поскольку сейчас выходной, то последний отсчёт времени в файлах данных не совпадает с текущим, не суть
for instrument in instruments:
if dict___with_prices_for_all_instruments[instrument]['is_data']:
str1 = 'Последний отсчёт в файле с ценами для {}: {}'
print(str1.format(instrument, str(int(dict___with_prices_for_all_instruments[instrument]['prices'][N-1, 0]))))
# завершение соединения с MetaTrader5
terminal_done()
# определение параметров ожидания до следующего выполнения тела цикла
dt_start = date_time.now()
dt_write = dt_stamp_from_M5_view(dt_start.M5_view) + dt.timedelta(minutes=5, seconds=10)
timedelta_sleep = dt_write - dt_start
print(date_time.now().nice_view + ' - засыпаю до {}\n\n\n\n\n'.format(dt_write.nice_view))
time.sleep(timedelta_sleep.seconds)
if __name__ == '__main__':
main(N)
Aber es kann kopiert und in der IDE geöffnet werden, während das Bild manuell eingegeben werden kann...
Ich glaube nicht, dass sich jemand die Mühe machen wird, den Code zu kopieren und einzufügen... niemand braucht ihn hier
zu lesen und zu diskutieren, ja. Heben Sie etwas Kurioses auf oder geben Sie Hinweise. Und ich glaube nicht, dass ich es im IDE mit mir herumschleppen werde. Die Leute veröffentlichen im Forum, damit andere sie lesen können, und um den Code zu verwenden, hängen sie ihn entweder an oder verlinken ihn mit dem Repository (oder kombinieren beides).
Ich werde mir eine einfache, dumme Logik einfallen lassen, etwa so:
Für jedes Instrument wird der SMA mit einem Abstand von z=100 zwischen den Stichproben berechnet, d.h. ein SMA der Größenordnung s=1+2*z=201.
Wenn es keine Geschäfte auf dem Markt gibt oder deren Menge (für ein bestimmtes Symbol) geringer ist als die zulässige Menge (getrennt für Verkauf und Kauf)
wenn der Preis derzeit 30 Pips oder mehr über dem SMA(201) liegt - eröffnen Sie ein Verkaufsgeschäft mit SL=TP=50 Pips,
wenn der Kurs derzeit 30 Pips oder mehr unter dem SMA(201) liegt - eröffnen Sie einen Kaufhandel mit SL=TP=50 Pips.
Wenn der Gewinn zu irgendeinem Zeitpunkt 20 Pips erreicht - schließen Sie den Handel, ohne auf die Schließung durch SL oder TP zu warten.
Lassen Sie uns einen solchen Handel als Beispiel durchführen. Einfach, dumm, vom Standpunkt des Handels aus gesehen, aber der Kern der Sache ist die Umsetzung.
Wenn Sie kein Benutzerkonto haben, registrieren Sie sich
Erlauben Sie die Verwendung von Cookies, um sich auf der Website MQL5.com anzumelden.
Bitte aktivieren Sie die notwendige Einstellung in Ihrem Browser, da Sie sich sonst nicht einloggen können.
Sie sind angemeldet. Die Zwei-Faktor-Authentifizierung wurde deaktiviert. Richten Sie sie erneut ein und scannen Sie einen neuen QR-Code oder fahren Sie mit deaktivierter Zwei-Faktor-Authentifizierung fort.
Mein Punkt ist, dass die Integration von Python mit MT5 nicht vollständig ist. Sie können Indikatorwerte nicht DIREKT abrufen
Daten in Python einlesen
Die Ziele des Themas sind so einfach wie fünf Pfennige: Jeder soll mit dem algorithmischen Handel in Python beginnen können, indem er einfach ein paar Codes kopiert, wie z. B. die Initialisierung der Kommunikation mit dem Terminal, das Anfordern von Kursen, die Aufforderung an den Server, einen Handel zu eröffnen oder zu schließen, usw. usw. Konzentrieren Sie sich ausschließlich auf die Logik, und zwar in einer extrem einfach zu verwendenden Sprache.
Genau... Die Logik ist genau das, was dem algorithmischen Handel fehlt - die Logik, die man braucht, um eine Handelsstrategie zu testen, bevor "alle anderen" Teile des Codes einfügen und in den echten Handel einsteigen
viel Glück bei der Verwirklichung Ihrer "nicht-mythischen" Ziele
)))
Wer keine in Dateien gespeicherten Preise benötigt, wird den Code ein wenig umschreiben und nicht "in Dateien schreiben - aus Dateien lesen", sondern nur die gewünschte Datenstruktur verwenden. Es ist im Wesentlichen nur ein Schaufenster für primitive Dinge, für diejenigen, die bereit sind, die ersten Schritte zu machen.
Diejenigen, die bereits mit Konzepten wie Listen, Tupeln, Wörterbüchern usw. vertraut sind.
Ich schlage vor, die Preisdateien mit der Funktion read_all_files_with_prices zu lesen, die die Funktion read_file_with_prices auslöst, um die Preisdatei jedes Instruments zu lesen.Die Funktion read_file_with_prices gibt entweder ein Array numpy.ndarray mit Zeilen und Spalten zurück, die der ursprünglichen Preisdatei entsprechen (wenn die Preise erfolgreich gelesen und auf Datenintegrität geprüft wurden, ist jedes Element vom Typ numpy.float64), oder die Zeichenkette "no data", wenn keine oder unvollständige Daten gelesen wurden .
Die Funktion read_all_files_with_prices soll ein Wörterbuch mit Kursen für alle Instrumente zurückgeben. Angenommen, die Schlüssel in diesem Wörterbuch sind die Namen der Instrumente und die Werte sind die Wörterbücher mit Anführungszeichen eines entsprechenden Instruments. In den Wörterbüchern mit Anführungszeichen für ein Symbol sind die Schlüssel Datum_Zeit, die Werte sind Balken (Klasse bar); außerdem schlage ich vor, die Schlüssel :
is_data": Schlüsselwert - True, wenn ein Zitat vorhanden ist, False - wenn beim Lesen aus der Datei "keine Daten" zurückgegeben wurden,
Instrument": Schlüsselwert - Instrument (str);
Preise": Schlüsselwert - Array der Preise nach Instrument (numpy.ndarray)
Kurz gesagt, dies ist die von mir vorgeschlagene Datenstruktur:
Python-Code lässt sich besser als Screenshot aus der IDE/dem Editor/der Website platzieren.
Das Fehlen von Hervorhebungen, zumindest von Code-Kommentaren, macht sie schlecht lesbar, sie verschmelzen mit dem Haupttext.
Funktionen zum Lesen von Dateien und zum Erstellen der oben genannten Datenstruktur hinzugefügt:
Python-Code lässt sich besser als Screenshot aus der IDE/dem Editor/der Website platzieren.
Das lokale Fehlen von Hervorhebungen, zumindest für Code-Kommentare, macht sie schlecht lesbar, sie verschmelzen mit dem Haupttext.
Aber es kann kopiert und in IDE geöffnet werden, aber aus dem Bild kann es manuell neu eingegeben werden, außer...
Die Arbeit des oben gezeigten Programms:
Im Grunde ist fast alles bereit, um mit der Analyse von Daten und dem Treffen und Ausführen von Handelsentscheidungen zu beginnen.
Aber es kann kopiert und in der IDE geöffnet werden, während das Bild manuell eingegeben werden kann...
Ich glaube nicht, dass sich jemand die Mühe machen wird, den Code zu kopieren und einzufügen... niemand braucht ihn hier
zu lesen und zu diskutieren, ja. Heben Sie etwas Kurioses auf oder geben Sie Hinweise. Und ich glaube nicht, dass ich es im IDE mit mir herumschleppen werde. Die Leute veröffentlichen im Forum, damit andere sie lesen können, und um den Code zu verwenden, hängen sie ihn entweder an oder verlinken ihn mit dem Repository (oder kombinieren beides).
Aber das ist störend.
Fügen Sie den folgenden Code in die Datei Functions.py ein, eine Funktion, die den SMA berechnet
Ich benötige die Parameter d und k, um eine Zeitverschiebung durchzuführen, nicht den Punkt, wir setzen sie auf Nullen.
Ich werde mir eine einfache, dumme Logik einfallen lassen, etwa so:
Für jedes Instrument wird der SMA mit einem Abstand von z=100 zwischen den Stichproben berechnet, d.h. ein SMA der Größenordnung s=1+2*z=201.
Wenn es keine Geschäfte auf dem Markt gibt oder deren Menge (für ein bestimmtes Symbol) geringer ist als die zulässige Menge (getrennt für Verkauf und Kauf)
wenn der Preis derzeit 30 Pips oder mehr über dem SMA(201) liegt - eröffnen Sie ein Verkaufsgeschäft mit SL=TP=50 Pips,
wenn der Kurs derzeit 30 Pips oder mehr unter dem SMA(201) liegt - eröffnen Sie einen Kaufhandel mit SL=TP=50 Pips.
Wenn der Gewinn zu irgendeinem Zeitpunkt 20 Pips erreicht - schließen Sie den Handel, ohne auf die Schließung durch SL oder TP zu warten.
Lassen Sie uns einen solchen Handel als Beispiel durchführen. Einfach, dumm, vom Standpunkt des Handels aus gesehen, aber der Kern der Sache ist die Umsetzung.
Ich schlage solche Funktionen für die Eröffnung und Schließung von Geschäften vor: