Você está perdendo oportunidades de negociação:
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Registro
Login
Você concorda com a política do site e com os termos de uso
Se você não tem uma conta, por favor registre-se
Vou apoiar o início do tópico, pedi emprestado mql muitas vezes como 4 e 5, e vou dizer que pessoalmente tenho pouco desejo de aprender a língua que só posso usar aqui no comércio ...
Bem, ou isso é em vão ou porque você não entende o problema. Você vai realmente escrever os algoritmos indicadores novamente? É como chegar de Volgograd a Moscou via Vladivostok. Mais uma coisa, todos os indicadores levam em conta o histórico. Ou seja, se você pegar os dados (barras) durante um mês, calcular o indicador de acordo com seu algoritmo e compará-lo com o Terminal, seus cálculos serão diferentes.
Eu também não entendo a frase:
Com base no que escrevi, acontece que existe uma grande camada de conhecimento de Python :) Você abre um editor e já conhece python - é tão fácil, e abre mql e você não sabe nada.
Ao mesmo tempo, para chamar o mql, queé completamente orientado para plataformas, uma ferramenta "obsoleta" ... python foi criada em 1991 e isto é muito anterior
O que eu vi neste fio, escrito em píton, é muito fácil de implementar em mql
---
Bem, é interessante como uma idéia geral, mas não mais.
Além disso, ele não tira vantagens da Python e não é "estilo Python". É como martelar pregos com uma chave de fenda, o martelo é antiquado.
Eu suspeito que a única louça em sua casa é uma colher - você pode fazer uma sopa ou um bolo e é mais seguro de usar
)))
Se você gosta, use Python, mas não como o iniciador do tópico - não crie seus próprios tipos de dados personalizados - barras e assim por diante, não escreva seus próprios cálculos ... e use as soluções existentes, caso contrário não adianta usar esta linguagem, você também pode escrever seus próprios pacotes de rede neural ;)
Sim) A propósito, não há bíblia em Python para tais funções quase comerciais, ou se você puder escrever a análise estatística completa de uma série em algumas linhas, você não precisa de MA)...
Sim) A propósito, não há nenhuma biblioteca Python para todos os tipos de funções quase comerciais, ou se você puder escrever uma análise estatística completa de uma série em algumas linhas, então o MA não é mais necessário)...
As Melhores 101 bibliotecas Python algorítmicas de comercialização | PythonRepo
Não foi possível voltar ao fórum ontem. Eu vou continuar. Iniciei uma nova conta demo, e nela estão os nomes dos instrumentos sem '_i' no final, então corrigi o código nesta parte.
Vou continuar o movimento gradual e lento, uma espécie de micro-tutorial, para quem possa vir a calhar.
Vamos introduzir uma variável n (pequena) - seja, por assim dizer, o comprimento da janela. Ou seja, em arquivos com preços, N leituras, por exemplo, 1000, en, vamos definir, por exemplo, 10, ou 100, ou 288 (um dia, se o prazo for M5).
A variável d para mim significa a mudança desta janela no tempo, para o passado. Vamos definir d = 0.
Por exemplo, exibiremos 10 leituras de preços de fechamento e SMA da ordem de 101 (atrasado em 50 intervalos entre as leituras):
Resultado do trabalho:
Vamos aprender a interrogar o terminal sobre os negócios atuais no mercado, por assim dizer, para os instrumentos.
Vou apresentar a função
def buy_or_sell_opredelitel(position): try: tp = position.tp sl = position.sl if tp > sl: return 'buy' elif sl > tp: return 'sell' else: return None except: return None def Nsell_Nbuy_calculator(current_positions): ''' Функция принимает перечень открытых позиций. Функция возвращает кортеж (Nsell, Nbuy) с количествами позиций sell и buy, соответственно ''' Nsell = 0 Nbuy = 0 if len(current_positions) == 0: return (Nsell, Nbuy) else: for position in current_positions: if buy_or_sell_opredelitel(position) == 'sell': Nsell += 1 elif buy_or_sell_opredelitel(position) == 'buy': Nbuy += 1 return (Nsell, Nbuy)Deixe ele pegar a lista de posições abertas do símbolo e devolver o tuple(o número de negócios a vender, o número de negócios a comprar).
Na função principal adicione este fragmento antes da função terminal_done()
# запрос открытых сделок по инструменту for instrument in instruments: current_positions_for_instrument = mt5.positions_get(symbol = instrument) Nsell_Nbuy = Nsell_Nbuy_calculator(current_positions_for_instrument) print(date_time.now().nice_view, ' - по {} открытых сделок sell {}, открытых сделок buy {}'.format(instrument, Nsell_Nbuy[0], Nsell_Nbuy[1]))O resultado (n é reduzido a 5 por causa da produção):
Proponho iniciar a abertura real dos negócios. Por exemplo: se o preço for superior ao SMA por alguns: abrir um comércio de venda, se for inferior ao SMA por alguns: abrir um comércio de compra.
Sugiro mais algumas funções: controlar os negócios abertos em termos de SL e TP, fechá-los se estiverem ausentes, e uma função que retorna o resultado atual (lucro ou perda) em pips.
Temos que nos lembrar de lidar de alguma forma com a situação quando a ordem já está na história e não está na posição ativa, e não reenviar a ordem de abertura neste caso.
Esta situação acontece de tempos em tempos e, por exemplo, trabalhar através do Trade.mqh não resolve este problema (pelo menos, não resolvia antes - eu desisti do Trade.mqh há muito tempo).
Às vezes é o contrário - a ordem de fechamento já está na história e a posição ainda é visível.
Temos que nos lembrar de lidar de alguma forma com a situação quando a ordem já está na história e não está na posição ativa, e não reenviar a ordem de abertura neste caso.
Esta situação acontece de tempos em tempos e, por exemplo, trabalhar através do Trade.mqh não resolve este problema (pelo menos, não resolvia antes - eu desisti do Trade.mqh há muito tempo).
Às vezes é vice-versa - a ordem de fechamento já está na história e a posição ainda é visível.
Mostrei como interrogar o terminal em relação às posições em aberto. Nada nos impede de escrever o código de tal forma que, se a posição já existe, não precisaríamos reenviar o pedido, se não - nós o faremos. Especialmente, que após enviar um pedido, o objeto é devolvido, que tem tudo em suas propriedades, podemos ver se ele é normal, ou que tipo de erro está presente, e com base neste ato. Aqui não há nenhum problema.
As Melhores 101 bibliotecas Python algorítmicas de comercialização | PythonRepo
Já está 104) Aqui está escrito 105)
Código completo do arquivo TradeLogic.py até agora (sim, é primitivo, mas tenho certeza de que pode abrir a porta para o comércio usando Metatrader 5 e Python para alguns)
import os, time import datetime as 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 = 5 d = 0 price_SMA_razn_Level = 10 # модуль разности между ценой и SMA, при превышении этого порога открываем сделку N_sd_sell_max = 2 # максимальное количество сделок типа sell по одному инструменту N_sd_buy_max = 2 # максимальное количество сделок типа buy по одному инструменту SL = 50; TP = 50 # уровни SL и TP, в пипсах volume = 0.01 # объём сделок account_demo = ['Alpari-MT5-Demo', 51056680, 'pxav2sxs'] work_account = account_demo work_catalog = 'Z:\\fx_for_forum\\fx\\' instruments = ['EURUSD', 'GBPUSD', 'EURGBP', 'USDCHF', 'USDCAD', 'USDJPY'] 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', 'GBPUSD', 'EURGBP', 'USDCHF', 'USDCAD']: return 0.0001 elif instrument in ['USDJPY']: return 0.01 else: 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 open_trade(buy_or_sell, instr, volume, price_in, price_sl, price_tp, w, deviation_in_pips): ''' Функция осуществляет проверку: не ушёл ли текущий уровень цены от ожидаемого уровня price_in, и если всё хорошо, совершает открытие сделки ''' dopustimaya_delta_ot_price_in_in_pips = 5 if buy_or_sell == 'buy': trade_type = mt5.ORDER_TYPE_BUY price = mt5.symbol_info_tick(instr).ask comment = 'buy via Python' elif buy_or_sell == 'sell': trade_type = mt5.ORDER_TYPE_SELL price = mt5.symbol_info_tick(instr).bid comment = 'sell via Python' if abs((price - price_in)/w) < dopustimaya_delta_ot_price_in_in_pips: trade_request = {'action': mt5.TRADE_ACTION_DEAL, 'symbol': instr, 'volume': volume, 'type': trade_type, 'price': price, 'sl': price_sl, 'tp': price_tp, 'deviation': deviation_in_pips*10, 'magic': 12345, 'comment': comment, 'type_time': mt5.ORDER_TIME_GTC, 'type_filling': mt5.ORDER_FILLING_FOK} # отправление торгового запроса на сервер result = mt5.order_send(trade_request) # print(result) if result.comment == 'Request executed': if buy_or_sell == 'buy': print(date_time.now().nice_view, ' - сделка на покупку {} открыта'.format(instr)) elif buy_or_sell == 'sell': print(date_time.now().nice_view, ' - сделка на продажу {} открыта'.format(instr)) else: if buy_or_sell == 'buy': print(date_time.now().nice_view, ' - сделку на покупку {} открыть не удалось'.format(instr)) elif buy_or_sell == 'sell': print(date_time.now().nice_view, ' - сделку на продажу {} открыть не удалось'.format(instr)) return result else: print(date_time.now().nice_view, ' - цена ушла от ожидаемой >5 пипс, сделку по {} не открываю'.format(instr)) return None def close_trade(position): ''' Функция осуществляет закрытие сделки ''' instr = position.symbol if position.tp > position.sl: # buy trade_type = mt5.ORDER_TYPE_SELL # если позиция buy, то для её закрытия нужно sell price = mt5.symbol_info_tick(instr).bid elif position.sl > position.tp: # sell trade_type = mt5.ORDER_TYPE_BUY # если позиция sell, то для её закрытия нужно buy price = mt5.symbol_info_tick(instr).ask position_id = position.ticket volume = position.volume trade_request = {'action': mt5.TRADE_ACTION_DEAL, 'symbol': instr, 'volume': volume, 'type': trade_type, 'position': position_id, 'price': price, #'deviation': deviation_in_pips*10, 'magic': position.magic, 'comment': 'close via python', 'type_time': mt5.ORDER_TIME_GTC, 'type_filling': mt5.ORDER_FILLING_FOK} # отправление торгового запроса на сервер result = mt5.order_send(trade_request) if result.comment == 'Request executed': print(date_time.now().nice_view, ' - сделка {} по {} закрыта'.format(position_id, instr)) return result def buy_or_sell_opredelitel(position): try: tp = position.tp sl = position.sl if tp > sl: return 'buy' elif sl > tp: return 'sell' else: return None except: return None def Nsell_Nbuy_calculator(current_positions): ''' Функция принимает перечень открытых позиций. Функция возвращает кортеж (Nsell, Nbuy) с количествами позиций sell и buy, соответственно ''' Nsell = 0 Nbuy = 0 if len(current_positions) == 0: return (Nsell, Nbuy) else: for position in current_positions: if buy_or_sell_opredelitel(position) == 'sell': Nsell += 1 elif buy_or_sell_opredelitel(position) == 'buy': Nbuy += 1 return (Nsell, Nbuy) def SL_TP_control(instrument, current_positions): ''' Функция принимает перечень открытых позиций. Функция осуществляет контроль выставленности SL и TP у открытых позиций, в случае обнаружения сделки без SL или TP - закрывает (пытается закрыть) все сделки из полученного перечня. ''' Nsell_Nbuy = Nsell_Nbuy_calculator(current_positions) if Nsell_Nbuy[0] > 0 or Nsell_Nbuy[1] > 0: print(date_time.now().nice_view, ' - осуществляю проверку выставленности TP и SL у открытых сделок по {}'.format(instrument)) print(date_time.now().nice_view, ' - открытых сделок sell {}, открытых сделок buy {}'.format(Nsell_Nbuy[0], Nsell_Nbuy[1])) s = 0 for i in range(len(current_positions)): try: if current_positions[i].tp > current_positions[i].sl or current_positions[i].sl > current_positions[i].tp: s += 1 except: print(date_time.now().nice_view, ' - обнаружена сделка по {} с отсутствующим SL или TP - закрываю!'.format(instrument)) close_trade(current_positions[i]) time.sleep(0.5) if s == len(current_positions): print(date_time.now().nice_view, ' - выставленность TP и SL у открытых сделок по {} - OK'.format(instrument)) def profit_calculator(instrument, position): ''' Функция принимает позицию, и возвращает текущий результат, в пипсах. ''' w = pips_definer(instrument) buy_sell = buy_or_sell_opredelitel(position) if buy_sell == 'sell': bs = -1 elif buy_sell == 'buy': bs = 1 if buy_sell == 'buy' or buy_sell == 'sell': profit_in_pips = round((position.price_current - position.price_open)/w, 1)*bs return profit_in_pips return None 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) # вычислим значения последних n отсчётов цен закрытия баров, и SMA101, вычисленной по ценам закрытия баров, # если цена выше SMA на price_SMA_razn_Level, в пипсах, и открытых сделок на продажу по этому инструменту меньше, # чем N_sd_sell_max, то открываем сделку на продажу, # если цена ниже SMA на price_SMA_razn_Level, в пипсах, и открытых сделок на покупку по этому инструменту меньше, # чем N_sd_buy_max, то открываем сделку на покупку. for instrument in instruments: dict___with_prices_for_instrument = dict___with_prices_for_all_instruments[instrument] current_positions_for_instrument = mt5.positions_get(symbol = instrument) Nsell_Nbuy = Nsell_Nbuy_calculator(current_positions_for_instrument) if dict___with_prices_for_instrument['is_data']: w = pips_definer(instrument) # величина пипса для инструмента tochn = int(abs(np.log10(w))+1) AData = dict___with_prices_for_instrument['prices'] Ax_close = AData[:, 4] # столбец отсчётов цен закрытия в N строк A_close = Ax_close[Ax_close.size-n-d:Ax_close.size-d] # столбец отсчётов цен закрытия в n строк z = 50 # параметр, задающий запаздывание скользящей средней, для z=50 скользящая средняя по 1+2*50=101 отсчёту A_close_s = Functions.SMA(Ax_close, 1+2*z, 0, n, d) price_SMA_razn_for_instrument = round((A_close[n-1] - A_close_s[n-1])/w, 1) print('\n') str1 = ' - для {} крайние справа отсчёты цены {}, SMA {}, разность {} пипс' print(date_time.now().nice_view, str1.format(instrument, A_close[n-1], round(A_close_s[n-1], tochn), price_SMA_razn_for_instrument)) if abs(price_SMA_razn_for_instrument) < price_SMA_razn_Level: print(date_time.now().nice_view, ' - разность с SMA не превышает порога {} пипс, ничего не делаю'.format(price_SMA_razn_Level)) elif abs(price_SMA_razn_for_instrument) > price_SMA_razn_Level: if price_SMA_razn_for_instrument > price_SMA_razn_Level and Nsell_Nbuy[0] < N_sd_sell_max: print(date_time.now().nice_view, ' - разность с SMA превышает порог {} пипс, продаю {}'.format(price_SMA_razn_Level, instrument)) open_trade('sell', instrument, volume, A_close[n-1], A_close[n-1]+SL*w, A_close[n-1]-TP*w, w, 2) time.sleep(1) if price_SMA_razn_for_instrument < -price_SMA_razn_Level and Nsell_Nbuy[1] < N_sd_buy_max: print(date_time.now().nice_view, ' - разность с SMA превышает порог {} пипс, покупаю {}'.format(price_SMA_razn_Level, instrument)) open_trade('buy', instrument, volume, A_close[n-1], A_close[n-1]-SL*w, A_close[n-1]+TP*w, w, 2) time.sleep(1) # запрос открытых сделок по инструменту print('\n') for instrument in instruments: current_positions_for_instrument = mt5.positions_get(symbol = instrument) Nsell_Nbuy = Nsell_Nbuy_calculator(current_positions_for_instrument) print(date_time.now().nice_view, ' - по {} открытых сделок sell {}, открытых сделок buy {}'.format(instrument, Nsell_Nbuy[0], Nsell_Nbuy[1])) # завершение соединения с 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)Resultado do trabalho:
Z.I.Y. As peças de código mais primitivas, elementares, mostradas, em minha opinião, já demonstram muito claramente que não é difícil implementar absolutamente nenhuma lógica, quaisquer cálculos, comparações, controle de negócios abertos por vários critérios, fechando-os automaticamente sob algumas condições, mantendo registros tanto na linha de comando como por escrito em arquivos, etc., etc. - qualquer coisa sem qualquer restrição.
Z.U.2 Até agora, a classe Sdelka era usada, e em geral é conveniente passar os objetos desta classe em funções, escrevê-los em arquivos como .json, etc., - mas de alguma forma ficou um pouco cansado, acho que aqueles que querem entender, eu posso ajudar aqui com algo. Se você quiser, você pode parafusar uma interface gráfica.
Recomendo vivamente o comércio com a biblioteca Python + metatrader5.
Eu mostrei como sondar o terminal para posições abertas. Não há nada que o impeça de escrever o código para que, se já houver uma posição, não seja necessário reenviar o pedido, se não - enviá-lo. Especialmente, que após o envio de um pedido, o objeto é devolvido, que tem tudo em suas propriedades, podemos ver se ele abriu normalmente ou se há um erro, e com base neste ato. Aqui não há problemas.
Mais uma vez, a ordem já foi executada e passada para a história. Ela não está mais na posição ativa. A posição já foi aberta, mas ainda não é visível; o pedido não a mostra.
Normalmente, este é um intervalo de tempo muito curto e é difícil alcançá-lo, especialmente porque nem sempre é o caso.
Entretanto, esta situação pode não durar nem mesmo segundos, mas minutos em uma abertura matinal com um intervalo e uma grande quantidade de pedidos.
Para tornar mais claro: TRADE_TRANSACTION_ORDER_DELETE veio mais cedo que TRADE_TRANSACTION_HISTORY_ADD ou TRADE_TRANSACTION_DEAL_ADD
E podemos não ver ordens em atividade ou histórico em algum momento, ou podemos não ver nenhuma ordem ou negociação.