Untitled

mail@pastecode.io avatar
unknown
plain_text
17 days ago
18 kB
1
Indexable
Never
Y3BOT

###

main.py

import os
from src.gui import BotGUI
import tkinter as tk
from src.loading_screen import LoadingScreen

if __name__ == "__main__":
    loading_root = tk.Tk()
    loading_screen = LoadingScreen(loading_root)
    loading_screen.update_status("Starting application...", 0)
    gui = BotGUI(loading_screen)
    loading_screen.update_status("Loading complete!", 100)
    loading_root.after(1000, loading_screen.close)
    gui.run()

###

requirements.txt

MetaTrader5==5.0.37
tk==0.1.0

###

settings.json

{"symbol": "XAUUSD", "lot": "0.01", "time_frame": "M15", "stop_loss": "80", "take_profit": "40", "preset": "scalping", "custom": {"period": "", "deviation": ""}}


###


Y3BOT.spec


# -*- mode: python ; coding: utf-8 -*-


a = Analysis(
    ['main.py'],
    pathex=[],
    binaries=[],
    datas=[],
    hiddenimports=[],
    hookspath=[],
    hooksconfig={},
    runtime_hooks=[],
    excludes=[],
    noarchive=False,
    optimize=0,
)
pyz = PYZ(a.pure)

exe = EXE(
    pyz,
    a.scripts,
    [],
    exclude_binaries=True,
    name='Y3BOT',
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,
    console=True,
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
)
coll = COLLECT(
    exe,
    a.binaries,
    a.datas,
    strip=False,
    upx=True,
    upx_exclude=[],
    name='Y3BOT',
)


###

src/bot.py

import MetaTrader5 as mt5
import pandas as pd  # Убедитесь, что вы импортируете pandas, если используете его
from src.trade_logic import TradeLogic  # Импортируйте TradeLogic из соответствующего модуля
from config.presets import Presets  # Импортируйте Presets из соответствующего модуля

class Y3BOT:
    def __init__(self, symbol, lot, time_frame, stop_loss, take_profit, preset='scalping'):
        self.symbol = symbol
        self.lot = lot
        self.time_frame = self.convert_time_frame(time_frame)
        self.stop_loss = stop_loss
        self.take_profit = take_profit
        self.preset = preset
        self.trade_logic = TradeLogic(self.symbol, self.lot, self.stop_loss, self.take_profit)
        self.preset_config = Presets.load_preset(self.preset)  # Изменено на load_preset

    def connect(self, account, server):
        if not mt5.initialize():
            print("Failed to initialize MT5")
            return False
        login_status = mt5.login(account, server=server)
        if login_status:
            account_info = mt5.account_info()
            if account_info is None:
                print("Failed to get account info")
                return False
            print(f"Connected to account: {account_info.login}, balance: {account_info.balance}")
            return True
        else:
            print("Failed to login")
            return False

    def convert_time_frame(self, time_frame):
        time_frames = {
            "M1": mt5.TIMEFRAME_M1,
            "M5": mt5.TIMEFRAME_M5,
            "M15": mt5.TIMEFRAME_M15,
            "M30": mt5.TIMEFRAME_M30,
            "H1": mt5.TIMEFRAME_H1,
            "H4": mt5.TIMEFRAME_H4,
            "D1": mt5.TIMEFRAME_D1,
        }
        return time_frames.get(time_frame, mt5.TIMEFRAME_M1)

    def get_data(self):
        rates = mt5.copy_rates_from_pos(self.symbol, self.time_frame, 0, 100)
        df = pd.DataFrame(rates)
        df['time'] = pd.to_datetime(df['time'], unit='s')
        return df

###


src/gui.py

import tkinter as tk
from tkinter import ttk
import json
import MetaTrader5 as mt5
from src.bot import Y3BOT
from config.presets import Presets
from src.loading_screen import LoadingScreen
import os

class BotGUI:
    def __init__(self, loading_screen):
        self.loading_screen = loading_screen
        self.root = tk.Tk()
        self.root.title("Y3BOT - Forex Scalping Bot")
        self.create_widgets()
        self.bot = None
        self.account_info = None  # Для хранения информации о счете

    def create_widgets(self):
        # Установка стиля
        style = ttk.Style()
        style.configure("TLabel", font=("Helvetica", 12))
        style.configure("TButton", font=("Helvetica", 12))

        self.loading_screen.update_status("Loading symbols...", 10)

        # Инициализация MetaTrader 5
        if not mt5.initialize():
            print("Ошибка инициализации MetaTrader 5")
            self.loading_screen.update_status("Ошибка инициализации MetaTrader 5", 100)
            return  # Прекращаем выполнение, если инициализация не удалась

        symbols = mt5.symbols_get()
        if symbols is None:
            print("Не удалось получить символы. Проверьте подключение к MetaTrader 5.")
            self.loading_screen.update_status("Не удалось получить символы", 100)
            return  # Прекращаем выполнение, если символы не получены

        symbols = [sym.name for sym in symbols]
        self.symbol_label = ttk.Label(self.root, text="Symbol:")
        self.symbol_label.grid(row=0, column=0)
        self.symbol_combobox = ttk.Combobox(self.root, values=symbols)
        self.symbol_combobox.grid(row=0, column=1)

        self.loading_screen.update_status("Loading time frames...", 20)
        self.time_frame_label = ttk.Label(self.root, text="Time frame:")
        self.time_frame_label.grid(row=1, column=0)
        time_frames = ["M1", "M5", "M15", "M30", "H1", "H4", "D1"]
        self.time_frame_combobox = ttk.Combobox(self.root, values=time_frames)
        self.time_frame_combobox.grid(row=1, column=1)

        self.loading_screen.update_status("Loading trading settings...", 40)
        self.lot_label = ttk.Label(self.root, text="Lot size:")
        self.lot_label.grid(row=2, column=0)
        self.lot_entry = ttk.Entry(self.root)
        self.lot_entry.grid(row=2, column=1)

        self.stop_loss_label = ttk.Label(self.root, text="Stop Loss:")
        self.stop_loss_label.grid(row=3, column=0)
        self.stop_loss_entry = ttk.Entry(self.root)
        self.stop_loss_entry.grid(row=3, column=1)

        self.take_profit_label = ttk.Label(self.root, text="Take Profit:")
        self.take_profit_label.grid(row=4, column=0)
        self.take_profit_entry = ttk.Entry(self.root)
        self.take_profit_entry.grid(row=4, column=1)

        self.preset_label = ttk.Label(self.root, text="Preset:")
        self.preset_label.grid(row=5, column=0)
        self.preset_combobox = ttk.Combobox(self.root, values=["scalping", "custom"])
        self.preset_combobox.grid(row=5, column=1)
        self.preset_combobox.bind("<<ComboboxSelected>>", self.toggle_custom_settings)

        self.custom_frame = tk.Frame(self.root)
        self.custom_frame.grid(row=6, column=0, columnspan=2)

        # Новые настройки для custom
        self.custom_period_label = ttk.Label(self.custom_frame, text="Period:")
        self.custom_period_label.grid(row=0, column=0)
        self.custom_period_entry = ttk.Entry(self.custom_frame)
        self.custom_period_entry.grid(row=0, column=1)

        self.custom_deviation_label = ttk.Label(self.custom_frame, text="Deviation:")
        self.custom_deviation_label.grid(row=1, column=0)
        self.custom_deviation_entry = ttk.Entry(self.custom_frame)
        self.custom_deviation_entry.grid(row=1, column=1)

        self.custom_frame.grid_remove()  # Скрываем кастомные настройки по умолчанию

        self.loading_screen.update_status("Loading buttons...", 70)
        self.start_button = ttk.Button(self.root, text="Start Bot", command=self.start_bot)
        self.start_button.grid(row=7, column=0, columnspan=2)

        self.info_label = ttk.Label(self.root, text="Bot Status:")
        self.info_label.grid(row=8, column=0, columnspan=2)

        self.history_label = ttk.Label(self.root, text="Trade History:")
        self.history_label.grid(row=9, column=0, columnspan=2)

        self.history_text = tk.Text(self.root, height=10, width=50)
        self.history_text.grid(row=10, column=0, columnspan=2)

        # Метка для отображения информации о счете и валютной паре
        self.account_info_label = ttk.Label(self.root, text="", font=("Helvetica", 14))
        self.account_info_label.grid(row=11, column=0, columnspan=2)

        # Поле для отладочной информации
        self.debug_text = tk.Text(self.root, height=5, width=50, state='disabled')
        self.debug_text.grid(row=12, column=0, columnspan=2)

        self.loading_screen.update_status("Finalizing...", 90)
        self.load_settings()

    def get_account_info(self):
        account_info = mt5.account_info()
        if account_info is not None:
            self.account_info = account_info
            return account_info.login, account_info.server
        else:
            print("Не удалось получить информацию об аккаунте.")
            return None, None

    def toggle_custom_settings(self, event):
        if self.preset_combobox.get() == "custom":
            self.custom_frame.grid()
        else:
            self.custom_frame.grid_remove()

    def start_bot(self):
        symbol = self.symbol_combobox.get()
        lot = float(self.lot_entry.get())
        time_frame = self.time_frame_combobox.get()
        stop_loss = float(self.stop_loss_entry.get())
        take_profit = float(self.take_profit_entry.get())
        preset = self.preset_combobox.get()

        # Получите данные для подключения
        account, server = self.get_account_info()  # Получаем информацию о счете и сервере

        if account is None or server is None:
            print("Не удалось получить информацию об аккаунте и сервере.")
            return  # Прекращаем выполнение, если информация не получена

        # Обновляем метку с информацией о счете
        self.account_info_label.config(text=f"Connected to account: {account}, Symbol: {symbol}, Time Frame: {time_frame}")

        if preset == 'custom':
            custom_config = {
                'period': int(self.custom_period_entry.get()),
                'deviation': float(self.custom_deviation_entry.get())
            }
            Presets.save_preset('custom', custom_config)

        self.bot = Y3BOT(symbol, lot, time_frame, stop_loss, take_profit, preset)
        
        # Передаем account и server в метод connect
        if self.bot.connect(account, server):
            self.bot.run()  # Запускаем бота
            self.log_debug("Bot started.")

    def stop_bot(self):
        if self.bot:
            self.bot.stop()  # Останавливаем бота
            self.log_debug("Bot stopped.")

    def log_debug(self, message):
        self.debug_text.config(state='normal')
        self.debug_text.insert(tk.END, message + "\n")
        self.debug_text.config(state='disabled')
        self.debug_text.see(tk.END)  # Прокручиваем текстовое поле вниз

    def save_settings(self):
        settings = {
            'symbol': self.symbol_combobox.get(),
            'lot': self.lot_entry.get(),
            'time_frame': self.time_frame_combobox.get(),
            'stop_loss': self.stop_loss_entry.get(),
            'take_profit': self.take_profit_entry.get(),
            'preset': self.preset_combobox.get(),
            'custom': {
                'period': self.custom_period_entry.get(),
                'deviation': self.custom_deviation_entry.get()
            }
        }
        with open('settings.json', 'w') as f:
            json.dump(settings, f)

    def load_settings(self):
        try:
            with open('settings.json', 'r') as f:
                settings = json.load(f)
                self.symbol_combobox.set(settings['symbol'])
                self.lot_entry.insert(0, settings['lot'])
                self.time_frame_combobox.set(settings['time_frame'])
                self.stop_loss_entry.insert(0, settings['stop_loss'])
                self.take_profit_entry.insert(0, settings['take_profit'])
                self.preset_combobox.set(settings['preset'])

                if settings['preset'] == 'custom':
                    self.custom_period_entry.insert(0, settings['custom']['period'])
                    self.custom_deviation_entry.insert(0, settings['custom']['deviation'])
                    self.custom_frame.grid()
        except FileNotFoundError:
            pass

    def run(self):
        self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
        self.root.mainloop()

    def on_closing(self):
        self.save_settings()
        self.stop_bot()
        mt5.shutdown()  # Закрываем соединение с MetaTrader 5
        self.root.destroy()


class Y3BOT:
    def __init__(self, symbol, lot, time_frame, stop_loss, take_profit, preset):
        self.symbol = symbol
        self.lot = lot
        self.time_frame = time_frame
        self.stop_loss = stop_loss
        self.take_profit = take_profit
        self.preset = preset
        self.running = False

    def connect(self, account, server):
        # Здесь добавьте логику для подключения к аккаунту
        print(f"Connected to account: {account}, server: {server}")
        return True  # Возвращаем True, если подключение успешно

    def run(self):
        self.running = True
        print("Бот запущен.")
        # Здесь добавьте логику для работы бота

    def stop(self):
        self.running = False
        print("Бот остановлен.")


###

src/loading_screen.py

import tkinter as tk
from tkinter import ttk

class LoadingScreen:
    def __init__(self, root):
        self.root = root
        self.root.title("Loading Y3BOT...")
        self.progress = ttk.Progressbar(root, orient=tk.HORIZONTAL, length=300, mode='determinate')
        self.progress.pack(pady=20)
        self.status_label = tk.Label(root, text="Initializing...")
        self.status_label.pack(pady=10)

    def update_status(self, status, progress):
        self.status_label.config(text=status)
        self.progress['value'] = progress
        self.root.update_idletasks()

    def close(self):
        self.root.destroy()

src/strategies.py

import pandas as pd

class BollingerBandsStrategy:
    @staticmethod
    def apply(df, period=20, deviation=2):
        df['ma'] = df['close'].rolling(window=period).mean()
        df['std'] = df['close'].rolling(window=period).std()
        df['upper'] = df['ma'] + (df['std'] * deviation)
        df['lower'] = df['ma'] - (df['std'] * deviation)
        return df

    @staticmethod
    def generate_signal(df):
        if df['close'].iloc[-1] > df['upper'].iloc[-1]:
            return 'sell'
        elif df['close'].iloc[-1] < df['lower'].iloc[-1]:
            return 'buy'
        return None

###

src/trade_logic.py

import MetaTrader5 as mt5
from src.strategies import BollingerBandsStrategy

class TradeLogic:
    def __init__(self, symbol, lot, stop_loss, take_profit):
        self.symbol = symbol
        self.lot = lot
        self.stop_loss = stop_loss
        self.take_profit = take_profit

    def analyze(self, df, preset_config):
        df = BollingerBandsStrategy.apply(df)
        signal = BollingerBandsStrategy.generate_signal(df)
        return signal

    def execute_trade(self, signal):
        if signal == 'buy':
            order = mt5.ORDER_TYPE_BUY
        elif signal == 'sell':
            order = mt5.ORDER_TYPE_SELL
        else:
            return

        price = mt5.symbol_info_tick(self.symbol).ask if order == mt5.ORDER_TYPE_BUY else mt5.symbol_info_tick(self.symbol).bid
        request = {
            "action": mt5.TRADE_ACTION_DEAL,
            "symbol": self.symbol,
            "volume": self.lot,
            "type": order,
            "price": price,
            "sl": price - self.stop_loss if signal == 'buy' else price + self.stop_loss,
            "tp": price + self.take_profit if signal == 'buy' else price - self.take_profit,
            "deviation": 10,
            "magic": 234000,
            "comment": "Y3BOT trade",
            "type_time": mt5.ORDER_TIME_GTC,
            "type_filling": mt5.ORDER_FILLING_IOC,
        }
        result = mt5.order_send(request)
        if result.retcode != mt5.TRADE_RETCODE_DONE:
            print(f"Order failed, retcode={result.retcode}")


###

config/presets.py

import json
import os

class Presets:
    presets_file = 'config/presets.json'  # Изменено, чтобы учитывать правильный путь

    @staticmethod
    def load_preset(preset_name):
        presets = Presets.load_presets()
        return presets.get(preset_name, {})

    @staticmethod
    def save_preset(preset_name, preset_data):
        presets = Presets.load_presets()
        presets[preset_name] = preset_data
        with open(Presets.presets_file, 'w') as f:
            json.dump(presets, f)

    @staticmethod
    def load_presets():
        try:
            with open(Presets.presets_file, 'r') as f:
                return json.load(f)
        except FileNotFoundError:
            return {}
Leave a Comment