latest

🧩 Syntax:
from datetime import datetime
from time import sleep

from pandas.plotting import register_matplotlib_converters
import MetaTrader5 as mt5

if not mt5.initialize(): # mt5.initialize('C:/Program Files/MetaTrader 5/terminal.exe'):
    print("initialize() failed")
    mt5.shutdown()

print(mt5.terminal_info())
print(mt5.version())
# mt5.login('41282', password='fquuiv2d', server='PMEX-Demo', )

# connect to the trade account without specifying a password and a server
account = 41447
password = "aj3spdyp"

# account = 41468
# password = "o3nfwqbm"

authorized = mt5.login(account, password=password,
                       server='PMEX-Demo')  # the terminal database password is applied if connection data is set to be remembered
if authorized:
    print("connected to account #{}".format(account))
else:
    print("failed to connect at account #{}, error code: {}".format(account, mt5.last_error()))

price_of_each_step = 0.3
first_order_price_deviation = 0.4

stop_loss_price_deviation = 0.5

first_buy_order_lot_size = 10.0  # set to 10
second_buy_order_lot_size = 5.0  # set to 5
other_buy_order_lot_size = 2.0  # set to 2

first_sell_order_lot_size = 10.0  # set to 10
second_sell_order_lot_size = 5.0  # set to 5
other_sell_order_lot_size = 2.0  # set to 2

deviation = 20  # mt5 setting

# ----------------------Program Vars-------------------------------
# ----------------------DO NOT EDIT--------------------------------

# When either stop losses are executed then reset all orders
buy_stop_loss_execution_price = 0
sell_stop_loss_execution_price = 0

first_buy_execution_price = 0
first_sell_execution_price = 0
first_buy_executed = False
first_sell_executed = False
first_buy_ticket_id = 0
first_sell_ticket_id = 0

open_position_buy_ticket_id = 0
open_position_sell_ticket_id = 0


def on_price_change_handler(current_price):
    # Update first_buy_executed and first_sell_stop_executed
    global first_buy_ticket_id
    global first_sell_ticket_id
    global open_position_buy_ticket_id
    global open_position_sell_ticket_id
    global highest_price
    global lowest_price

    is_first_buy_order_executed = False
    is_first_sell_order_executed = False

    if bool(first_buy_ticket_id):
        is_first_buy_order_executed = False if mt5.orders_get(ticket=first_buy_ticket_id) else True
    if bool(first_sell_ticket_id):
        is_first_sell_order_executed = False if mt5.orders_get(ticket=first_sell_ticket_id) else True

    if bool(first_buy_ticket_id):
        first_buy_ticket_id = 0
        if is_first_buy_order_executed:
            delete_all_orders(type="sell")

    if bool(first_sell_ticket_id):
        first_sell_ticket_id = 0
        if is_first_sell_order_executed:
            delete_all_orders(type="buy")

    open_positions = mt5.positions_get()

    buy_positions = [i for i in open_positions if i.type == 0]
    sell_positions = [i for i in open_positions if i.type == 1]

    if buy_positions:
        if not bool(open_position_buy_ticket_id):
            open_position_buy_ticket_id = buy_positions[0].ticket

            stop_loss = current_price - stop_loss_price_deviation
            change_stop_loss_all_orders(new_stop_loss_price=stop_loss, type='buy')
    else:
        # Maybe a position existed previously but the stop loss was hit, and its gone now
        if bool(open_position_buy_ticket_id):
            # If Buy Stop Loss order is executed(Price falls below buy_stop_loss_execution_price)
            open_position_buy_ticket_id = 0  # we set to position to null, if it existed
            highest_price = current_price
            lowest_price = current_price

            delete_and_rebuild_all_orders()
            sleep(1)

    if sell_positions:
        if not bool(open_position_sell_ticket_id):
            open_position_sell_ticket_id = sell_positions[0].ticket
            stop_loss = current_price + stop_loss_price_deviation
            change_stop_loss_all_orders(new_stop_loss_price=stop_loss, type='sell')
    else:
        # Maybe a position existed previously but the stop loss was hit, and its gone now
        if bool(open_position_sell_ticket_id):
            # If Sell Stop Loss order is executed(Price Increases above sell_stop_loss_execution_price)
            open_position_sell_ticket_id = 0  # we set to position to null, if it existed
            highest_price = current_price
            lowest_price = current_price
            delete_and_rebuild_all_orders()
            sleep(1)


def on_highest_price_change_handler(current_price):
    stop_loss = current_price - stop_loss_price_deviation
    change_stop_loss_all_orders(stop_loss, type='buy')


def on_lowest_price_change_handler(current_price):
    stop_loss = current_price + stop_loss_price_deviation
    change_stop_loss_all_orders(stop_loss, type='sell')


def process_post_order_execution(result, lot, price):
    if not result:
        print(f"Failed to place order error code: {mt5.last_error()}")
        # mt5.shutdown()
        # quit()
    # check the execution result
    # print("1. order_send(): by {} {} lots at {} with deviation={} points".format(symbol, lot, price, deviation))
    if result.retcode != mt5.TRADE_RETCODE_DONE:
        # print("2. order_send failed, retcode={}".format(result.retcode))

        result_dict = result._asdict()
        for field in result_dict.keys():
            # print("   {}={}".format(field, result_dict[field]))

            if field == "request":
                traderequest_dict = result_dict[field]._asdict()
                for tradereq_filed in traderequest_dict:
                    # print("       traderequest: {}={}".format(tradereq_filed, traderequest_dict[tradereq_filed]))
                    pass
        print("Don't shutdown() and quit")
        # mt5.shutdown()
        # quit()
    else:
        print("2. order_send done, ")
        print("   opened position with POSITION_TICKET={}".format(result.order))


def place_buy_stop_order(symbol, lot, price, stop_loss, is_first=False):
    request = {
        "action": mt5.TRADE_ACTION_PENDING,
        "symbol": symbol,
        "volume": lot,
        "type": mt5.ORDER_TYPE_BUY_STOP,
        "price": price,

        "deviation": deviation,
        # "magic": 234000,
        "comment": "python script open",
        "type_time": mt5.ORDER_TIME_GTC,
        "type_filling": mt5.ORDER_FILLING_RETURN,
    }

    # send a trading request
    result = mt5.order_send(request)
    if is_first:
        global first_buy_ticket_id
        first_buy_ticket_id = result.order
    process_post_order_execution(result, lot, price)


def place_sell_stop_order(symbol, lot, price, stop_loss, is_first=False):
    request = {
        "action": mt5.TRADE_ACTION_PENDING,
        "symbol": symbol,
        "volume": lot,
        "type": mt5.ORDER_TYPE_SELL_STOP,
        "price": price,

        "deviation": deviation,
        # "magic": 234000,
        "comment": "python script open",
        "type_time": mt5.ORDER_TIME_GTC,
        "type_filling": mt5.ORDER_FILLING_RETURN,
    }

    # send a trading request
    result = mt5.order_send(request)
    if is_first:
        global first_sell_ticket_id
        first_sell_ticket_id = result.order
    process_post_order_execution(result, lot, price)


def change_stop_loss_all_orders(new_stop_loss_price, type='buy'):
    # orders = mt5.orders_get(symbol=symbol)
    positions = mt5.positions_get(symbol=symbol)
    # type=4 is BUY Stop
    if positions is None:
        print(f"No Positions on {symbol}, error code={mt5.last_error()}")
    else:
        print(f"Total Positions on {symbol}:", len(positions))
        # display all active orders
        for position in positions:
            request = {
                'action': mt5.TRADE_ACTION_SLTP,
                "symbol": symbol,
                "volume": position.volume,
                'price_open': position.price_open,
                'sl': new_stop_loss_price,
                "comment": "python script modify",
                'ticket': position.ticket,
                'ENUM_ORDER_STATE': mt5.ORDER_FILLING_RETURN
                # Old Details
                # "price": order.price_open,
            }
            if position.type == 0 and type == 'buy':
                # request['action'] = mt5.POSITION_TYPE_BUY
                mt5.order_send(request)
                print(
                    f"Modified Stop Loss on #{position.ticket}, Old Price: {position.sl} ---> New Price:{new_stop_loss_price}")
            elif position.type == 1 and type == 'sell':
                # request['action'] = mt5.POSITION_TYPE_SELL
                mt5.order_send(request)
                print(
                    f"Modified Stop Loss on #{position.ticket}, Old Price: {position.sl} ---> New Price:{new_stop_loss_price}")


def delete_all_orders(type='buy'):
    orders = mt5.orders_get(symbol=symbol)
    # type=4 is BUY Stop
    if orders is None:
        print(f"No orders on {symbol}, error code={mt5.last_error()}")
    else:
        print(f"Total orders on {symbol}:", len(orders))
        # display all active orders
        for order in orders:
            request = {
                "action": mt5.TRADE_ACTION_REMOVE,
                'order': order.ticket,
                "comment": "python script delete",
            }
            if order.type == 4 and type == 'buy':
                mt5.order_send(request)
            elif order.type != 4 and type == 'sell':
                mt5.order_send(request)
            print(f"Deleted #{order.ticket}")


def place_list_of_orders(current_price, type='buy'):
    if type == "buy":

        first_order_price = current_price + first_order_price_deviation  # (price_of_each_step * no_of_steps)
        second_order_price = first_order_price + price_of_each_step
        subsequent_order_price = second_order_price + price_of_each_step
        global first_buy_execution_price
        first_buy_execution_price = first_order_price
        stop_loss = first_order_price - stop_loss_price_deviation

        global buy_stop_loss_execution_price
        buy_stop_loss_execution_price = stop_loss
    else:

        first_order_price = current_price - first_order_price_deviation # (price_of_each_step * no_of_steps)
        second_order_price = first_order_price - price_of_each_step
        subsequent_order_price = second_order_price - price_of_each_step
        global first_sell_execution_price
        first_sell_execution_price = first_order_price
        stop_loss = first_order_price + stop_loss_price_deviation

        global sell_stop_loss_execution_price
        sell_stop_loss_execution_price = stop_loss

    # First Order
    if type == "buy":
        place_buy_stop_order(symbol, first_buy_order_lot_size, first_order_price, stop_loss, is_first=True)
    else:
        place_sell_stop_order(symbol, first_sell_order_lot_size, first_order_price, stop_loss, is_first=True)

    # Second Order
    if type == "buy":
        place_buy_stop_order(symbol, second_buy_order_lot_size, second_order_price, stop_loss)
    else:
        place_sell_stop_order(symbol, second_sell_order_lot_size, second_order_price, stop_loss)

    # Subsequent Orders
    for i in range(1, 10):
        if type == "buy":
            place_buy_stop_order(symbol, other_buy_order_lot_size, subsequent_order_price, stop_loss)
            subsequent_order_price += price_of_each_step
        else:
            place_sell_stop_order(symbol, other_sell_order_lot_size, subsequent_order_price, stop_loss)
            subsequent_order_price -= price_of_each_step


def delete_and_rebuild_all_orders():
    sleep(0.1)
    delete_all_orders(type='sell')
    sleep(0.2)
    delete_all_orders(type='buy')

    sleep(0.5)
    place_list_of_orders(current_price, type='buy')
    sleep(0.3)
    place_list_of_orders(current_price, type='sell')


symbol = "GO1OZ-AU23"
highest_price = 0
lowest_price = 0

no_of_orders = 0

print('Balance')
o = 0
is_initial_operations_done = False

while True:
    selected = mt5.symbol_select(symbol, True)
    if not selected:
        print(f"Failed to select {symbol}")
        mt5.shutdown()
        quit()

    symbol_info = mt5.symbol_info(symbol)

    if symbol_info is None:
        print(symbol, "not found, can not call order_check()")
        mt5.shutdown()
        quit()

    # if the symbol is unavailable in MarketWatch, add it
    if not symbol_info.visible:
        print(symbol, "is not visible, trying to switch on")
        if not mt5.symbol_select(symbol, True):
            print("symbol_select({}}) failed, exit", symbol)
            mt5.shutdown()
            quit()

    current_price = symbol_info.bid
    on_price_change_handler(current_price)
    if current_price > highest_price or not highest_price:
        highest_price = current_price
        print(f'Price to Sell at (First Order): {highest_price - first_order_price_deviation}')

        # Delete all sell orders at previous prices
        # and place new orders at latest price deviations
        if is_initial_operations_done:
            on_highest_price_change_handler(current_price)

    if current_price < lowest_price or not lowest_price:
        lowest_price = current_price
        print(f'Price to Buy at (First Order): {lowest_price + first_order_price_deviation}')

        # Delete all buy orders at previous prices
        # and place new orders at latest price deviations
        if is_initial_operations_done:
            on_lowest_price_change_handler(current_price)

    # Place orders even before the price touches the point
    # Keep Modifying the orders, by trailing the price
    if not is_initial_operations_done:
        delete_and_rebuild_all_orders()

        print(f"buy_stop_loss_execution_price: {buy_stop_loss_execution_price}")
        print(f"sell_stop_loss_execution_price: {sell_stop_loss_execution_price}")
        is_initial_operations_done = True

    # If Buy Stop Loss order is executed(Price falls below buy_stop_loss_execution_price)
    if current_price <= buy_stop_loss_execution_price:
        if first_buy_executed:
            highest_price = current_price
            lowest_price = current_price

            delete_and_rebuild_all_orders()
            sleep(1)
            first_buy_executed = False
        pass

    # If Sell Stop Loss order is executed(Price Increases above sell_stop_loss_execution_price)
    if current_price >= sell_stop_loss_execution_price:
        if first_sell_executed:
            highest_price = current_price
            lowest_price = current_price

            delete_and_rebuild_all_orders()
            sleep(1)
            first_sell_executed = False
            pass