Il mio punto è che l'integrazione di python con MT5 non è completa. Non è possibile ottenere i valori dell'indicatore DIRETTAMENTE
Salvare i dati 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);
Gli obiettivi dell'argomento sono semplici come cinque centesimi: permettere a chiunque di iniziare il trading algoritmico in Python, semplicemente copiando pezzi di codice come inizializzare la comunicazione con il terminale, richiedere quotazioni, chiedere al server di aprire o chiudere un trade, ecc. Si concentra solo sulla logica, e in un linguaggio estremamente facile da usare.
Giusto... La logica è esattamente ciò che manca al trading algoritmico - la logica di cui avete bisogno per testare una strategia di trading prima che "all comers" inserisca pezzi di codice ed entri nel trading reale
buona fortuna con i tuoi obiettivi "non mitici" comunque
Le persone che non hanno bisogno di prezzi salvati su file riscriveranno un po' il codice, e non "scrivere su file - leggere da file", ma solo la struttura dei dati che vogliono. È in gran parte solo una vetrina di cose primitive, per chi è disposto a fare i primi passi.
Tuttavia, coloro che hanno già familiarità con concetti come liste, tuple, dizionari, ecc.
Propongo di leggere dai file dei prezzi con la funzione read_all_files_with_prices, che attiverà la funzione read_file_with_prices per leggere il file dei prezzi di ogni strumento.
Lascia che la funzione read_file_with_prices restituisca un array numpy.ndarray con righe e colonne corrispondenti al file originale dei prezzi (se i prezzi sono stati letti con successo e controllati per l'integrità dei dati, ogni tipo di elemento è numpy.float64), o la stringa 'no data' se nessun dato è stato letto o incompleto .
Che la funzione read_all_files_with_prices restituisca un dizionario con le quotazioni di tutti gli strumenti. Supponiamo che le chiavi di questo dizionario siano i nomi degli strumenti e i valori siano i dizionari con le virgolette di uno strumento corrispondente. Nei dizionari con le virgolette per un simbolo le chiavi sono date_time, i valori sono barre (classe bar); inoltre, suggerisco di fornire chiavi :
'is_data': valore chiave - True se c'è una citazione, False - se la lettura dal file restituisce 'no data',
'instrument': valore chiave - instrument (str);
'prices': key-value - array di prezzi per lo strumento (numpy.ndarray)
In breve, questa è la struttura dei dati che suggerisco:
Aggiunte funzioni per leggere i file e creare la suddetta struttura di dati:
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)
Ma può essere copiato e aperto nell'IDE, mentre l'immagine può essere riscritta solo a mano...
Non credo che qualcuno si prenderà la briga di copiare e incollare il codice... nessuno ne ha bisogno qui
per leggere e discutere, sì. Raccogliete qualcosa di curioso o date qualche suggerimento. E non credo che lo porterò in giro in IDE. Le persone pubblicano sul forum per la lettura da parte di altri e per l'utilizzo del codice o lo allegano o il link al repository (o li combinano).
Mi viene in mente una semplice logica stupida, tipo:
per ogni strumento calcoliamo la SMA in ritardo di z=100 intervalli tra i campioni, cioè la SMA dell'ordine s=1+2*z=201.
Se non ci sono compravendite nel mercato o la loro quantità (per un certo simbolo) è inferiore alla quantità ammissibile (separatamente per Vendere e Comprare)
se il prezzo è attualmente 30 pip o più sopra la SMA(201) - aprire un'operazione di vendita con SL=TP=50 pip,
se il prezzo è attualmente 30 pip o più sotto la SMA(201) - aprire un trade Buy con SL=TP=50 pip.
Se in qualsiasi momento il profitto sul trade raggiunge i 20 pip - chiudilo senza aspettare la chiusura di SL o TP.
Implementiamo un tale commercio come esempio. Semplice, sciocco, dal punto di vista del trading, ma l'essenza della questione è l'implementazione.
Il mio punto è che l'integrazione di python con MT5 non è completa. Non è possibile ottenere i valori dell'indicatore DIRETTAMENTE
Leggere i dati in python
Gli obiettivi dell'argomento sono semplici come cinque centesimi: permettere a chiunque di iniziare il trading algoritmico in Python, semplicemente copiando pezzi di codice come inizializzare la comunicazione con il terminale, richiedere quotazioni, chiedere al server di aprire o chiudere un trade, ecc. Si concentra solo sulla logica, e in un linguaggio estremamente facile da usare.
Giusto... La logica è esattamente ciò che manca al trading algoritmico - la logica di cui avete bisogno per testare una strategia di trading prima che "all comers" inserisca pezzi di codice ed entri nel trading reale
buona fortuna con i tuoi obiettivi "non mitici" comunque
)))
Le persone che non hanno bisogno di prezzi salvati su file riscriveranno un po' il codice, e non "scrivere su file - leggere da file", ma solo la struttura dei dati che vogliono. È in gran parte solo una vetrina di cose primitive, per chi è disposto a fare i primi passi.
Tuttavia, coloro che hanno già familiarità con concetti come liste, tuple, dizionari, ecc.
Propongo di leggere dai file dei prezzi con la funzione read_all_files_with_prices, che attiverà la funzione read_file_with_prices per leggere il file dei prezzi di ogni strumento.Lascia che la funzione read_file_with_prices restituisca un array numpy.ndarray con righe e colonne corrispondenti al file originale dei prezzi (se i prezzi sono stati letti con successo e controllati per l'integrità dei dati, ogni tipo di elemento è numpy.float64), o la stringa 'no data' se nessun dato è stato letto o incompleto .
Che la funzione read_all_files_with_prices restituisca un dizionario con le quotazioni di tutti gli strumenti. Supponiamo che le chiavi di questo dizionario siano i nomi degli strumenti e i valori siano i dizionari con le virgolette di uno strumento corrispondente. Nei dizionari con le virgolette per un simbolo le chiavi sono date_time, i valori sono barre (classe bar); inoltre, suggerisco di fornire chiavi :
'is_data': valore chiave - True se c'è una citazione, False - se la lettura dal file restituisce 'no data',
'instrument': valore chiave - instrument (str);
'prices': key-value - array di prezzi per lo strumento (numpy.ndarray)
In breve, questa è la struttura dei dati che suggerisco:
Il codice Python è meglio messo come screenshot dall'IDE/editor/sito.
La mancanza di evidenziazione locale, almeno dei commenti al codice, lo rende poco leggibile, si confonde con il testo principale.
Aggiunte funzioni per leggere i file e creare la suddetta struttura di dati:
Il codice Python è meglio messo come screenshot dall'IDE/editor/sito.
La mancanza di evidenziazione locale, almeno per i commenti al codice, lo rende poco leggibile, si confonde con il testo principale.
Ma può essere copiato e aperto nell'IDE, ma dall'immagine può essere riscritto manualmente tranne...
Il lavoro del programma mostrato sopra:
Fondamentalmente, quasi tutto è pronto per iniziare ad analizzare i dati e prendere ed eseguire decisioni di trading.
Ma può essere copiato e aperto nell'IDE, mentre l'immagine può essere riscritta solo a mano...
Non credo che qualcuno si prenderà la briga di copiare e incollare il codice... nessuno ne ha bisogno qui
per leggere e discutere, sì. Raccogliete qualcosa di curioso o date qualche suggerimento. E non credo che lo porterò in giro in IDE. Le persone pubblicano sul forum per la lettura da parte di altri e per l'utilizzo del codice o lo allegano o il link al repository (o li combinano).
Ma questo mi distrae.
Metti il seguente codice nel file Functions.py, una funzione che calcola la SMA
Ho bisogno dei parametri d e k per eseguire uno spostamento temporale, non il punto, li metteremo a zero.
Mi viene in mente una semplice logica stupida, tipo:
per ogni strumento calcoliamo la SMA in ritardo di z=100 intervalli tra i campioni, cioè la SMA dell'ordine s=1+2*z=201.
Se non ci sono compravendite nel mercato o la loro quantità (per un certo simbolo) è inferiore alla quantità ammissibile (separatamente per Vendere e Comprare)
se il prezzo è attualmente 30 pip o più sopra la SMA(201) - aprire un'operazione di vendita con SL=TP=50 pip,
se il prezzo è attualmente 30 pip o più sotto la SMA(201) - aprire un trade Buy con SL=TP=50 pip.
Se in qualsiasi momento il profitto sul trade raggiunge i 20 pip - chiudilo senza aspettare la chiusura di SL o TP.
Implementiamo un tale commercio come esempio. Semplice, sciocco, dal punto di vista del trading, ma l'essenza della questione è l'implementazione.
Suggerisco tali funzioni per l'apertura e la chiusura delle transazioni: