From 6efc5e0022e1f363dd4550304ad5faf35f8a5ddb Mon Sep 17 00:00:00 2001 From: New Nick Date: Sun, 30 May 2021 09:38:43 +0700 Subject: [PATCH 01/22] deleted: pyFinance.py file --- broker_manager_gui.py | 108 ++++++++++++------ broker_manager_gui_luzin_config.json | 4 + broker_manager_gui_nick_config.json | 4 + pyFinance_v3_ref.py => pyFinance_v1_quotex.py | 35 +++--- 4 files changed, 98 insertions(+), 53 deletions(-) rename pyFinance_v3_ref.py => pyFinance_v1_quotex.py (81%) diff --git a/broker_manager_gui.py b/broker_manager_gui.py index 633e501..5026c62 100644 --- a/broker_manager_gui.py +++ b/broker_manager_gui.py @@ -14,7 +14,7 @@ class BrokerManagerGui(BrokerManagerInterface): - TRY_COUNT = 3 + TRY_COUNT = 10 def __init__(self, result_handler, config_file): super().__init__(result_handler) @@ -60,7 +60,7 @@ def _get_deal_result(self): pyperclip.copy("") # <- Это предотвращает замену последней копии текущей копией null. pyautogui.doubleClick(self.config['fields']['result']['x'], self.config['fields']['result']['y']) pyautogui.hotkey('ctrl', 'c') - time.sleep(1) # ctrl-c обычно работает очень быстро, но ваша программа может выполняться быстрее + time.sleep(0.5) # ctrl-c обычно работает очень быстро, но ваша программа может выполняться быстрее result = pyperclip.paste() if result in ['LOSE', 'WIN']: break @@ -69,9 +69,58 @@ def _get_deal_result(self): # If result not in ['LOSE', 'WIN'] return as is self.result_handler(result) + def check_deal_summ(self, summ): + pyperclip.copy("") # <- Это предотвращает замену последней копии текущей копией null. + + pyautogui.doubleClick( + self.config['fields']['investment_money']['x'], + self.config['fields']['investment_money']['y'], + duration=0.1 + ) + time.sleep(0.5) + + pyautogui.rightClick( + self.config['fields']['investment_money']['x'], + self.config['fields']['investment_money']['y'], + duration=0.1 + ) + time.sleep(0.5) + + pyautogui.click( + self.config['fields']['copy_summ']['x'], + self.config['fields']['copy_summ']['y'], + duration=0.1 + ) + time.sleep(0.5) + + actual_summ = int(pyperclip.paste()) + if actual_summ == summ: + return True + else: + return False + + def check_deal_time(self, chtime): + pyperclip.copy("") # <- Это предотвращает замену последней копии текущей копией null. + + pyautogui.doubleClick( + self.config['fields']['expiration_time']['x'], + self.config['fields']['expiration_time']['y'], + duration=0.1 + ) + time.sleep(0.5) + + pyautogui.hotkey('ctrl', 'c') + time.sleep(0.5) # ctrl-c обычно работает очень быстро, но ваша программа может выполняться быстрее + + actual_time = int(pyperclip.paste()) + if actual_time == chtime: + return True + else: + return False + def make_deal(self, option, prognosis, summ, deal_time): if self.is_deal: - logger.info('Deal is active now, skip new deal.') + logger.info('Deal is active now, skip new deal.\n') return windows_manager.activate_window('Прозрачный брокер бинарных опционов') @@ -86,41 +135,30 @@ def make_deal(self, option, prognosis, summ, deal_time): ) time.sleep(1) pyautogui.write(str(summ), interval=0.25) + time.sleep(0.5) + if self.check_deal_summ(summ): + logger.debug('Check deal summ True') + break + else: + logger.debug('Check deal summ attempt №{} - False'.format(k)) + + for k in range(self.TRY_COUNT): + pyautogui.doubleClick( + self.config['fields']['expiration_time']['x'], + self.config['fields']['expiration_time']['y'], + duration=0.1 + ) time.sleep(1) + pyautogui.write(str(deal_time), interval=0.25) + time.sleep(0.5) + if self.check_deal_time(deal_time): + logger.debug('Check deal time True') + break + else: + logger.debug('Check deal time attempt №{} - False'.format(k)) - pyautogui.click( - self.config['fields']['expiration_time']['x'], - self.config['fields']['expiration_time']['y'], - duration=0.1 - ) - time.sleep(2) - pyautogui.click(self.exp_hour_buttons[deal_time.hour].x, self.exp_hour_buttons[deal_time.hour].y, duration=0.1) - time.sleep(2) - pyautogui.click( - self.exp_minute_buttons[deal_time.minute // 5].x, - self.exp_minute_buttons[deal_time.minute // 5].y, - duration=0.1 - ) - time.sleep(2) pyautogui.click(self.prognosis_table[prognosis].x, self.prognosis_table[prognosis].y, duration=0.1) self.is_deal = True - # Set up timer on finish job - msk_tz = pytz.timezone('Europe/Moscow') - now_date = datetime.datetime.now(msk_tz) - finish_datetime = msk_tz.localize( - datetime.datetime( - now_date.year, - now_date.month, - now_date.day, - deal_time.hour, - deal_time.minute - ) - ) - if deal_time.hour in [0, 1]: - finish_datetime += datetime.timedelta(days=1) - finish_datetime = finish_datetime.astimezone() - - logger.debug("finish_datetime={}".format(finish_datetime)) - + finish_datetime = datetime.datetime.now() + datetime.timedelta(minutes=deal_time) self.scheduler.add_job(self._get_deal_result, 'date', run_date=finish_datetime) diff --git a/broker_manager_gui_luzin_config.json b/broker_manager_gui_luzin_config.json index 1b6091f..e823c22 100644 --- a/broker_manager_gui_luzin_config.json +++ b/broker_manager_gui_luzin_config.json @@ -49,6 +49,10 @@ "result": { "x": 1330, "y": 462 + } + "copy_summ": { + "x": 903, + "y": 247 } } } diff --git a/broker_manager_gui_nick_config.json b/broker_manager_gui_nick_config.json index b3302ba..3d074cd 100644 --- a/broker_manager_gui_nick_config.json +++ b/broker_manager_gui_nick_config.json @@ -49,6 +49,10 @@ "result": { "x": 983, "y": 457 + }, + "copy_summ": { + "x": 903, + "y": 247 } } } diff --git a/pyFinance_v3_ref.py b/pyFinance_v1_quotex.py similarity index 81% rename from pyFinance_v3_ref.py rename to pyFinance_v1_quotex.py index 004efc8..ee3f07f 100644 --- a/pyFinance_v3_ref.py +++ b/pyFinance_v1_quotex.py @@ -18,7 +18,7 @@ logger = logging.getLogger('pyFinance') logger.setLevel(logging.DEBUG) -fh = logging.FileHandler(datetime.datetime.now().strftime('%Y-%m-%d.log'), 'a', 'utf-8') +fh = logging.FileHandler(datetime.datetime.now().strftime('%Y-%m-%d.log')) formatter = logging.Formatter('%(asctime)s %(message)s') fh.setFormatter(formatter) fh.setLevel(logging.DEBUG) @@ -44,7 +44,7 @@ def save_state(save_file_path): with open(save_file_path, 'w') as sav: sav.write("{} {}".format(step, init_summ)) - logger.debug("Saved to {}".format(save_file_path)) + logger.debug("Saved to {}\n".format(save_file_path)) def load_state(save_file_path): @@ -65,13 +65,13 @@ def load_state(save_file_path): def get_summ(st): - return int(init_summ * (2.2 ** (st - 1))) - + return int(init_summ * (2.3 ** (st - 1))) def parse_signal(signal_text): signal_lines = signal_text.split('\n') - if len(signal_lines) < 2: - # Ожидаем как минимум 2 строки, иначе это не сигнал + print(signal_lines) + if len(signal_lines) != 1: + # Ожидаем 1 строку, иначе это не сигнал return None option = signal_lines[0][:6] @@ -79,18 +79,17 @@ def parse_signal(signal_text): # Если не нашли известный нам опцион, значит это не сигнал return None - pattern = r'(вверх|вниз)до(\d{2}.\d{2})мск' - m = re.match(pattern, signal_lines[1].replace(' ', '').lower()) + pattern = r'[\S\D]*(вверх|вниз)на(\d+)[\S\D]*' + m = re.match(pattern, signal_lines[0].replace(' ', '').lower()) if m is None: - # Если вторая строка не соответствует шаблону, значит это не сигнал + # Если строка не соответствует шаблону, значит это не сигнал return prognosis = m.group(1) deal_time_str = m.group(2) - deal_time = datetime.datetime.strptime(deal_time_str, '%H.%M').time() + deal_time = int(deal_time_str) - 1 return option, prognosis, deal_time - def deal_result_process(result): global step @@ -100,6 +99,7 @@ def deal_result_process(result): elif result == 'WIN': step = 1 else: + step = 1 logger.error('Unknown result: {}'.format(result)) save_state(SAVE_STATE_FILE_PATH) @@ -108,7 +108,6 @@ def deal_result_process(result): def message_process(message_text, message_date, broker_manager): global step - logger.info('') logger.info('Got message') logger.debug(message_text) logger.info(message_date.strftime('Message date: %d-%m-%Y %H:%M')) @@ -116,15 +115,15 @@ def message_process(message_text, message_date, broker_manager): try: signal = parse_signal(message_text) if signal is None: - logger.info('Message is not a signal, skip.') + logger.info('Message is not a signal, skip.\n') return option, prognosis, deal_time = signal - logger.info('Получен сигнал: {opt} {prog} до {tm}'.format( + logger.info('Получен сигнал: {opt} {prog} на {tm}'.format( opt=option, prog=prognosis, - tm=deal_time.strftime('%H.%M') + tm=deal_time )) summ = get_summ(step) @@ -148,15 +147,15 @@ def main(): client = TelegramClient(number, api_id, api_hash) broker_manager = BrokerManagerGui(deal_result_process, config) - - @client.on(events.NewMessage(chats='Scrooge Club')) # создает событие, срабатывающее при появлении нового сообщения +#🔊 СИГНАЛЫ №1 🔊 + @client.on(events.NewMessage(chats='tFinace')) # создает событие, срабатывающее при появлении нового сообщения async def normal_handler(event): message = event.message.to_dict() message_process(message['message'], message['date'], broker_manager) load_state(SAVE_STATE_FILE_PATH) client.start() - logger.info('Клиент запущен, бот активен.') + logger.info('Клиент запущен, бот активен.\n') client.run_until_disconnected() From fb706542508a54c49bcd15d8b53cc0e60d1b0cdd Mon Sep 17 00:00:00 2001 From: New Nick Date: Tue, 1 Jun 2021 21:22:22 +0700 Subject: [PATCH 02/22] chenge from 01.06.2021 --- broker_manager_gui.py | 28 +++++++++------------------- broker_manager_gui_luzin_config.json | 6 +++--- pyFinance_v1_quotex.py | 9 +++++---- 3 files changed, 17 insertions(+), 26 deletions(-) diff --git a/broker_manager_gui.py b/broker_manager_gui.py index 5026c62..92e7bcb 100644 --- a/broker_manager_gui.py +++ b/broker_manager_gui.py @@ -69,7 +69,7 @@ def _get_deal_result(self): # If result not in ['LOSE', 'WIN'] return as is self.result_handler(result) - def check_deal_summ(self, summ): + def get_deal_summ(self): pyperclip.copy("") # <- Это предотвращает замену последней копии текущей копией null. pyautogui.doubleClick( @@ -92,14 +92,9 @@ def check_deal_summ(self, summ): duration=0.1 ) time.sleep(0.5) - - actual_summ = int(pyperclip.paste()) - if actual_summ == summ: - return True - else: - return False - - def check_deal_time(self, chtime): + return pyperclip.paste() + + def get_deal_time(self): pyperclip.copy("") # <- Это предотвращает замену последней копии текущей копией null. pyautogui.doubleClick( @@ -111,12 +106,7 @@ def check_deal_time(self, chtime): pyautogui.hotkey('ctrl', 'c') time.sleep(0.5) # ctrl-c обычно работает очень быстро, но ваша программа может выполняться быстрее - - actual_time = int(pyperclip.paste()) - if actual_time == chtime: - return True - else: - return False + return pyperclip.paste() def make_deal(self, option, prognosis, summ, deal_time): if self.is_deal: @@ -127,7 +117,7 @@ def make_deal(self, option, prognosis, summ, deal_time): pyautogui.click(self.option_buttons[option].x, self.option_buttons[option].y, duration=0.1) time.sleep(2) - for k in range(self.TRY_COUNT): + for k in range(BrokerManagerGui.TRY_COUNT): pyautogui.doubleClick( self.config['fields']['investment_money']['x'], self.config['fields']['investment_money']['y'], @@ -136,13 +126,13 @@ def make_deal(self, option, prognosis, summ, deal_time): time.sleep(1) pyautogui.write(str(summ), interval=0.25) time.sleep(0.5) - if self.check_deal_summ(summ): + if self.get_deal_summ() == str(summ) logger.debug('Check deal summ True') break else: logger.debug('Check deal summ attempt №{} - False'.format(k)) - for k in range(self.TRY_COUNT): + for k in range(BrokerManagerGui.TRY_COUNT): pyautogui.doubleClick( self.config['fields']['expiration_time']['x'], self.config['fields']['expiration_time']['y'], @@ -151,7 +141,7 @@ def make_deal(self, option, prognosis, summ, deal_time): time.sleep(1) pyautogui.write(str(deal_time), interval=0.25) time.sleep(0.5) - if self.check_deal_time(deal_time): + if self.get_deal_time() == str(deal_time) logger.debug('Check deal time True') break else: diff --git a/broker_manager_gui_luzin_config.json b/broker_manager_gui_luzin_config.json index e823c22..cd5dac6 100644 --- a/broker_manager_gui_luzin_config.json +++ b/broker_manager_gui_luzin_config.json @@ -49,10 +49,10 @@ "result": { "x": 1330, "y": 462 - } + }, "copy_summ": { - "x": 903, - "y": 247 + "x": 1170, + "y": 195 } } } diff --git a/pyFinance_v1_quotex.py b/pyFinance_v1_quotex.py index ee3f07f..dd0bca6 100644 --- a/pyFinance_v1_quotex.py +++ b/pyFinance_v1_quotex.py @@ -18,7 +18,7 @@ logger = logging.getLogger('pyFinance') logger.setLevel(logging.DEBUG) -fh = logging.FileHandler(datetime.datetime.now().strftime('%Y-%m-%d.log')) +fh = logging.FileHandler(datetime.datetime.now().strftime('%Y-%m-%d.log'), 'a', 'utf-8') formatter = logging.Formatter('%(asctime)s %(message)s') fh.setFormatter(formatter) fh.setLevel(logging.DEBUG) @@ -107,7 +107,8 @@ def deal_result_process(result): def message_process(message_text, message_date, broker_manager): global step - + + logger.info('') logger.info('Got message') logger.debug(message_text) logger.info(message_date.strftime('Message date: %d-%m-%Y %H:%M')) @@ -147,8 +148,8 @@ def main(): client = TelegramClient(number, api_id, api_hash) broker_manager = BrokerManagerGui(deal_result_process, config) -#🔊 СИГНАЛЫ №1 🔊 - @client.on(events.NewMessage(chats='tFinace')) # создает событие, срабатывающее при появлении нового сообщения + + @client.on(events.NewMessage(chats='🔊 СИГНАЛЫ №1 🔊')) # создает событие, срабатывающее при появлении нового сообщения async def normal_handler(event): message = event.message.to_dict() message_process(message['message'], message['date'], broker_manager) From 84cd47ff1a20c04c262d77b9113ea37840b82666 Mon Sep 17 00:00:00 2001 From: New Nick Date: Tue, 1 Jun 2021 21:30:35 +0700 Subject: [PATCH 03/22] =?UTF-8?q?chenge=20from=2001.06.2021=20=E2=84=962?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- broker_manager_gui.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/broker_manager_gui.py b/broker_manager_gui.py index 92e7bcb..0863fc5 100644 --- a/broker_manager_gui.py +++ b/broker_manager_gui.py @@ -126,7 +126,7 @@ def make_deal(self, option, prognosis, summ, deal_time): time.sleep(1) pyautogui.write(str(summ), interval=0.25) time.sleep(0.5) - if self.get_deal_summ() == str(summ) + if self.get_deal_summ() == str(summ): logger.debug('Check deal summ True') break else: @@ -141,7 +141,7 @@ def make_deal(self, option, prognosis, summ, deal_time): time.sleep(1) pyautogui.write(str(deal_time), interval=0.25) time.sleep(0.5) - if self.get_deal_time() == str(deal_time) + if self.get_deal_time() == str(deal_time): logger.debug('Check deal time True') break else: From c9fff3b96dc7e0ad1aa1a9144df527b8a597b861 Mon Sep 17 00:00:00 2001 From: New Nick Date: Fri, 4 Jun 2021 19:34:31 +0700 Subject: [PATCH 04/22] =?UTF-8?q?=D1=82=D0=B5=D0=BF=D0=B5=D1=80=D1=8C=20?= =?UTF-8?q?=D0=BE=D0=BF=D1=86=D0=B8=D0=BE=D0=BD=20=D1=82=D1=8B=D0=BA=D0=B0?= =?UTF-8?q?=D0=B5=D1=82=D1=81=D1=8F=20=D0=B4=D0=B2=D0=B0=D0=B6=D0=B4=D1=8B?= =?UTF-8?q?=20=D0=B8=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20?= =?UTF-8?q?=D1=80=D0=B0=D1=81=D1=81=D1=87=D0=B5=D1=82=20=D1=81=D1=83=D0=BC?= =?UTF-8?q?=D0=BC=20=D0=BA=D0=BE=D0=BB=D0=B5=D0=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- broker_manager_gui.py | 2 ++ limit.py | 13 +++++++++++++ pyFinance_v1_quotex.py | 3 ++- 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 limit.py diff --git a/broker_manager_gui.py b/broker_manager_gui.py index 0863fc5..dcdb2d9 100644 --- a/broker_manager_gui.py +++ b/broker_manager_gui.py @@ -116,6 +116,8 @@ def make_deal(self, option, prognosis, summ, deal_time): windows_manager.activate_window('Прозрачный брокер бинарных опционов') pyautogui.click(self.option_buttons[option].x, self.option_buttons[option].y, duration=0.1) time.sleep(2) + pyautogui.click(self.option_buttons[option].x, self.option_buttons[option].y, duration=0.1) + time.sleep(5) for k in range(BrokerManagerGui.TRY_COUNT): pyautogui.doubleClick( diff --git a/limit.py b/limit.py new file mode 100644 index 0000000..f651574 --- /dev/null +++ b/limit.py @@ -0,0 +1,13 @@ +# Python 3 + +summa = float(input('введите первоночальную сумму = ')) +k = float(input('введите коэффициент мартина = ')) +step = int(input('введите кол-во колен = ')) +i=1 +s=0 + +for i in range(step): + a = int(summa * (k ** (i))) + print('колено №{} = {}'.format(i, a)) + s = s + a +print('общая сумма = ', s) diff --git a/pyFinance_v1_quotex.py b/pyFinance_v1_quotex.py index dd0bca6..d29cdf8 100644 --- a/pyFinance_v1_quotex.py +++ b/pyFinance_v1_quotex.py @@ -38,6 +38,7 @@ telethon_logger.addHandler(tfh) + def save_state(save_file_path): global step global init_summ @@ -148,7 +149,7 @@ def main(): client = TelegramClient(number, api_id, api_hash) broker_manager = BrokerManagerGui(deal_result_process, config) - + @client.on(events.NewMessage(chats='🔊 СИГНАЛЫ №1 🔊')) # создает событие, срабатывающее при появлении нового сообщения async def normal_handler(event): message = event.message.to_dict() From f0f485ea366152ca4a766a7a4673d3f4d99159f9 Mon Sep 17 00:00:00 2001 From: New Nick Date: Sat, 5 Jun 2021 13:07:55 +0700 Subject: [PATCH 05/22] =?UTF-8?q?=D0=BB=D0=BE=D0=B3=D0=B8=20=D0=B2=20?= =?UTF-8?q?=D0=BE=D1=82=D0=B4=D0=B5=D0=BB=D1=8C=D0=BD=D0=BE=D0=B9=20=D0=BF?= =?UTF-8?q?=D0=B0=D0=BF=D0=BA=D0=B5=20=D0=B8=20=D0=BA=D0=BE=D0=BD=D1=84?= =?UTF-8?q?=D0=B8=D0=B3=20=D0=B4=D0=BE=D0=BF=D0=BE=D0=BB=D0=BD=D0=B5=D0=BD?= =?UTF-8?q?=20=D1=80=D0=B0=D0=B7=D0=B4=D0=B5=D0=BB=D0=BE=D0=BC=20context?= =?UTF-8?q?=5Fmenu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- broker_manager_gui.py | 4 ++-- broker_manager_gui_luzin_config.json | 7 ++++-- broker_manager_gui_nick_config.json | 25 +++++++++++--------- get_coord.py | 7 ++++++ pyFinance_v1_quotex.py | 34 ++++++++++++++++------------ 5 files changed, 47 insertions(+), 30 deletions(-) create mode 100644 get_coord.py diff --git a/broker_manager_gui.py b/broker_manager_gui.py index dcdb2d9..bb6ee8f 100644 --- a/broker_manager_gui.py +++ b/broker_manager_gui.py @@ -87,8 +87,8 @@ def get_deal_summ(self): time.sleep(0.5) pyautogui.click( - self.config['fields']['copy_summ']['x'], - self.config['fields']['copy_summ']['y'], + self.config['context_menu']['copy']['x'], + self.config['context_menu']['copy']['y'], duration=0.1 ) time.sleep(0.5) diff --git a/broker_manager_gui_luzin_config.json b/broker_manager_gui_luzin_config.json index cd5dac6..6df16e5 100644 --- a/broker_manager_gui_luzin_config.json +++ b/broker_manager_gui_luzin_config.json @@ -49,8 +49,11 @@ "result": { "x": 1330, "y": 462 - }, - "copy_summ": { + } + }, + + "context_menu": { + "copy": { "x": 1170, "y": 195 } diff --git a/broker_manager_gui_nick_config.json b/broker_manager_gui_nick_config.json index 3d074cd..bed8322 100644 --- a/broker_manager_gui_nick_config.json +++ b/broker_manager_gui_nick_config.json @@ -4,11 +4,11 @@ "expiration_time": { "first_hour": { "x": 585, - "y": 219 + "y": 231 }, "first_minute": { "x": 831, - "y": 219 + "y": 231 }, "delta": { "x": 39, @@ -18,7 +18,7 @@ "option": { "first": { "x": 164, - "y": 146 + "y": 159 }, "delta": { "x": 54, @@ -28,11 +28,11 @@ "prognosis": { "call": { "x": 824, - "y": 351 + "y": 363 }, "put": { "x": 944, - "y": 351 + "y": 363 } } }, @@ -40,19 +40,22 @@ "fields": { "investment_money": { "x": 851, - "y": 156 + "y": 168 }, "expiration_time": { "x": 911, - "y": 156 + "y": 168 }, "result": { "x": 983, - "y": 457 - }, - "copy_summ": { + "y": 469 + } + }, + + "context_menu": { + "copy": { "x": 903, - "y": 247 + "y": 259 } } } diff --git a/get_coord.py b/get_coord.py new file mode 100644 index 0000000..27507c3 --- /dev/null +++ b/get_coord.py @@ -0,0 +1,7 @@ +import pyautogui +import time + +while True: + currentMouseX, currentMouseY = pyautogui.position() # Получаем XY координаты курсора. + print(currentMouseX, currentMouseY) + time.sleep(1) \ No newline at end of file diff --git a/pyFinance_v1_quotex.py b/pyFinance_v1_quotex.py index d29cdf8..6bac38e 100644 --- a/pyFinance_v1_quotex.py +++ b/pyFinance_v1_quotex.py @@ -12,13 +12,14 @@ # Initial values step = 1 -init_summ = 50 +INIT_SUMM = 50 +TIME_OFFSET = 1 # Prepare logger logger = logging.getLogger('pyFinance') logger.setLevel(logging.DEBUG) -fh = logging.FileHandler(datetime.datetime.now().strftime('%Y-%m-%d.log'), 'a', 'utf-8') +fh = logging.FileHandler(datetime.datetime.now().strftime('logging/%Y-%m-%d.log'), 'a', 'utf-8') formatter = logging.Formatter('%(asctime)s %(message)s') fh.setFormatter(formatter) fh.setLevel(logging.DEBUG) @@ -31,26 +32,25 @@ # Prepare telethon logger telethon_logger = logging.getLogger('telethon') -tfh = logging.FileHandler(datetime.datetime.now().strftime('%Y-%m-%d_telethon.log')) +tfh = logging.FileHandler(datetime.datetime.now().strftime('logging/%Y-%m-%d_telethon.log')) formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s') tfh.setFormatter(formatter) telethon_logger.setLevel(logging.DEBUG) telethon_logger.addHandler(tfh) - def save_state(save_file_path): global step - global init_summ + global INIT_SUMM with open(save_file_path, 'w') as sav: - sav.write("{} {}".format(step, init_summ)) + sav.write("{} {}".format(step, INIT_SUMM)) logger.debug("Saved to {}\n".format(save_file_path)) def load_state(save_file_path): global step - global init_summ + global INIT_SUMM if not os.path.isfile(save_file_path): logger.error("Save state {} is not exists".format(save_file_path)) @@ -58,15 +58,16 @@ def load_state(save_file_path): with open(save_file_path, 'r') as sav: content = sav.read() - step, init_summ = map(int, content.split()) + step, INIT_SUMM = map(int, content.split()) logger.debug("Loaded from {}".format(save_file_path)) logger.debug('step = {}'.format(step)) - logger.debug('init_summ = {}'.format(init_summ)) + logger.debug('init_summ = {}'.format(INIT_SUMM)) def get_summ(st): - return int(init_summ * (2.3 ** (st - 1))) + return int(INIT_SUMM * (2.3 ** (st - 1))) + def parse_signal(signal_text): signal_lines = signal_text.split('\n') @@ -79,7 +80,7 @@ def parse_signal(signal_text): if option not in BrokerManagerInterface.OPTION_LIST: # Если не нашли известный нам опцион, значит это не сигнал return None - + pattern = r'[\S\D]*(вверх|вниз)на(\d+)[\S\D]*' m = re.match(pattern, signal_lines[0].replace(' ', '').lower()) if m is None: @@ -88,9 +89,10 @@ def parse_signal(signal_text): prognosis = m.group(1) deal_time_str = m.group(2) - deal_time = int(deal_time_str) - 1 + deal_time = int(deal_time_str) return option, prognosis, deal_time + def deal_result_process(result): global step @@ -108,7 +110,7 @@ def deal_result_process(result): def message_process(message_text, message_date, broker_manager): global step - + logger.info('') logger.info('Got message') logger.debug(message_text) @@ -121,6 +123,7 @@ def message_process(message_text, message_date, broker_manager): return option, prognosis, deal_time = signal + deal_time = deal_time - TIME_OFFSET logger.info('Получен сигнал: {opt} {prog} на {tm}'.format( opt=option, @@ -149,8 +152,9 @@ def main(): client = TelegramClient(number, api_id, api_hash) broker_manager = BrokerManagerGui(deal_result_process, config) - - @client.on(events.NewMessage(chats='🔊 СИГНАЛЫ №1 🔊')) # создает событие, срабатывающее при появлении нового сообщения +#🔊 СИГНАЛЫ №1 🔊 + @client.on( + events.NewMessage(chats='tFinace')) # создает событие, срабатывающее при появлении нового сообщения async def normal_handler(event): message = event.message.to_dict() message_process(message['message'], message['date'], broker_manager) From 24ac6aee8844f82caac6b39448b5f0c745cafc02 Mon Sep 17 00:00:00 2001 From: New Nick Date: Sat, 5 Jun 2021 13:13:42 +0700 Subject: [PATCH 06/22] =?UTF-8?q?=D0=B8=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5?= =?UTF-8?q?=D0=BD=20=D0=BA=D0=B0=D0=BD=D0=B0=D0=BB=20=D1=82=D0=B5=D0=BB?= =?UTF-8?q?=D0=B5=D0=B3=D1=80=D0=B0=D0=BC=D0=BC=D0=B0,=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=B1=D1=8B=D0=BB=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=20=D1=82=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyFinance_v1_quotex.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyFinance_v1_quotex.py b/pyFinance_v1_quotex.py index 6bac38e..301909d 100644 --- a/pyFinance_v1_quotex.py +++ b/pyFinance_v1_quotex.py @@ -152,9 +152,9 @@ def main(): client = TelegramClient(number, api_id, api_hash) broker_manager = BrokerManagerGui(deal_result_process, config) -#🔊 СИГНАЛЫ №1 🔊 + @client.on( - events.NewMessage(chats='tFinace')) # создает событие, срабатывающее при появлении нового сообщения + events.NewMessage(chats='🔊 СИГНАЛЫ №1 🔊')) # создает событие, срабатывающее при появлении нового сообщения async def normal_handler(event): message = event.message.to_dict() message_process(message['message'], message['date'], broker_manager) From f270d0e9d4ff90eade58933cc63945ff72f4f36c Mon Sep 17 00:00:00 2001 From: New Nick Date: Sun, 6 Jun 2021 12:25:14 +0700 Subject: [PATCH 07/22] =?UTF-8?q?=D1=82=D0=B5=D0=BF=D0=B5=D1=80=D1=8C=20co?= =?UTF-8?q?ntext=5Fmenu=20=D0=BE=D1=82=D0=BD=D0=BE=D1=81=D0=B8=D1=82=D0=B5?= =?UTF-8?q?=D0=BB=D1=8C=D0=BD=D1=8B=D0=B5=20=D0=BA=D0=BE=D0=BE=D1=80=D0=B4?= =?UTF-8?q?=D0=B8=D0=BD=D0=B0=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- broker_manager_gui.py | 5 ++++- broker_manager_gui_luzin_config.json | 4 ++-- broker_manager_gui_nick_config.json | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/broker_manager_gui.py b/broker_manager_gui.py index bb6ee8f..8112035 100644 --- a/broker_manager_gui.py +++ b/broker_manager_gui.py @@ -86,11 +86,14 @@ def get_deal_summ(self): ) time.sleep(0.5) - pyautogui.click( + pyautogui.move( self.config['context_menu']['copy']['x'], self.config['context_menu']['copy']['y'], duration=0.1 ) + + pyautogui.click() + time.sleep(0.5) return pyperclip.paste() diff --git a/broker_manager_gui_luzin_config.json b/broker_manager_gui_luzin_config.json index 6df16e5..65fec3f 100644 --- a/broker_manager_gui_luzin_config.json +++ b/broker_manager_gui_luzin_config.json @@ -54,8 +54,8 @@ "context_menu": { "copy": { - "x": 1170, - "y": 195 + "x": 160, + "y": 267 } } } diff --git a/broker_manager_gui_nick_config.json b/broker_manager_gui_nick_config.json index bed8322..81f3717 100644 --- a/broker_manager_gui_nick_config.json +++ b/broker_manager_gui_nick_config.json @@ -54,8 +54,8 @@ "context_menu": { "copy": { - "x": 903, - "y": 259 + "x": 52, + "y": 91 } } } From 453038a598a84c5afa65cfe58a436664e422be21 Mon Sep 17 00:00:00 2001 From: New Nick Date: Sun, 6 Jun 2021 12:35:20 +0700 Subject: [PATCH 08/22] =?UTF-8?q?=D0=BC=D0=B5=D0=BB=D0=BA=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=B8=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B8?= =?UTF-8?q?=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=BF?= =?UTF-8?q?=D0=B0=D0=BF=D0=BA=D0=B8=20tools?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyFinance_v1_quotex.py | 2 +- get_coord.py => tools/get_coord.py | 2 +- limit.py => tools/limit.py | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename get_coord.py => tools/get_coord.py (91%) rename limit.py => tools/limit.py (100%) diff --git a/pyFinance_v1_quotex.py b/pyFinance_v1_quotex.py index 301909d..00285a2 100644 --- a/pyFinance_v1_quotex.py +++ b/pyFinance_v1_quotex.py @@ -123,7 +123,7 @@ def message_process(message_text, message_date, broker_manager): return option, prognosis, deal_time = signal - deal_time = deal_time - TIME_OFFSET + deal_time -= TIME_OFFSET logger.info('Получен сигнал: {opt} {prog} на {tm}'.format( opt=option, diff --git a/get_coord.py b/tools/get_coord.py similarity index 91% rename from get_coord.py rename to tools/get_coord.py index 27507c3..a7a50f3 100644 --- a/get_coord.py +++ b/tools/get_coord.py @@ -4,4 +4,4 @@ while True: currentMouseX, currentMouseY = pyautogui.position() # Получаем XY координаты курсора. print(currentMouseX, currentMouseY) - time.sleep(1) \ No newline at end of file + time.sleep(1) diff --git a/limit.py b/tools/limit.py similarity index 100% rename from limit.py rename to tools/limit.py From f55ba6a9b2da205e4ca8c3c160ec8691f8f2fa2c Mon Sep 17 00:00:00 2001 From: New Nick Date: Sun, 6 Jun 2021 20:11:31 +0700 Subject: [PATCH 09/22] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA?= =?UTF-8?q?=D0=B0=20=D0=BA=D0=BD=D0=BE=D0=BF=D0=BA=D0=B8=20=D0=BE=D0=BF?= =?UTF-8?q?=D1=86=D0=B8=D0=BE=D0=BD=D0=B0=20=D1=81=20=D0=BF=D0=BE=D0=BC?= =?UTF-8?q?=D0=BE=D1=89=D1=8C=D1=8E=20=D1=81=D0=BA=D1=80=D0=B8=D0=BD=D1=88?= =?UTF-8?q?=D0=BE=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- broker_manager_gui.py | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/broker_manager_gui.py b/broker_manager_gui.py index 8112035..fa5323a 100644 --- a/broker_manager_gui.py +++ b/broker_manager_gui.py @@ -86,17 +86,15 @@ def get_deal_summ(self): ) time.sleep(0.5) - pyautogui.move( - self.config['context_menu']['copy']['x'], - self.config['context_menu']['copy']['y'], + pyautogui.click( + self.config['fields']['investment_money']['x'] + self.config['context_menu']['copy']['x'], + self.config['fields']['investment_money']['y'] + self.config['context_menu']['copy']['y'], duration=0.1 ) - pyautogui.click() - time.sleep(0.5) return pyperclip.paste() - + def get_deal_time(self): pyperclip.copy("") # <- Это предотвращает замену последней копии текущей копией null. @@ -111,16 +109,25 @@ def get_deal_time(self): time.sleep(0.5) # ctrl-c обычно работает очень быстро, но ваша программа может выполняться быстрее return pyperclip.paste() + def click_option(self, point): + for k in range(BrokerManagerGui.TRY_COUNT): + screenshot_1 = pyautogui.screenshot(region=(point.x - 5, point.y - 5, point.x + 5, point.y + 5)) + pyautogui.click(point.x, point.y, duration=0.1) + time.sleep(3) + screenshot_2 = pyautogui.screenshot(region=(point.x - 5, point.y - 5, point.x + 5, point.y + 5)) + if screenshot_1 != screenshot_2: + logger.debug('Check option button - True') + return + else: + logger.debug('Check option button attempt №{} - False'.format(k)) + def make_deal(self, option, prognosis, summ, deal_time): if self.is_deal: logger.info('Deal is active now, skip new deal.\n') return windows_manager.activate_window('Прозрачный брокер бинарных опционов') - pyautogui.click(self.option_buttons[option].x, self.option_buttons[option].y, duration=0.1) - time.sleep(2) - pyautogui.click(self.option_buttons[option].x, self.option_buttons[option].y, duration=0.1) - time.sleep(5) + self.click_option(self.option_buttons[option]) for k in range(BrokerManagerGui.TRY_COUNT): pyautogui.doubleClick( @@ -132,7 +139,7 @@ def make_deal(self, option, prognosis, summ, deal_time): pyautogui.write(str(summ), interval=0.25) time.sleep(0.5) if self.get_deal_summ() == str(summ): - logger.debug('Check deal summ True') + logger.debug('Check deal summ - True') break else: logger.debug('Check deal summ attempt №{} - False'.format(k)) @@ -147,7 +154,7 @@ def make_deal(self, option, prognosis, summ, deal_time): pyautogui.write(str(deal_time), interval=0.25) time.sleep(0.5) if self.get_deal_time() == str(deal_time): - logger.debug('Check deal time True') + logger.debug('Check deal time - True') break else: logger.debug('Check deal time attempt №{} - False'.format(k)) From d767521471b38077d462c0d84b2341b338267c99 Mon Sep 17 00:00:00 2001 From: New Nick Date: Sat, 12 Jun 2021 21:09:53 +0700 Subject: [PATCH 10/22] =?UTF-8?q?=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=20=D0=BF=D1=83=D1=82=D1=8C=20=D0=BA=20=D0=BB?= =?UTF-8?q?=D0=BE=D0=B3=D1=83,=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=BD=D1=8B=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8?= =?UTF-8?q?=D0=B8=20=D0=BF=D0=BE=D0=BB=D1=83=D1=87=D0=B5=D0=BD=D0=B8=D1=8F?= =?UTF-8?q?=20=D0=B7=D0=BD=D0=B0=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B8?= =?UTF-8?q?=D0=B7=20=D0=BF=D0=BE=D0=BB=D1=8F=20=D0=B8=20=D0=B2=D0=B2=D0=BE?= =?UTF-8?q?=D0=B4=20=D0=B7=D0=BD=D0=B0=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=B2=20=D0=BF=D0=BE=D0=BB=D0=B5,=20=D0=B4=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D0=BA=D0=B0=20=D0=B2=D1=81=D0=B5=D1=85=20=D0=BF=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B5=D1=80=D0=BE))))=20=D0=B5=D1=81=D0=BB=D0=B8?= =?UTF-8?q?=20=D0=B2=D1=81=D0=B5=20=D0=BF=D0=BE=D0=BF=D1=8B=D1=82=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=B2=D1=8B=D0=B1=D0=BE=D1=80=D0=B0=20=D0=BE=D0=BF?= =?UTF-8?q?=D1=86=D0=B8=D0=BE=D0=BD=D0=B0=20=D0=B8=D0=BB=D0=B8=20=D0=B2?= =?UTF-8?q?=D0=B2=D0=BE=D0=B4=D0=B0=20=D0=B7=D0=BD=D0=B0=D1=87=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=B2=20=D0=BF=D0=BE=D0=BB=D0=B5=20=D0=BD=D0=B5?= =?UTF-8?q?=D1=83=D0=B4=D0=B0=D1=87=D0=BD=D1=8B=D0=B5=20=D1=82=D0=BE=20?= =?UTF-8?q?=D0=BD=D0=B8=D1=87=D0=B5=D0=B3=D0=BE=20=D0=BD=D0=B5=20=D0=B4?= =?UTF-8?q?=D0=B5=D0=BB=D0=B0=D0=B5=D0=BC.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .screenshot2021-0606_19-25-04-863328.png | Bin 0 -> 40960 bytes broker_manager_gui.py | 109 ++++++++++------------- broker_manager_gui_luzin_config.json | 4 +- broker_manager_gui_nick_config.json | 2 +- pyFinance_v1_quotex.py | 19 ++-- 5 files changed, 63 insertions(+), 71 deletions(-) create mode 100644 .screenshot2021-0606_19-25-04-863328.png diff --git a/.screenshot2021-0606_19-25-04-863328.png b/.screenshot2021-0606_19-25-04-863328.png new file mode 100644 index 0000000000000000000000000000000000000000..84e8bf3d5553f6b4b81fb51bb17a10392ef1b313 GIT binary patch literal 40960 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 z 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 C Date: Sun, 13 Jun 2021 16:37:17 +0700 Subject: [PATCH 11/22] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=BD=D0=BE=20=D0=B8=D1=81=D0=BA=D0=BB=D1=8E=D1=87?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BA=D0=BE=D0=B3=D0=B4=D0=B0=20?= =?UTF-8?q?=D0=B2=D1=81=D0=B5=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=BD=D0=B5=D1=83=D0=B4=D0=B0=D1=87=D0=BD=D1=8B=D0=B5?= =?UTF-8?q?,=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=20=D1=84=D0=B0=D0=B9?= =?UTF-8?q?=D0=BB=20=D1=81=20=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D1=82=D0=B5=D0=BB=D1=8C=D1=81=D0=BA=D0=B8=D0=BC=D0=B8=20?= =?UTF-8?q?=D0=B8=D1=81=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8=D1=8F?= =?UTF-8?q?=D0=BC=D0=B8.=20=D0=B8=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD?= =?UTF-8?q?=D1=8B=20=D1=84=D1=83=D0=BA=D1=86=D0=B8=D0=B8=20=D0=BF=D0=BE?= =?UTF-8?q?=D0=BB=D1=83=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B7=D0=BD=D0=B0?= =?UTF-8?q?=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B8=D0=B7=20=D0=BF=D0=BE?= =?UTF-8?q?=D0=BB=D1=8F=20=D0=B8=20=D0=B2=D0=B2=D0=BE=D0=B4=20=D0=B2=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=BB=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- broker_manager_gui.py | 33 +++++++++++++++++---------------- errors.py | 15 +++++++++++++++ 2 files changed, 32 insertions(+), 16 deletions(-) create mode 100644 errors.py diff --git a/broker_manager_gui.py b/broker_manager_gui.py index 3af9a67..d226d42 100644 --- a/broker_manager_gui.py +++ b/broker_manager_gui.py @@ -5,11 +5,12 @@ import pyperclip import pytz import time - import geometry_2d import windows_manager +import errors from broker_manager_interface import BrokerManagerInterface + logger = logging.getLogger('pyFinance') @@ -67,8 +68,8 @@ def _get_deal_result(self): def set_field(self, field, value): pyautogui.doubleClick( - field['x'], - field['y'], + self.config['fields'][field]['x'], + self.config['fields'][field]['y'], duration=0.1 ) time.sleep(0.5) @@ -79,23 +80,23 @@ def get_field(self, field, use_mouse=False): pyperclip.copy("") # <- Это предотвращает замену последней копии текущей копией null. pyautogui.doubleClick( - field['x'], - field['y'], + self.config['fields'][field]['x'], + self.config['fields'][field]['y'], duration=0.1 ) time.sleep(0.5) if use_mouse: pyautogui.rightClick( - field['x'], - field['y'], + self.config['fields'][field]['x'], + self.config['fields'][field]['y'], duration=0.1 ) time.sleep(0.5) pyautogui.click( - field['x'] + self.config['context_menu']['copy']['x'], - field['y'] + self.config['context_menu']['copy']['y'], + self.config['fields'][field]['x'] + self.config['context_menu']['copy']['x'], + self.config['fields'][field]['y'] + self.config['context_menu']['copy']['y'], duration=0.1 ) else: @@ -124,27 +125,27 @@ def make_deal(self, option, prognosis, summ, deal_time): windows_manager.activate_window('Прозрачный брокер бинарных опционов') if not self.click_option(self.option_buttons[option]): - return + raise errors.ClickoptionError('invalid option selection') for k in range(BrokerManagerGui.TRY_COUNT): - self.set_field(self.config['fields']['investment_money'], summ) - if self.get_field(self.config['fields']['investment_money'], use_mouse=True) == str(summ): + self.set_field('investment_money', summ) + if self.get_field('investment_money', use_mouse=True) == str(summ): logger.debug('Check deal summ - True') break logger.debug('Check deal summ attempt №{} - False'.format(k)) # при всех неудачных попытках ничего не делаем if k == (BrokerManagerGui.TRY_COUNT - 1): - return + raise errors.ValueSummError('invalid summ input') for k in range(BrokerManagerGui.TRY_COUNT): - self.set_field(self.config['fields']['expiration_time'], deal_time) - if self.get_field(self.config['fields']['expiration_time']) == str(deal_time): + self.set_field('expiration_time', deal_time) + if self.get_field('expiration_time') == str(deal_time): logger.debug('Check deal time - True') break logger.debug('Check deal time attempt №{} - False'.format(k)) # при всех неудачных попытках ничего не делаем if k == (BrokerManagerGui.TRY_COUNT - 1): - return + raise errors.ValueTimeError('invalid time input') pyautogui.click(self.prognosis_table[prognosis].x, self.prognosis_table[prognosis].y, duration=0.1) self.is_deal = True diff --git a/errors.py b/errors.py new file mode 100644 index 0000000..feb1efd --- /dev/null +++ b/errors.py @@ -0,0 +1,15 @@ +class Error(Exception): + """Базовый класс для других исключений""" + pass + +class ClickoptionError(Error): + """Вызывается. когда все проверки выбора опциона прошли неудачно""" + pass + +class ValueSummError(Error): + """Вызывается, когда введена неверная сумма сделки""" + pass + +class ValueTimeError(Error): + """Вызывается, когда введено неверное время сделки""" + pass From be2af88abd9ac0204d633f6645ec68f91011178a Mon Sep 17 00:00:00 2001 From: New Nick Date: Tue, 15 Jun 2021 20:30:14 +0700 Subject: [PATCH 12/22] =?UTF-8?q?=D0=B8=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D0=B2=20=D1=84=D0=BE=D1=80=D0=BC=D1=83?= =?UTF-8?q?=D0=BB=D0=B8=D1=80=D0=BE=D0=B2=D0=BA=D0=B5=20=D0=BB=D0=BE=D0=B3?= =?UTF-8?q?=D0=B0=20=D0=B8=20=D0=B8c=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=B2=20=D1=84=D1=83=D0=BD=D0=BA=D1=86?= =?UTF-8?q?=D0=B8=D0=B8=20=D0=BF=D0=BE=D0=BB=D1=83=D1=87=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D1=80=D0=B5=D0=B7=D1=83=D0=BB=D1=8C=D1=82=D0=B0=D1=82?= =?UTF-8?q?=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- broker_manager_gui.py | 9 ++++----- errors.py | 15 --------------- pyFinance_v1_quotex.py | 9 +++++---- 3 files changed, 9 insertions(+), 24 deletions(-) delete mode 100644 errors.py diff --git a/broker_manager_gui.py b/broker_manager_gui.py index d226d42..f1f5fec 100644 --- a/broker_manager_gui.py +++ b/broker_manager_gui.py @@ -7,7 +7,6 @@ import time import geometry_2d import windows_manager -import errors from broker_manager_interface import BrokerManagerInterface @@ -58,7 +57,7 @@ def _get_deal_result(self): result = '' windows_manager.activate_window('Прозрачный брокер бинарных опционов') for k in range(BrokerManagerGui.TRY_COUNT): - result = self.get_field(self.config['fields']['result']) + result = self.get_field('result') if result in ['LOSE', 'WIN']: break time.sleep(5) @@ -125,7 +124,7 @@ def make_deal(self, option, prognosis, summ, deal_time): windows_manager.activate_window('Прозрачный брокер бинарных опционов') if not self.click_option(self.option_buttons[option]): - raise errors.ClickoptionError('invalid option selection') + RuntimeError('Option selection error') for k in range(BrokerManagerGui.TRY_COUNT): self.set_field('investment_money', summ) @@ -135,7 +134,7 @@ def make_deal(self, option, prognosis, summ, deal_time): logger.debug('Check deal summ attempt №{} - False'.format(k)) # при всех неудачных попытках ничего не делаем if k == (BrokerManagerGui.TRY_COUNT - 1): - raise errors.ValueSummError('invalid summ input') + raise RuntimeError('Summ input error') for k in range(BrokerManagerGui.TRY_COUNT): self.set_field('expiration_time', deal_time) @@ -145,7 +144,7 @@ def make_deal(self, option, prognosis, summ, deal_time): logger.debug('Check deal time attempt №{} - False'.format(k)) # при всех неудачных попытках ничего не делаем if k == (BrokerManagerGui.TRY_COUNT - 1): - raise errors.ValueTimeError('invalid time input') + raise RuntimeError('Time input error') pyautogui.click(self.prognosis_table[prognosis].x, self.prognosis_table[prognosis].y, duration=0.1) self.is_deal = True diff --git a/errors.py b/errors.py deleted file mode 100644 index feb1efd..0000000 --- a/errors.py +++ /dev/null @@ -1,15 +0,0 @@ -class Error(Exception): - """Базовый класс для других исключений""" - pass - -class ClickoptionError(Error): - """Вызывается. когда все проверки выбора опциона прошли неудачно""" - pass - -class ValueSummError(Error): - """Вызывается, когда введена неверная сумма сделки""" - pass - -class ValueTimeError(Error): - """Вызывается, когда введено неверное время сделки""" - pass diff --git a/pyFinance_v1_quotex.py b/pyFinance_v1_quotex.py index efb7ca3..6910e7a 100644 --- a/pyFinance_v1_quotex.py +++ b/pyFinance_v1_quotex.py @@ -116,7 +116,8 @@ def deal_result_process(result): def message_process(message_text, message_date, broker_manager): global step - logger.info('\nGot message') + logger.info('-------------------------------------------------------------------') + logger.info('Got message') logger.debug(message_text) logger.info(message_date.strftime('Message date: %d-%m-%Y %H:%M')) @@ -157,9 +158,9 @@ def main(): client = TelegramClient(number, api_id, api_hash) broker_manager = BrokerManagerGui(deal_result_process, config) -#🔊 СИГНАЛЫ №1 🔊 - @client.on( - events.NewMessage(chats='tFinace')) # создает событие, срабатывающее при появлении нового сообщения + + # создает событие, срабатывающее при появлении нового сообщения + @client.on(events.NewMessage(chats='🔊 СИГНАЛЫ №1 🔊')) async def normal_handler(event): message = event.message.to_dict() message_process(message['message'], message['date'], broker_manager) From 113fb8a1aeaa1b767fb88ced4b4a70934c394060 Mon Sep 17 00:00:00 2001 From: New Nick Date: Sun, 20 Jun 2021 12:09:09 +0700 Subject: [PATCH 13/22] =?UTF-8?q?=D0=B2=D0=BD=D0=B5=D0=B4=D1=80=D0=B5?= =?UTF-8?q?=D0=BD=D0=BE=20=D0=A4=D0=9F,=20=D1=82=D0=BE=D0=BB=D1=8C=D0=BA?= =?UTF-8?q?=D0=BE=20=D0=B2=D0=BC=D0=B5=D1=81=D1=82=D0=BE=20=D0=B4=D0=B2?= =?UTF-8?q?=D1=83=D1=85=20=D0=BF=D0=BE=D0=B2=D1=82=D0=BE=D1=80=D1=8F=D1=8E?= =?UTF-8?q?=D1=89=D0=B8=D1=85=D1=81=D1=8F=20=D0=BC=D0=B5=D1=81=D1=82=20?= =?UTF-8?q?=D1=82=D0=B5=D0=BF=D0=B5=D1=80=D1=8C=20=D0=B2=20=D1=84=D1=83?= =?UTF-8?q?=D0=BD=D0=BA=D1=86=D0=B8=D0=B8=20try=5Fset=5Ffiald=20=D0=B8?= =?UTF-8?q?=D1=85=20=D1=82=D1=80=D0=B8,=20=D0=BC=D0=BE=D0=B6=D1=82=20?= =?UTF-8?q?=D1=87=D0=B5=D1=82=D0=BE=20=D0=BD=D0=B5=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=D1=8C=D0=BD=D0=BE=20=D1=81=D0=B4=D0=B5=D0=BB=D0=B0?= =?UTF-8?q?=D0=BB.=20=D0=A0=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=D0=B5=D1=82=20?= =?UTF-8?q?=D1=81=D0=BE=D0=BE=D1=82=D0=B2=D0=B5=D1=82=D1=81=D1=82=D0=B2?= =?UTF-8?q?=D0=B5=D0=BD=D0=BD=D0=BE=20=D0=BD=D0=B5=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=D1=8C=D0=BD=D0=BE=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D0=BA=D0=B8=20=D1=81=D1=83=D0=BC=D0=BC=D1=8B=20=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D1=88=D0=BB=D0=B8=20=D0=BD=D0=BE=20=D0=BE=D0=BD=20?= =?UTF-8?q?=D0=BF=D1=80=D0=BE=D0=B4=D0=BE=D0=BB=D0=B6=D0=B5=D0=BB=20=D0=B2?= =?UTF-8?q?=D1=8B=D0=BF=D0=BE=D0=BB=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5.=20?= =?UTF-8?q?=D0=B8=20=D0=B2=D0=BC=D0=B5=D1=81=D1=82=D0=BE=20=D0=B2=D1=80?= =?UTF-8?q?=D0=B5=D0=BC=D0=B5=D0=BD=D0=B8=2014=20=D0=BC=D0=B8=D0=BD=20?= =?UTF-8?q?=D0=BA=D0=BF=D1=80=D0=B8=D0=BC=D0=B5=D1=80=D1=83,=20=D0=B2?= =?UTF-8?q?=D0=B2=D0=BE=D0=B4=D0=B8=D1=82=20=D0=B4=D0=B0=D1=82=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- broker_manager_gui.py | 94 +++++++++++++++++++++------- broker_manager_gui_luzin_config.json | 6 +- broker_manager_gui_nick_config.json | 4 ++ pyFinance_v1_quotex.py | 9 +-- 4 files changed, 86 insertions(+), 27 deletions(-) diff --git a/broker_manager_gui.py b/broker_manager_gui.py index f1f5fec..fd3028b 100644 --- a/broker_manager_gui.py +++ b/broker_manager_gui.py @@ -9,7 +9,6 @@ import windows_manager from broker_manager_interface import BrokerManagerInterface - logger = logging.getLogger('pyFinance') @@ -56,6 +55,15 @@ def _get_deal_result(self): result = '' windows_manager.activate_window('Прозрачный брокер бинарных опционов') + + # открываем графу сделок "открытые" + pyautogui.doubleClick( + self.config['buttons']['opened']['x'], + self.config['buttons']['opened']['y'], + duration=0.1 + ) + time.sleep(5) + for k in range(BrokerManagerGui.TRY_COUNT): result = self.get_field('result') if result in ['LOSE', 'WIN']: @@ -65,6 +73,10 @@ def _get_deal_result(self): # If result not in ['LOSE', 'WIN'] return as is self.result_handler(result) + def get_deal_time(self, finish_datetime): + deal_time = int((finish_datetime - datetime.datetime.now()).total_seconds() // 60) + return deal_time + def set_field(self, field, value): pyautogui.doubleClick( self.config['fields'][field]['x'], @@ -105,6 +117,36 @@ def get_field(self, field, use_mouse=False): time.sleep(0.5) return pyperclip.paste() + def try_set_field(self, field, value, use_mouse=False): + if use_mouse: + self.set_field(field, value) + if self.get_field(field, use_mouse=True) == str(value): + return True + + # Если передали дату, узнаем время сделки + if isinstance(value, datetime.datetime): + deal_time = self.get_deal_time(value) + self.set_field(field, deal_time) + if self.get_field(field) == str(deal_time): + return True + + self.set_field(field, value) + if self.get_field(field) == str(value): + return True + return False + + def repeater(self, tries, action, *args, **kvargs): + for k in range(tries): + if action(*args, **kvargs): + logger.debug('Check {} - True'.format(args[0])) + return + logger.debug('Check {} attempt №{} - False'.format(args[0], k)) + + # при всех неудачных попытках ничего не делаем + if not k < tries: + raise RuntimeError('Time input error') + + def click_option(self, option): screenshot_1 = pyautogui.screenshot(region=(option.x - 5, option.y - 5, option.x + 5, option.y + 5)) for k in range(BrokerManagerGui.TRY_COUNT): @@ -122,29 +164,37 @@ def make_deal(self, option, prognosis, summ, deal_time): logger.info('Deal is active now, skip new deal.\n') return + finish_datetime = datetime.datetime.now() + datetime.timedelta(minutes=deal_time) + windows_manager.activate_window('Прозрачный брокер бинарных опционов') if not self.click_option(self.option_buttons[option]): - RuntimeError('Option selection error') - - for k in range(BrokerManagerGui.TRY_COUNT): - self.set_field('investment_money', summ) - if self.get_field('investment_money', use_mouse=True) == str(summ): - logger.debug('Check deal summ - True') - break - logger.debug('Check deal summ attempt №{} - False'.format(k)) - # при всех неудачных попытках ничего не делаем - if k == (BrokerManagerGui.TRY_COUNT - 1): - raise RuntimeError('Summ input error') - - for k in range(BrokerManagerGui.TRY_COUNT): - self.set_field('expiration_time', deal_time) - if self.get_field('expiration_time') == str(deal_time): - logger.debug('Check deal time - True') - break - logger.debug('Check deal time attempt №{} - False'.format(k)) - # при всех неудачных попытках ничего не делаем - if k == (BrokerManagerGui.TRY_COUNT - 1): - raise RuntimeError('Time input error') + raise RuntimeError('Option selection error') + + self.repeater(BrokerManagerGui.TRY_COUNT, self.try_set_field, 'investment_money', summ, use_mouse=True) + self.repeater(BrokerManagerGui.TRY_COUNT, self.try_set_field, 'expiration_time', finish_datetime) + + # for k in range(BrokerManagerGui.TRY_COUNT): + # self.set_field('investment_money', summ) + # if self.get_field('investment_money', use_mouse=True) == str(summ): + # logger.debug('Check deal summ - True') + # break + # logger.debug('Check deal summ attempt №{} - False'.format(k)) + # + # # при всех неудачных попытках ничего не делаем + # if k == (BrokerManagerGui.TRY_COUNT - 1): + # raise RuntimeError('Summ input error') + # + # for k in range(BrokerManagerGui.TRY_COUNT): + # deal_time = self.get_deal_time(finish_datetime) + # self.set_field('expiration_time', deal_time) + # if self.get_field('expiration_time') == str(deal_time): + # logger.debug('Check deal time - True') + # break + # logger.debug('Check deal time attempt №{} - False'.format(k)) + # + # # при всех неудачных попытках ничего не делаем + # if k == (BrokerManagerGui.TRY_COUNT - 1): + # raise RuntimeError('Time input error') pyautogui.click(self.prognosis_table[prognosis].x, self.prognosis_table[prognosis].y, duration=0.1) self.is_deal = True diff --git a/broker_manager_gui_luzin_config.json b/broker_manager_gui_luzin_config.json index 7043792..c376f7f 100644 --- a/broker_manager_gui_luzin_config.json +++ b/broker_manager_gui_luzin_config.json @@ -34,6 +34,10 @@ "x": 1250, "y": 340 } + }, + "opened": { + "x": 1213, + "y": 415 } }, @@ -48,7 +52,7 @@ }, "result": { "x": 1330, - "y": 462 + "y": 470 } }, diff --git a/broker_manager_gui_nick_config.json b/broker_manager_gui_nick_config.json index 63e09b4..ecfd0a7 100644 --- a/broker_manager_gui_nick_config.json +++ b/broker_manager_gui_nick_config.json @@ -34,6 +34,10 @@ "x": 944, "y": 363 } + }, + "opened": { + "x": 866, + "y": 412 } }, diff --git a/pyFinance_v1_quotex.py b/pyFinance_v1_quotex.py index 6910e7a..1b6e672 100644 --- a/pyFinance_v1_quotex.py +++ b/pyFinance_v1_quotex.py @@ -5,6 +5,7 @@ import re import sys import traceback +from apscheduler.schedulers.background import BackgroundScheduler from broker_manager_gui import BrokerManagerGui, BrokerManagerInterface @@ -18,7 +19,7 @@ # Initial values step = 1 INIT_SUMM = 50 -TIME_OFFSET = 1 +#TIME_OFFSET = 1 # Prepare logger logger = logging.getLogger('pyFinance') @@ -128,7 +129,7 @@ def message_process(message_text, message_date, broker_manager): return option, prognosis, deal_time = signal - deal_time -= TIME_OFFSET + #deal_time -= TIME_OFFSET logger.info('Получен сигнал: {opt} {prog} на {tm}'.format( opt=option, @@ -158,9 +159,9 @@ def main(): client = TelegramClient(number, api_id, api_hash) broker_manager = BrokerManagerGui(deal_result_process, config) - +#🔊 СИГНАЛЫ №1 🔊 # создает событие, срабатывающее при появлении нового сообщения - @client.on(events.NewMessage(chats='🔊 СИГНАЛЫ №1 🔊')) + @client.on(events.NewMessage(chats='tFinace')) async def normal_handler(event): message = event.message.to_dict() message_process(message['message'], message['date'], broker_manager) From 215e84ddd3918ae60bb8206cb57108e2364a6f7d Mon Sep 17 00:00:00 2001 From: New Nick Date: Sun, 20 Jun 2021 13:20:58 +0700 Subject: [PATCH 14/22] =?UTF-8?q?=D0=BF=D0=BE=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D1=80=D0=B0=D1=81=D1=87=D0=B5=D1=82=20=D0=B2?= =?UTF-8?q?=D1=80=D0=B5=D0=BC=D0=B5=D0=BD=D0=B8=20=D0=B7=D0=B0=D0=BF=D1=83?= =?UTF-8?q?=D1=81=D0=BA=D0=B0=20=D0=B8=D0=B7=D0=BD=D0=B0=D0=B2=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D1=80=D0=B5=D0=B7=D1=83=D0=BB=D1=8C=D1=82=D0=B0?= =?UTF-8?q?=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- broker_manager_gui.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/broker_manager_gui.py b/broker_manager_gui.py index fd3028b..4cddf7f 100644 --- a/broker_manager_gui.py +++ b/broker_manager_gui.py @@ -10,6 +10,7 @@ from broker_manager_interface import BrokerManagerInterface logger = logging.getLogger('pyFinance') +deal_time_gl = 0 class BrokerManagerGui(BrokerManagerInterface): @@ -118,6 +119,8 @@ def get_field(self, field, use_mouse=False): return pyperclip.paste() def try_set_field(self, field, value, use_mouse=False): + global deal_time_gl + if use_mouse: self.set_field(field, value) if self.get_field(field, use_mouse=True) == str(value): @@ -125,9 +128,10 @@ def try_set_field(self, field, value, use_mouse=False): # Если передали дату, узнаем время сделки if isinstance(value, datetime.datetime): - deal_time = self.get_deal_time(value) - self.set_field(field, deal_time) - if self.get_field(field) == str(deal_time): + deal_time_gl = self.get_deal_time(value) + print(deal_time_gl) + self.set_field(field, deal_time_gl) + if self.get_field(field) == str(deal_time_gl): return True self.set_field(field, value) @@ -160,6 +164,7 @@ def click_option(self, option): return False def make_deal(self, option, prognosis, summ, deal_time): + if self.is_deal: logger.info('Deal is active now, skip new deal.\n') return @@ -199,5 +204,5 @@ def make_deal(self, option, prognosis, summ, deal_time): pyautogui.click(self.prognosis_table[prognosis].x, self.prognosis_table[prognosis].y, duration=0.1) self.is_deal = True - finish_datetime = datetime.datetime.now() + datetime.timedelta(minutes=deal_time) + finish_datetime = datetime.datetime.now() + datetime.timedelta(minutes=deal_time_gl) self.scheduler.add_job(self._get_deal_result, 'date', run_date=finish_datetime) From 0499a905a20be194ca009a3a180c3d77df39565e Mon Sep 17 00:00:00 2001 From: New Nick Date: Mon, 21 Jun 2021 17:37:32 +0700 Subject: [PATCH 15/22] =?UTF-8?q?=D0=B7=D0=B0=D0=BC=D0=B5=D0=BD=D0=B5?= =?UTF-8?q?=D0=BD=20=D0=BA=D0=B0=D0=BD=D0=B0=D0=BB=20=D1=82=D0=B5=D0=BB?= =?UTF-8?q?=D0=B5=D0=B3=D1=80=D0=B0=D0=BC=D0=BC=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyFinance_v1_quotex.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyFinance_v1_quotex.py b/pyFinance_v1_quotex.py index 1b6e672..3e59ff5 100644 --- a/pyFinance_v1_quotex.py +++ b/pyFinance_v1_quotex.py @@ -159,9 +159,9 @@ def main(): client = TelegramClient(number, api_id, api_hash) broker_manager = BrokerManagerGui(deal_result_process, config) -#🔊 СИГНАЛЫ №1 🔊 + # создает событие, срабатывающее при появлении нового сообщения - @client.on(events.NewMessage(chats='tFinace')) + @client.on(events.NewMessage(chats='🔊 СИГНАЛЫ №1 🔊')) async def normal_handler(event): message = event.message.to_dict() message_process(message['message'], message['date'], broker_manager) From 8c0a442c5a7fd2dd453e9b318c22963b78b98724 Mon Sep 17 00:00:00 2001 From: New Nick Date: Mon, 21 Jun 2021 21:26:09 +0700 Subject: [PATCH 16/22] =?UTF-8?q?=D0=B8=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=2021.06?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- broker_manager_gui.py | 77 ++++++++++++++++++++++++++---------------- pyFinance_v1_quotex.py | 7 ++-- 2 files changed, 49 insertions(+), 35 deletions(-) diff --git a/broker_manager_gui.py b/broker_manager_gui.py index 4cddf7f..4c2bd98 100644 --- a/broker_manager_gui.py +++ b/broker_manager_gui.py @@ -5,6 +5,7 @@ import pyperclip import pytz import time + import geometry_2d import windows_manager from broker_manager_interface import BrokerManagerInterface @@ -13,6 +14,18 @@ deal_time_gl = 0 +def repeater(action, *args, **kvargs): + tries = 5 + for k in range(tries): + if action(*args, **kvargs): + logger.debug('Check {} - True'.format(action.__name__)) + return + logger.debug('Check {} - False'.format(action.__name__)) + + # при всех неудачных попытках кидаем исключение об ошибке + raise RuntimeError('{} setting error'.format(args[0])) + + class BrokerManagerGui(BrokerManagerInterface): TRY_COUNT = 5 @@ -22,6 +35,13 @@ def __init__(self, result_handler, config_file): with open(config_file, 'r') as cf: self.config = json.load(cf) + # Устанавливаем начальный опцион + self.prev_option = None + try: + self.click_option('EURUSD') + except: + pass + self.exp_hour_buttons = geometry_2d.get_matrix( m_size=geometry_2d.Vector(x=6, y=4), start=geometry_2d.Vector(**self.config['buttons']['expiration_time']['first_hour']), @@ -121,46 +141,43 @@ def get_field(self, field, use_mouse=False): def try_set_field(self, field, value, use_mouse=False): global deal_time_gl - if use_mouse: - self.set_field(field, value) - if self.get_field(field, use_mouse=True) == str(value): - return True - # Если передали дату, узнаем время сделки if isinstance(value, datetime.datetime): deal_time_gl = self.get_deal_time(value) - print(deal_time_gl) self.set_field(field, deal_time_gl) if self.get_field(field) == str(deal_time_gl): return True self.set_field(field, value) - if self.get_field(field) == str(value): - return True - return False - - def repeater(self, tries, action, *args, **kvargs): - for k in range(tries): - if action(*args, **kvargs): - logger.debug('Check {} - True'.format(args[0])) - return - logger.debug('Check {} attempt №{} - False'.format(args[0], k)) - - # при всех неудачных попытках ничего не делаем - if not k < tries: - raise RuntimeError('Time input error') - + return self.get_field(field, use_mouse) == str(value) def click_option(self, option): - screenshot_1 = pyautogui.screenshot(region=(option.x - 5, option.y - 5, option.x + 5, option.y + 5)) + if self.prev_option == option: + return True + + screenshot_1 = pyautogui.screenshot( + region=( + self.option_buttons[option].x - 5, + self.option_buttons[option].y - 5, + self.option_buttons[option].x + 5, + self.option_buttons[option].y + 5 + ) + ) for k in range(BrokerManagerGui.TRY_COUNT): - pyautogui.click(option.x, option.y, duration=0.1) + pyautogui.click(self.option_buttons[option].x, self.option_buttons[option].y, duration=0.1) time.sleep(3) - screenshot_2 = pyautogui.screenshot(region=(option.x - 5, option.y - 5, option.x + 5, option.y + 5)) + screenshot_2 = pyautogui.screenshot( + region=( + self.option_buttons[option].x - 5, + self.option_buttons[option].y - 5, + self.option_buttons[option].x + 5, + self.option_buttons[option].y + 5 + ) + ) if screenshot_1 != screenshot_2: - logger.debug('Check option button - True') + logger.debug('Check option button {} - True'.format(option)) return True - logger.debug('Check option button attempt №{} - False'.format(k)) + logger.debug('Check option button {} attempt №{} - False'.format(k, option)) return False def make_deal(self, option, prognosis, summ, deal_time): @@ -172,11 +189,11 @@ def make_deal(self, option, prognosis, summ, deal_time): finish_datetime = datetime.datetime.now() + datetime.timedelta(minutes=deal_time) windows_manager.activate_window('Прозрачный брокер бинарных опционов') - if not self.click_option(self.option_buttons[option]): - raise RuntimeError('Option selection error') + if not self.click_option(option): + raise RuntimeError('Option {} selection error'.format(option)) - self.repeater(BrokerManagerGui.TRY_COUNT, self.try_set_field, 'investment_money', summ, use_mouse=True) - self.repeater(BrokerManagerGui.TRY_COUNT, self.try_set_field, 'expiration_time', finish_datetime) + repeater(self.try_set_field, self, 'investment_money', summ, use_mouse=True) + repeater(self.try_set_field, self, 'expiration_time', finish_datetime) # for k in range(BrokerManagerGui.TRY_COUNT): # self.set_field('investment_money', summ) diff --git a/pyFinance_v1_quotex.py b/pyFinance_v1_quotex.py index 3e59ff5..ca8403f 100644 --- a/pyFinance_v1_quotex.py +++ b/pyFinance_v1_quotex.py @@ -5,7 +5,6 @@ import re import sys import traceback -from apscheduler.schedulers.background import BackgroundScheduler from broker_manager_gui import BrokerManagerGui, BrokerManagerInterface @@ -19,7 +18,6 @@ # Initial values step = 1 INIT_SUMM = 50 -#TIME_OFFSET = 1 # Prepare logger logger = logging.getLogger('pyFinance') @@ -129,7 +127,6 @@ def message_process(message_text, message_date, broker_manager): return option, prognosis, deal_time = signal - #deal_time -= TIME_OFFSET logger.info('Получен сигнал: {opt} {prog} на {tm}'.format( opt=option, @@ -159,9 +156,9 @@ def main(): client = TelegramClient(number, api_id, api_hash) broker_manager = BrokerManagerGui(deal_result_process, config) - +#🔊 СИГНАЛЫ №1 🔊 # создает событие, срабатывающее при появлении нового сообщения - @client.on(events.NewMessage(chats='🔊 СИГНАЛЫ №1 🔊')) + @client.on(events.NewMessage(chats='tFinace')) async def normal_handler(event): message = event.message.to_dict() message_process(message['message'], message['date'], broker_manager) From 161e71d71ec266ca0946cb0d8c18dcb70f9fb0c8 Mon Sep 17 00:00:00 2001 From: New Nick Date: Thu, 24 Jun 2021 21:24:16 +0700 Subject: [PATCH 17/22] =?UTF-8?q?=D0=BF=D0=BE=D1=81=D0=BC=D0=BE=D1=82?= =?UTF-8?q?=D1=80=D0=B8=20=D1=8F=20=D1=82=D0=B0=D0=BC=20=D1=81=D0=BE=20?= =?UTF-8?q?=D0=B2=D1=80=D0=B5=D0=BC=D0=B5=D0=BD=D0=B5=D0=BC=20=D0=B8=D0=B7?= =?UTF-8?q?=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B2=D0=BD=D0=B5?= =?UTF-8?q?=D1=81=20=D0=B8=20=D1=81=20=D0=BA=D0=BB=D0=B8=D0=BA=D0=BE=D0=BC?= =?UTF-8?q?=20=D0=BF=D0=BE=20=D0=BE=D0=BF=D1=86=D0=B8=D0=BE=D0=BD=D1=83,?= =?UTF-8?q?=20=D0=BD=D0=BE=20=D0=BA=D0=BB=D0=B8=D0=BA=20=D0=BF=D0=BE=20?= =?UTF-8?q?=D0=BE=D0=BF=D1=86=D0=B8=D0=BE=D0=BD=D1=83=20=D0=B2=D1=81=D0=B5?= =?UTF-8?q?=D0=B3=D0=B4=D0=B0=20=D1=83=D0=B4=D0=B0=D1=87=D0=BD=D0=BE=20?= =?UTF-8?q?=D0=BF=D1=80=D0=BE=D1=85=D0=BE=D0=B4=D0=B8=D1=82,=20=D1=85?= =?UTF-8?q?=D0=BE=D1=82=D1=8F=20=D1=8F=20=D0=B5=D0=BC=D1=83=20=D0=BA=D0=B0?= =?UTF-8?q?=D1=80=D1=82=D0=B8=D0=BD=D0=BA=D1=83=20=D0=BF=D0=BE=D0=B4=D1=81?= =?UTF-8?q?=D1=82=D0=B0=D0=B2=D0=BB=D1=8F=D0=BB=20=D0=BD=D0=B5=20=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D1=8F=D1=8E=D1=89=D1=83=D1=8E=D1=81=D1=8F,=20?= =?UTF-8?q?=D1=80=D0=B0=D0=BD=D1=8C=D1=88=D0=B5=20=D1=82=D0=B0=D0=BA=20?= =?UTF-8?q?=D0=BA=D0=B0=D0=BD=D0=B0=D0=BB=D0=BE=20=D0=BF=D1=80=D0=BE=D0=B2?= =?UTF-8?q?=D0=B5=D1=80=D1=8F=D1=82=D1=8C,=20=D1=81=D0=B5=D0=B9=D1=87?= =?UTF-8?q?=D0=B0=D1=81=20=D0=BE=D0=BD=20=D0=BC=D0=BD=D0=B5=20=D0=B2=D1=81?= =?UTF-8?q?=D0=B5=D0=B3=D0=B4=D0=B0=20=D1=82=D1=80=D1=83=20=D0=B2=D0=BE?= =?UTF-8?q?=D0=B7=D0=B2=D1=80=D0=B0=D1=89=D0=B0=D0=B5=D1=82=20=D0=BF=D0=BE?= =?UTF-8?q?=D1=87=D0=B5=D0=BC=D1=83=D1=82=D0=BE,=20=D0=BD=D0=B5=20=D0=BC?= =?UTF-8?q?=D0=BE=D0=B3=D1=83=20=D0=B4=D0=BE=D0=B3=D0=BD=D0=B0=D1=82=D1=8C?= =?UTF-8?q?=20=D1=87=D0=B5=D1=82=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- broker_manager_gui.py | 90 ++++++++++--------------------------- broker_manager_interface.py | 2 +- 2 files changed, 24 insertions(+), 68 deletions(-) diff --git a/broker_manager_gui.py b/broker_manager_gui.py index 4c2bd98..6e6232b 100644 --- a/broker_manager_gui.py +++ b/broker_manager_gui.py @@ -11,7 +11,6 @@ from broker_manager_interface import BrokerManagerInterface logger = logging.getLogger('pyFinance') -deal_time_gl = 0 def repeater(action, *args, **kvargs): @@ -22,8 +21,8 @@ def repeater(action, *args, **kvargs): return logger.debug('Check {} - False'.format(action.__name__)) - # при всех неудачных попытках кидаем исключение об ошибке - raise RuntimeError('{} setting error'.format(args[0])) + # при всех неудачных попытках кидаем исключение об ошибке + raise RuntimeError('{} setting error'.format(args[0])) class BrokerManagerGui(BrokerManagerInterface): @@ -35,6 +34,8 @@ def __init__(self, result_handler, config_file): with open(config_file, 'r') as cf: self.config = json.load(cf) + self.interval_deal_time = None + # Устанавливаем начальный опцион self.prev_option = None try: @@ -139,87 +140,42 @@ def get_field(self, field, use_mouse=False): return pyperclip.paste() def try_set_field(self, field, value, use_mouse=False): - global deal_time_gl - - # Если передали дату, узнаем время сделки - if isinstance(value, datetime.datetime): - deal_time_gl = self.get_deal_time(value) - self.set_field(field, deal_time_gl) - if self.get_field(field) == str(deal_time_gl): - return True - self.set_field(field, value) return self.get_field(field, use_mouse) == str(value) - def click_option(self, option): + def set_expiration_time(self, finish_datetime): + self.interval_deal_time = int((finish_datetime - datetime.datetime.now()).total_seconds() // 60) + return self.try_set_field('expiration_time', self.interval_deal_time) + + def click_option(self, option, screenshot): if self.prev_option == option: return True + self.prev_option = option - screenshot_1 = pyautogui.screenshot( - region=( - self.option_buttons[option].x - 5, - self.option_buttons[option].y - 5, - self.option_buttons[option].x + 5, - self.option_buttons[option].y + 5 - ) - ) - for k in range(BrokerManagerGui.TRY_COUNT): - pyautogui.click(self.option_buttons[option].x, self.option_buttons[option].y, duration=0.1) - time.sleep(3) - screenshot_2 = pyautogui.screenshot( - region=( - self.option_buttons[option].x - 5, - self.option_buttons[option].y - 5, - self.option_buttons[option].x + 5, - self.option_buttons[option].y + 5 - ) - ) - if screenshot_1 != screenshot_2: - logger.debug('Check option button {} - True'.format(option)) - return True - logger.debug('Check option button {} attempt №{} - False'.format(k, option)) - return False + pyautogui.click(self.option_buttons[option].x, self.option_buttons[option].y, duration=0.1) + time.sleep(3) + point = self.option_buttons[option] + screenshot_new = pyautogui.screenshot(region=(point.x - 5, point.y - 5, point.x + 5, point.y + 5)) + return screenshot == screenshot_new def make_deal(self, option, prognosis, summ, deal_time): - if self.is_deal: logger.info('Deal is active now, skip new deal.\n') return + point = self.option_buttons[option] + screenshot = pyautogui.screenshot(region=(point.x - 5, point.y - 5, point.x + 5, point.y + 5)) + finish_datetime = datetime.datetime.now() + datetime.timedelta(minutes=deal_time) windows_manager.activate_window('Прозрачный брокер бинарных опционов') - if not self.click_option(option): - raise RuntimeError('Option {} selection error'.format(option)) - - repeater(self.try_set_field, self, 'investment_money', summ, use_mouse=True) - repeater(self.try_set_field, self, 'expiration_time', finish_datetime) - - # for k in range(BrokerManagerGui.TRY_COUNT): - # self.set_field('investment_money', summ) - # if self.get_field('investment_money', use_mouse=True) == str(summ): - # logger.debug('Check deal summ - True') - # break - # logger.debug('Check deal summ attempt №{} - False'.format(k)) - # - # # при всех неудачных попытках ничего не делаем - # if k == (BrokerManagerGui.TRY_COUNT - 1): - # raise RuntimeError('Summ input error') - # - # for k in range(BrokerManagerGui.TRY_COUNT): - # deal_time = self.get_deal_time(finish_datetime) - # self.set_field('expiration_time', deal_time) - # if self.get_field('expiration_time') == str(deal_time): - # logger.debug('Check deal time - True') - # break - # logger.debug('Check deal time attempt №{} - False'.format(k)) - # - # # при всех неудачных попытках ничего не делаем - # if k == (BrokerManagerGui.TRY_COUNT - 1): - # raise RuntimeError('Time input error') + + repeater(self.click_option, option, screenshot) + repeater(self.try_set_field, 'investment_money', summ, use_mouse=True) + repeater(self.set_expiration_time, finish_datetime) pyautogui.click(self.prognosis_table[prognosis].x, self.prognosis_table[prognosis].y, duration=0.1) self.is_deal = True - finish_datetime = datetime.datetime.now() + datetime.timedelta(minutes=deal_time_gl) + finish_datetime = datetime.datetime.now() + datetime.timedelta(minutes=self.interval_deal_time) self.scheduler.add_job(self._get_deal_result, 'date', run_date=finish_datetime) diff --git a/broker_manager_interface.py b/broker_manager_interface.py index eedfc0f..00358ab 100644 --- a/broker_manager_interface.py +++ b/broker_manager_interface.py @@ -5,7 +5,7 @@ class BrokerManagerInterface: OPTION_LIST = ( 'AUDCAD', 'AUDJPY', 'AUDUSD', 'EURAUD', 'EURCHF', 'EURJPY', 'GBPAUD', 'GBPJPY', 'NZDJPY', 'USDCAD', 'USDJPY', - 'AUDCHF', 'AUDNZD', 'CADJPY', 'EURCAD', 'EURGBP', 'EURUSD', 'GBPCHF', 'GBPNZD', 'NZDUSD', 'USDCHF' + 'AUDCHF', 'AUDNZD', 'CADJPY', 'EURCAD', 'EURGBP', 'EURUSD', 'GBPCHF', 'GBPNZD', 'NZDUSD', 'USDCHF', 'CADCHF' ) PROGNOSIS_LIST = ('вверх', 'вниз') From e4390e4fdfee8fd1d9b4d815a53d7ddc7f9b9df3 Mon Sep 17 00:00:00 2001 From: New Nick Date: Fri, 25 Jun 2021 21:13:16 +0700 Subject: [PATCH 18/22] =?UTF-8?q?=D0=B2=D1=81=D0=B5=20=D1=81=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D0=B0=D0=BB=20=D1=87=D1=82=D0=BE=20=D1=82=D0=B0=D0=BC=20?= =?UTF-8?q?=D0=BE=D0=B1=D0=B3=D0=BE=D0=B2=D0=B0=D1=80=D0=B8=D0=B2=D0=B0?= =?UTF-8?q?=D0=BB=D0=B8,=20=D0=BA=D1=80=D0=BE=D0=BC=D0=B5=20=D1=84=D0=B8?= =?UTF-8?q?=D0=BD=D0=B8=D1=88=5F=D1=82=D0=B0=D0=B9=D0=BC,=20=D0=B2=D1=81?= =?UTF-8?q?=D0=B5=20=D1=82=D0=B0=D0=BA=D0=B8=20=D1=8F=20=D0=BF=D0=BE=D1=82?= =?UTF-8?q?=D0=BE=D0=BC=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D1=83?= =?UTF-8?q?=20=D0=B7=D0=B0=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8=D1=8F?= =?UTF-8?q?=20=D1=81=D0=B4=D0=B5=D0=BB=D0=BA=D0=B8=20=D1=81=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D0=B0=D1=8E=20=D1=81=D0=B4=D0=B5=D0=BB=D0=B0=D1=8E,=20?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=B2=D1=85=D0=BE=D0=B4=D0=BD=D1=8B=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- broker_manager_gui.py | 57 +++++++++++------------------ broker_manager_gui_nick_config.json | 4 +- 2 files changed, 24 insertions(+), 37 deletions(-) diff --git a/broker_manager_gui.py b/broker_manager_gui.py index 6e6232b..91afc0d 100644 --- a/broker_manager_gui.py +++ b/broker_manager_gui.py @@ -22,7 +22,7 @@ def repeater(action, *args, **kvargs): logger.debug('Check {} - False'.format(action.__name__)) # при всех неудачных попытках кидаем исключение об ошибке - raise RuntimeError('{} setting error'.format(args[0])) + raise RuntimeError('{} setting error'.format(action.__name__)) class BrokerManagerGui(BrokerManagerInterface): @@ -36,25 +36,6 @@ def __init__(self, result_handler, config_file): self.interval_deal_time = None - # Устанавливаем начальный опцион - self.prev_option = None - try: - self.click_option('EURUSD') - except: - pass - - self.exp_hour_buttons = geometry_2d.get_matrix( - m_size=geometry_2d.Vector(x=6, y=4), - start=geometry_2d.Vector(**self.config['buttons']['expiration_time']['first_hour']), - delta=geometry_2d.Vector(**self.config['buttons']['expiration_time']['delta']) - ) - - self.exp_minute_buttons = geometry_2d.get_matrix( - m_size=geometry_2d.Vector(x=3, y=4), - start=geometry_2d.Vector(**self.config['buttons']['expiration_time']['first_minute']), - delta=geometry_2d.Vector(**self.config['buttons']['expiration_time']['delta']) - ) - self.option_buttons = dict(zip( BrokerManagerInterface.OPTION_LIST, geometry_2d.get_matrix( @@ -72,6 +53,12 @@ def __init__(self, result_handler, config_file): ] )) + # Устанавливаем начальный опцион + self.prev_option = None + self.click_option('EURUSD') + + self.option_buttons['CADCHF'] = self.option_buttons['CADJPY'] + def _get_deal_result(self): self.is_deal = False @@ -95,10 +82,6 @@ def _get_deal_result(self): # If result not in ['LOSE', 'WIN'] return as is self.result_handler(result) - def get_deal_time(self, finish_datetime): - deal_time = int((finish_datetime - datetime.datetime.now()).total_seconds() // 60) - return deal_time - def set_field(self, field, value): pyautogui.doubleClick( self.config['fields'][field]['x'], @@ -147,30 +130,34 @@ def set_expiration_time(self, finish_datetime): self.interval_deal_time = int((finish_datetime - datetime.datetime.now()).total_seconds() // 60) return self.try_set_field('expiration_time', self.interval_deal_time) - def click_option(self, option, screenshot): + def click_option(self, option): + def click_option_button(point, screenshot): + pyautogui.click(point.x, point.y, duration=0.1) + time.sleep(3) + screenshot_new = pyautogui.screenshot(region=(point.x - 5, point.y - 5, point.x + 5, point.y + 5)) + if screenshot == screenshot_new: + return False + self.prev_option = option + return True + if self.prev_option == option: return True - self.prev_option = option - pyautogui.click(self.option_buttons[option].x, self.option_buttons[option].y, duration=0.1) - time.sleep(3) point = self.option_buttons[option] - screenshot_new = pyautogui.screenshot(region=(point.x - 5, point.y - 5, point.x + 5, point.y + 5)) - return screenshot == screenshot_new + screenshot = pyautogui.screenshot(region=(point.x - 5, point.y - 5, point.x + 5, point.y + 5)) + + repeater(click_option_button, point, screenshot) def make_deal(self, option, prognosis, summ, deal_time): if self.is_deal: logger.info('Deal is active now, skip new deal.\n') return - point = self.option_buttons[option] - screenshot = pyautogui.screenshot(region=(point.x - 5, point.y - 5, point.x + 5, point.y + 5)) + windows_manager.activate_window('Прозрачный брокер бинарных опционов') finish_datetime = datetime.datetime.now() + datetime.timedelta(minutes=deal_time) - windows_manager.activate_window('Прозрачный брокер бинарных опционов') - - repeater(self.click_option, option, screenshot) + self.click_option(option) repeater(self.try_set_field, 'investment_money', summ, use_mouse=True) repeater(self.set_expiration_time, finish_datetime) diff --git a/broker_manager_gui_nick_config.json b/broker_manager_gui_nick_config.json index ecfd0a7..09615b3 100644 --- a/broker_manager_gui_nick_config.json +++ b/broker_manager_gui_nick_config.json @@ -51,8 +51,8 @@ "y": 168 }, "result": { - "x": 983, - "y": 467 + "x": 987, + "y": 463 } }, From 8bbdc0e1db962205eaef8aa54710974b6b0f939d Mon Sep 17 00:00:00 2001 From: New Nick Date: Fri, 25 Jun 2021 21:52:43 +0700 Subject: [PATCH 19/22] =?UTF-8?q?=D0=BF=D0=BE=D0=BC=D0=B5=D0=BD=D1=8F?= =?UTF-8?q?=D0=BB=20=D0=BA=D0=B0=D0=BD=D0=B0=D0=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyFinance_v1_quotex.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyFinance_v1_quotex.py b/pyFinance_v1_quotex.py index ca8403f..4f8d692 100644 --- a/pyFinance_v1_quotex.py +++ b/pyFinance_v1_quotex.py @@ -156,9 +156,9 @@ def main(): client = TelegramClient(number, api_id, api_hash) broker_manager = BrokerManagerGui(deal_result_process, config) -#🔊 СИГНАЛЫ №1 🔊 + # создает событие, срабатывающее при появлении нового сообщения - @client.on(events.NewMessage(chats='tFinace')) + @client.on(events.NewMessage(chats='🔊 СИГНАЛЫ №1 🔊')) async def normal_handler(event): message = event.message.to_dict() message_process(message['message'], message['date'], broker_manager) From 23dff849419f5b61c80cd82087637a8148a3c292 Mon Sep 17 00:00:00 2001 From: New Nick Date: Sat, 26 Jun 2021 21:01:05 +0700 Subject: [PATCH 20/22] =?UTF-8?q?=D1=81=D0=B4=D0=B5=D0=BB=D0=B0=D0=BD=20?= =?UTF-8?q?=D0=B4=D0=B5=D0=BA=D0=BE=D1=80=D0=B0=D1=82=D0=BE=D1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- broker_manager_gui.py | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/broker_manager_gui.py b/broker_manager_gui.py index 91afc0d..8863b78 100644 --- a/broker_manager_gui.py +++ b/broker_manager_gui.py @@ -3,7 +3,6 @@ import logging import pyautogui import pyperclip -import pytz import time import geometry_2d @@ -13,16 +12,18 @@ logger = logging.getLogger('pyFinance') -def repeater(action, *args, **kvargs): - tries = 5 - for k in range(tries): - if action(*args, **kvargs): - logger.debug('Check {} - True'.format(action.__name__)) - return - logger.debug('Check {} - False'.format(action.__name__)) +def repeater(action): + def repeat_action(*args, **kvargs): + tries = 5 + for k in range(tries): + if action(*args, **kvargs): + logger.debug('Check {} - True'.format(action.__name__)) + return + logger.debug('Check {} - False'.format(action.__name__)) # при всех неудачных попытках кидаем исключение об ошибке raise RuntimeError('{} setting error'.format(action.__name__)) + return repeat_action class BrokerManagerGui(BrokerManagerInterface): @@ -54,9 +55,11 @@ def __init__(self, result_handler, config_file): )) # Устанавливаем начальный опцион - self.prev_option = None - self.click_option('EURUSD') - + self.current_option = None + try: + self.click_option('EURUSD') + except: + pass self.option_buttons['CADCHF'] = self.option_buttons['CADJPY'] def _get_deal_result(self): @@ -137,11 +140,11 @@ def click_option_button(point, screenshot): screenshot_new = pyautogui.screenshot(region=(point.x - 5, point.y - 5, point.x + 5, point.y + 5)) if screenshot == screenshot_new: return False - self.prev_option = option + self.current_option = option return True - if self.prev_option == option: - return True + if self.current_option == option: + return point = self.option_buttons[option] screenshot = pyautogui.screenshot(region=(point.x - 5, point.y - 5, point.x + 5, point.y + 5)) From 99178f665d7e3f5c0f85221ca64650b4e88e0e63 Mon Sep 17 00:00:00 2001 From: New Nick Date: Sun, 27 Jun 2021 17:09:24 +0700 Subject: [PATCH 21/22] =?UTF-8?q?=D1=81=D0=B4=D0=B5=D0=BB=D0=B0=D0=BD=20?= =?UTF-8?q?=D0=B4=D0=B5=D0=BA=D0=BE=D1=80=D0=B0=D1=82=D0=BE=D1=80,=20?= =?UTF-8?q?=D0=B2=D1=81=D0=B5=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=D0=B5?= =?UTF-8?q?=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- broker_manager_gui.py | 12 ++++++------ pyFinance_v1_quotex.py | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/broker_manager_gui.py b/broker_manager_gui.py index 8863b78..4a64f99 100644 --- a/broker_manager_gui.py +++ b/broker_manager_gui.py @@ -20,9 +20,8 @@ def repeat_action(*args, **kvargs): logger.debug('Check {} - True'.format(action.__name__)) return logger.debug('Check {} - False'.format(action.__name__)) - - # при всех неудачных попытках кидаем исключение об ошибке - raise RuntimeError('{} setting error'.format(action.__name__)) + # при всех неудачных попытках кидаем исключение об ошибке + raise RuntimeError('{} setting error'.format(action.__name__)) return repeat_action @@ -149,7 +148,8 @@ def click_option_button(point, screenshot): point = self.option_buttons[option] screenshot = pyautogui.screenshot(region=(point.x - 5, point.y - 5, point.x + 5, point.y + 5)) - repeater(click_option_button, point, screenshot) + repeater(click_option_button)(point, screenshot) + def make_deal(self, option, prognosis, summ, deal_time): if self.is_deal: @@ -161,8 +161,8 @@ def make_deal(self, option, prognosis, summ, deal_time): finish_datetime = datetime.datetime.now() + datetime.timedelta(minutes=deal_time) self.click_option(option) - repeater(self.try_set_field, 'investment_money', summ, use_mouse=True) - repeater(self.set_expiration_time, finish_datetime) + repeater(self.try_set_field)('investment_money', summ, use_mouse=True) + repeater(self.set_expiration_time)(finish_datetime) pyautogui.click(self.prognosis_table[prognosis].x, self.prognosis_table[prognosis].y, duration=0.1) self.is_deal = True diff --git a/pyFinance_v1_quotex.py b/pyFinance_v1_quotex.py index 4f8d692..ca8403f 100644 --- a/pyFinance_v1_quotex.py +++ b/pyFinance_v1_quotex.py @@ -156,9 +156,9 @@ def main(): client = TelegramClient(number, api_id, api_hash) broker_manager = BrokerManagerGui(deal_result_process, config) - +#🔊 СИГНАЛЫ №1 🔊 # создает событие, срабатывающее при появлении нового сообщения - @client.on(events.NewMessage(chats='🔊 СИГНАЛЫ №1 🔊')) + @client.on(events.NewMessage(chats='tFinace')) async def normal_handler(event): message = event.message.to_dict() message_process(message['message'], message['date'], broker_manager) From 8a8d2b06a92d8f46cccb671082bc1fcac49db2d0 Mon Sep 17 00:00:00 2001 From: New Nick Date: Wed, 30 Jun 2021 19:28:27 +0700 Subject: [PATCH 22/22] =?UTF-8?q?=D0=B4=D0=B5=D0=BA=D0=BE=D1=80=D0=B0?= =?UTF-8?q?=D1=82=D0=BE=D1=80=20=D1=87=D0=B5=D1=80=D0=B5=D0=B7=20@=20?= =?UTF-8?q?=D1=81=D0=B4=D0=B5=D0=BB=D0=B0=D0=BD=20=D1=82=D0=B5=D0=BF=D0=B5?= =?UTF-8?q?=D1=80=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- broker_manager_gui.py | 13 +++++++++---- broker_manager_gui_nick_config.json | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/broker_manager_gui.py b/broker_manager_gui.py index 4a64f99..57b3682 100644 --- a/broker_manager_gui.py +++ b/broker_manager_gui.py @@ -59,6 +59,7 @@ def __init__(self, result_handler, config_file): self.click_option('EURUSD') except: pass + self.option_buttons['CADCHF'] = self.option_buttons['CADJPY'] def _get_deal_result(self): @@ -124,15 +125,19 @@ def get_field(self, field, use_mouse=False): time.sleep(0.5) return pyperclip.paste() + @repeater def try_set_field(self, field, value, use_mouse=False): self.set_field(field, value) return self.get_field(field, use_mouse) == str(value) + @repeater def set_expiration_time(self, finish_datetime): self.interval_deal_time = int((finish_datetime - datetime.datetime.now()).total_seconds() // 60) - return self.try_set_field('expiration_time', self.interval_deal_time) + self.set_field('expiration_time', self.interval_deal_time) + return self.get_field('expiration_time') == str(self.interval_deal_time) def click_option(self, option): + @repeater def click_option_button(point, screenshot): pyautogui.click(point.x, point.y, duration=0.1) time.sleep(3) @@ -148,7 +153,7 @@ def click_option_button(point, screenshot): point = self.option_buttons[option] screenshot = pyautogui.screenshot(region=(point.x - 5, point.y - 5, point.x + 5, point.y + 5)) - repeater(click_option_button)(point, screenshot) + click_option_button(point, screenshot) def make_deal(self, option, prognosis, summ, deal_time): @@ -161,8 +166,8 @@ def make_deal(self, option, prognosis, summ, deal_time): finish_datetime = datetime.datetime.now() + datetime.timedelta(minutes=deal_time) self.click_option(option) - repeater(self.try_set_field)('investment_money', summ, use_mouse=True) - repeater(self.set_expiration_time)(finish_datetime) + self.try_set_field('investment_money', summ, use_mouse=True) + self.set_expiration_time(finish_datetime) pyautogui.click(self.prognosis_table[prognosis].x, self.prognosis_table[prognosis].y, duration=0.1) self.is_deal = True diff --git a/broker_manager_gui_nick_config.json b/broker_manager_gui_nick_config.json index 09615b3..82fe6a3 100644 --- a/broker_manager_gui_nick_config.json +++ b/broker_manager_gui_nick_config.json @@ -52,7 +52,7 @@ }, "result": { "x": 987, - "y": 463 + "y": 470 } },