AminHP / gym-mtsim

A general-purpose, flexible, and easy-to-use simulator alongside an OpenAI Gym trading environment for MetaTrader 5 trading platform (Approved by OpenAI Gym)
MIT License
412 stars 101 forks source link

Stop Loss & Take Profit #27

Closed philreyp closed 1 year ago

philreyp commented 1 year ago

Hi @AminHP I would appreciate if you could provide example on how to implement stop loss and take profit just like in metatrader5.

Thanks,

AminHP commented 1 year ago

Hi @philreyp, I actually was thinking about adding this feature to the simulator a few months ago. But I haven't had enough time to make it yet. In the next few days, I will try to give you a quick implementation that brings some good intuitions.

philreyp commented 1 year ago

Thanks @AminHP much appreciated.

AminHP commented 1 year ago

Here is a simple code for SL and TP:

sim = MtSimulator(balance=10000)
sim.load_symbols('...')
sim_index = sim.symbols_data['EURUSD'].index
minute_count = 20 * 24 * 60
end_offset = 3 * 24 * 60
start_index = 10 * 12 * (20 * 24 * 60)
sim.current_time = sim_index[start_index]

tp_threshold = 0.0030
sl_threshold = 0.0030
order_volume = 0.01

for i in range(minute_count + end_offset):
    for order in sim.orders.copy():
        current_price = sim.price_at('EURUSD', sim.current_time)
        close_order = False
        # print(order.id, order.type, order.entry_price, current_price['High'], current_price['Low'])

        if order.type == OrderType.Buy:
            if current_price['Low'] <= order.entry_price - sl_threshold:  # SL
                close_order = True
                # print(order.id, 'buy SL')
            elif current_price['High'] >= order.entry_price + tp_threshold:  # TP
                close_order = True
                # print(order.id, 'buy TP')

        if order.type == OrderType.Sell:
            if current_price['High'] >= order.entry_price + sl_threshold:  # SL
                close_order = True
                # print(order.id, 'sell SL')
            elif current_price['Low'] <= order.entry_price - tp_threshold:  # TP
                close_order = True
                # print(order.id, 'sell TP')

        if close_order:
            sim.close_order(order)

    if i <= minute_count:
        if np.random.uniform() < 0.05:
            sim.create_order(order_type=OrderType.Buy, symbol='EURUSD', volume=order_volume, fee=0.0003)

        if np.random.uniform() < 0.05:
            sim.create_order(order_type=OrderType.Sell, symbol='EURUSD', volume=order_volume, fee=0.0003)

    sim.tick(sim_index[start_index + i + 1] - sim_index[start_index + i])

Note that you can create/close orders using the env.step method instead of sim.create_order and sim.close_order in case you need the visualization and other features.

philreyp commented 1 year ago

Thank you very much @AminHP I'd like to clarify when we use sim.close_order(order), the reward is calculated based on close price of that tick and not the SL/TP?

AminHP commented 1 year ago

That's right. It is calculated based on the close price. If you want to be more precise, I suggest you use minutely data, but change the tick value to one day (for daily trading).