Files
Place-Order-Trading-Bot/placedOrderBot.ipynb
T
2025-05-27 13:23:26 +02:00

73 KiB

Setup

Import Libaries

In [1]:
import pandas as pd
import MetaTrader5 as mt
import time
import re
import keyring as kr

Login

In [2]:
# login to your Trading Account - sign up in the description
mt.initialize()
    
login = 10730196
server = 'VantageInternational-Demo'
password = kr.get_password(server, str(login))


mt.login(login, password, server)
Out [2]:
False

Set Symbol

In [3]:
symbol = 'XAUUSD'

Calculate

Get Alltimehigh

In [6]:
ohlc = mt.copy_rates_from_pos(symbol, mt.TIMEFRAME_D1, 0, 60)
ohlc_df = pd.DataFrame(ohlc)
ohlc_df['time']=pd.to_datetime(ohlc_df['time'], unit='s')
ohlc_df
Out [6]:
time open high low close tick_volume spread real_volume
0 2025-02-21 2938.70 2949.74 2916.75 2935.95 159274 18 0
1 2025-02-24 2935.19 2956.22 2921.30 2952.46 171870 18 0
2 2025-02-25 2952.42 2953.75 2888.18 2914.93 198402 18 0
3 2025-02-26 2915.06 2930.16 2890.77 2916.36 158179 18 0
4 2025-02-27 2916.73 2920.82 2867.77 2877.15 207221 18 0
5 2025-02-28 2877.31 2885.07 2832.62 2859.03 224045 18 0
6 2025-03-03 2856.18 2895.21 2855.57 2893.66 205740 18 0
7 2025-03-04 2892.77 2927.81 2881.92 2917.65 214258 18 0
8 2025-03-05 2917.84 2929.88 2894.34 2919.11 231043 18 0
9 2025-03-06 2919.52 2926.51 2891.20 2911.01 219058 18 0
10 2025-03-07 2911.39 2930.42 2896.78 2912.06 225312 18 0
11 2025-03-10 2911.25 2918.22 2880.22 2889.02 220535 18 0
12 2025-03-11 2888.82 2922.13 2880.30 2916.08 175258 18 0
13 2025-03-12 2915.66 2940.48 2906.11 2933.24 170540 18 0
14 2025-03-13 2934.10 2989.05 2932.89 2989.01 177969 18 0
15 2025-03-14 2989.31 3004.93 2978.46 2986.39 197059 18 0
16 2025-03-17 2984.83 3001.86 2982.13 3001.42 155946 18 0
17 2025-03-18 3001.16 3038.25 2999.39 3034.08 179165 18 0
18 2025-03-19 3033.89 3051.96 3022.79 3047.26 174636 18 0
19 2025-03-20 3047.96 3057.46 3025.69 3044.64 200333 18 0
20 2025-03-21 3044.55 3047.43 2999.46 3023.15 185542 18 0
21 2025-03-24 3021.99 3033.33 3002.46 3011.81 193224 18 0
22 2025-03-25 3011.62 3035.94 3007.55 3020.34 153347 18 0
23 2025-03-26 3019.39 3032.03 3012.34 3018.96 162718 18 0
24 2025-03-27 3019.37 3059.67 3017.60 3056.73 196828 18 0
25 2025-03-28 3056.57 3086.76 3054.19 3084.56 187584 18 0
26 2025-03-31 3086.34 3127.96 3076.77 3124.07 209942 18 0
27 2025-04-01 3122.98 3148.96 3100.79 3114.26 206537 18 0
28 2025-04-02 3113.80 3143.32 3105.20 3133.56 188846 18 0
29 2025-04-03 3142.25 3167.64 3054.21 3113.32 313074 0 0
30 2025-04-04 3114.54 3136.61 3015.79 3038.42 252778 18 0
31 2025-04-07 3008.62 3055.38 2956.52 2982.60 212668 0 0
32 2025-04-08 2983.16 3022.64 2974.72 2982.34 185173 18 0
33 2025-04-09 2983.48 3099.46 2969.98 3082.91 253727 18 0
34 2025-04-10 3083.53 3176.29 3071.39 3175.77 184496 18 0
35 2025-04-11 3175.72 3245.34 3175.71 3237.59 187568 18 0
36 2025-04-14 3226.90 3245.72 3193.72 3210.36 157467 18 0
37 2025-04-15 3211.18 3233.55 3210.02 3229.79 115741 18 0
38 2025-04-16 3231.04 3342.39 3229.80 3342.26 172558 18 0
39 2025-04-17 3343.13 3357.71 3283.98 3327.48 162159 18 0
40 2025-04-21 3332.68 3430.48 3328.90 3424.67 165503 18 0
41 2025-04-22 3424.07 3500.04 3366.85 3381.28 205173 18 0
42 2025-04-23 3353.28 3386.63 3260.21 3288.34 193560 18 0
43 2025-04-24 3288.51 3367.41 3288.45 3349.38 160771 18 0
44 2025-04-25 3350.42 3370.71 3265.04 3318.69 240555 18 0
45 2025-04-28 3325.13 3353.00 3267.94 3344.17 213198 18 0
46 2025-04-29 3344.69 3348.61 3299.62 3317.22 191465 18 0
47 2025-04-30 3313.76 3328.09 3266.90 3288.42 208859 18 0
48 2025-05-01 3289.21 3290.16 3201.96 3237.99 206881 18 0
49 2025-05-02 3238.70 3269.22 3222.86 3240.37 208163 18 0
50 2025-05-05 3239.47 3337.61 3237.41 3334.06 205296 18 0
51 2025-05-06 3336.22 3434.81 3323.37 3430.38 246511 18 0
52 2025-05-07 3438.23 3438.23 3360.23 3364.25 243602 18 0
53 2025-05-08 3366.16 3414.76 3288.71 3306.36 245009 18 0
54 2025-05-09 3304.70 3347.49 3274.74 3327.21 217656 18 0
55 2025-05-12 3287.15 3314.28 3207.77 3234.28 270255 18 0
56 2025-05-13 3236.58 3265.64 3215.87 3250.02 202239 18 0
57 2025-05-14 3249.88 3257.07 3168.02 3178.08 242008 18 0
58 2025-05-15 3177.50 3240.56 3120.75 3240.35 234795 18 0
59 2025-05-16 3240.30 3252.17 3206.50 3217.14 42203 18 0
In [7]:
# alltime high, low - last 60 days
ath_df = ohlc_df.iloc[ohlc_df['high'].idxmax()]
ath = round(ath_df['high'],0)
atl = round(ath_df['low'],0)
ath, atl
Out [7]:
(3500.0, 3367.0)
In [8]:
#lastday high, low
ldh = ohlc_df.iloc[-2]['high']
ldl = ohlc_df.iloc[-2]['low']
ldh, ldl
Out [8]:
(3240.56, 3120.75)
In [9]:
#today high, low
tdh = ohlc_df.iloc[-1]['high']
tdl = ohlc_df.iloc[-1]['low']
tdh ,tdl
Out [9]:
(3252.17, 3206.5)

Get High and Low last 5 Minutes intervall - 75 candles

In [10]:
def tp_sl():
    ohlc = mt.copy_rates_from_pos('XAUUSD', mt.TIMEFRAME_M5, 1, 75)
    ohlc_df = pd.DataFrame(ohlc)
    ohlc_df['time']=pd.to_datetime(ohlc_df['time'], unit='s')


    # Create a column to mark the start of 5-minute intervals
    ohlc_df['box_start'] = (ohlc_df['time'].dt.minute % 15 == 0).astype(int)
    # Create columns for rolling maximum and minimum over the last 5 candles, excluding the current candle
    ohlc_df['max_box'] = ohlc_df['high'].shift(1).rolling(window=15).max()
    ohlc_df['min_box'] = ohlc_df['low'].shift(1).rolling(window=15).min()
    # Breaking signal
    #ohlc_df["Break_signal"] =  (ohlc_df["close"] > ohlc_df["max_box"]).astype(int) * 2 + (ohlc_df["close"] < ohlc_df["min_box"]).astype(int)
    #print(ohlc_df['max_box'][14].astype(int)*2)

    return ohlc_df
In [11]:
lastchart = tp_sl()
lastchart = lastchart.drop(lastchart[lastchart.box_start != 1].index)
lastchart
Out [11]:
time open high low close tick_volume spread real_volume box_start max_box min_box
2 2025-05-16 01:30:00 3246.72 3246.72 3244.33 3245.02 305 18 0 1 NaN NaN
5 2025-05-16 01:45:00 3249.78 3250.68 3247.90 3249.74 526 18 0 1 NaN NaN
8 2025-05-16 02:00:00 3251.21 3251.24 3242.27 3243.55 740 18 0 1 NaN NaN
11 2025-05-16 02:15:00 3248.13 3248.19 3243.21 3244.53 358 18 0 1 NaN NaN
14 2025-05-16 02:30:00 3243.08 3246.99 3242.67 3246.49 399 18 0 1 NaN NaN
17 2025-05-16 02:45:00 3238.98 3239.07 3237.60 3238.15 364 18 0 1 3252.17 3237.40
20 2025-05-16 03:00:00 3237.15 3240.84 3236.41 3240.33 763 18 0 1 3252.17 3236.56
23 2025-05-16 03:15:00 3238.95 3239.78 3238.19 3239.46 486 18 0 1 3251.24 3233.44
26 2025-05-16 03:30:00 3234.54 3234.72 3232.00 3232.81 588 18 0 1 3248.19 3233.43
29 2025-05-16 03:45:00 3236.20 3238.70 3235.08 3237.08 525 18 0 1 3246.99 3232.00
32 2025-05-16 04:00:00 3243.13 3244.47 3235.03 3236.75 926 18 0 1 3243.93 3232.00
35 2025-05-16 04:15:00 3231.04 3231.04 3223.49 3223.49 828 18 0 1 3244.47 3228.72
38 2025-05-16 04:30:00 3223.44 3227.52 3221.57 3227.34 786 18 0 1 3244.47 3221.68
41 2025-05-16 04:45:00 3221.39 3221.41 3215.52 3215.67 777 18 0 1 3244.47 3220.25
44 2025-05-16 05:00:00 3222.27 3225.92 3221.82 3224.69 757 18 0 1 3244.47 3215.10
47 2025-05-16 05:15:00 3223.19 3224.83 3222.94 3224.68 451 18 0 1 3244.47 3215.10
50 2025-05-16 05:30:00 3223.11 3227.51 3222.85 3226.93 667 18 0 1 3231.04 3215.10
53 2025-05-16 05:45:00 3220.09 3220.92 3217.72 3217.95 556 18 0 1 3228.25 3215.10
56 2025-05-16 06:00:00 3215.47 3217.41 3210.82 3215.08 731 18 0 1 3227.51 3212.91
59 2025-05-16 06:15:00 3207.98 3210.37 3206.91 3210.31 737 18 0 1 3227.51 3206.50
62 2025-05-16 06:30:00 3210.53 3213.23 3209.67 3212.29 570 18 0 1 3227.51 3206.50
65 2025-05-16 06:45:00 3208.76 3210.77 3208.04 3210.53 450 18 0 1 3227.51 3206.50
68 2025-05-16 07:00:00 3211.77 3213.45 3211.72 3213.44 409 18 0 1 3220.92 3206.50
71 2025-05-16 07:15:00 3214.96 3215.87 3212.93 3215.55 464 18 0 1 3217.41 3206.50
74 2025-05-16 07:30:00 3214.64 3216.83 3214.51 3216.18 336 18 0 1 3219.38 3206.91
In [12]:
current_high = lastchart['high'].iloc[-1]
current_close = lastchart['close'].iloc[-1]
#sl = lastchart['min_box'][23] - tp_sl_ratio  * (current_high - current_close) # SL at the high of the current candle
#tp = lastchart['max_box'][23] + tp_sl_ratio * (current_high - current_close)
current_diff = lastchart.max_box.max() - lastchart.min_box.min()
lastchart.max_box.max() - lastchart.min_box.min()

#current_close, current_high
Out [12]:
45.67000000000007
In [13]:
last_max = lastchart.max_box.mean()
last_min = lastchart.min_box.mean()
mean_high = round((ath + tdh + ldh + last_max) / 4, 2)
mean_low = round((atl + tdl + ldl + last_min) / 4, 2)
mean_high, mean_low, last_max, last_min
Out [13]:
(3307.48, 3228.42, 3237.2039999999997, 3219.41)

Fibanaccio retracement

The Fibonacci retracement strategy is a popular technical analysis tool to identify potential reversal levels in financial markets and is used by traders. Based on the Fibonacci sequence, this strategy involves plotting key retracement levels. The typical or default levels are 23.6%, 38.2%, 50%, 61.8%, and 78.6%, against a price movement.

  • Total up move = $250 - $200 = $50 38.2% of up move = 38.2% * 50 = $19.1
  • Retracement forecast = $250 - $19.1 = $230.9

e.g.:

res = AllTimeHigh - LastDayLow fb1 = round(AllTimeHigh - (res * 0.236))

The ratios 38.2% and 61.8% are the most important support levels.

Link zur Webseite Fibanaccio

Calculate BuyLimit

Fibanaccio == Take Price

In [14]:
res = ath - ldl
res = ldh - tdl
res = mean_high - tdl
fb1 = round(mean_high - (res * 0.236),2)
fb2 = round(mean_high - (res * 0.382),2)
fb3 = round(mean_high - (res * 0.681),2)
fb4 = round(mean_high - (res * 0.786),2)
fb1, fb2, fb3, fb4
Out [14]:
(3283.65, 3268.91, 3238.71, 3228.11)

Take Profit and Stop Loss

In [15]:
tp = ath - ldh + fb1
sl = fb1 - (tp - ldh)
tp, sl
Out [15]:
(3543.09, 2981.12)

Create Dataframe

In [16]:
current_price = mt.symbol_info_tick(symbol)
fb = [fb1, fb2, fb3, fb4]
trading_type = []

x = 1
for i in fb:
    #print(i)
    
    if current_price.bid < i:
        print(f"Aktueller Preis {current_price.bid} ist kleiner als FB{x}  {i}, trading ist BuyStop")
        trading_type.append('BuyStop')
    elif current_price.bid > i: 
        print(f"Aktueller Preis {current_price.bid} ist größer als FB{x} {i}, trading type ist BuyLimit")
        trading_type.append("BuyLimit")
    x += 1

trading_type
Out [16]:
Aktueller Preis 3217.14 ist kleiner als FB1  3283.65, trading ist BuyStop
Aktueller Preis 3217.14 ist kleiner als FB2  3268.91, trading ist BuyStop
Aktueller Preis 3217.14 ist kleiner als FB3  3238.71, trading ist BuyStop
Aktueller Preis 3217.14 ist kleiner als FB4  3228.11, trading ist BuyStop
['BuyStop', 'BuyStop', 'BuyStop', 'BuyStop']
In [17]:
ldh - tdl
mean_high - mean_low
Out [17]:
79.05999999999995
In [18]:
tp_factor = ath-ldh
tp_factor = ath - tdh
#tp_factor = ath - mean_low
tp_factor = mean_high - mean_low - current_diff
sl_factor = [tp - fb1, tp - fb2, tp - fb3, tp - fb4]


data = {
    'trade_type' : [trading_type[0] + '01', trading_type[1] + '02', trading_type[2] + '03', trading_type[3] + '04'],
    'trade_price': [fb1, fb2, fb3, fb4],
    'trade_volume': [0.1, 0.2, 0.3, 0.4],
    #'trade_sl': [fb1 - sl_factor, fb2 - sl_factor, fb3 - sl_factor, fb4 - sl_factor],
    #'trade_sl': [fb1 - sl_factor[0], fb2 - sl_factor[1], fb3 - sl_factor[2], fb4 - sl_factor[3]],
    'trade_sl': [fb1 - tp_factor, fb2 - tp_factor, fb3 - tp_factor, fb4 - tp_factor],
    'trade_tp': [tp_factor + fb1, tp_factor + fb2, tp_factor + fb3, tp_factor + fb4]

}
In [19]:
# adj = 15
# factor = 5
# adj2 = adj - 5

# data = {
#     'trade_type' : ['BuyLimit01', 'BuyLimit02', 'BuyLimit03', 'BuyLimit04', 'BuyLimit05', 'BuyLimit06', 'BuyLimit07', 'BuyLimit08', 'BuyLimit09', 'BuyStop01', 'BuyStop02'],
#     'trade_price': [ath - adj, ath - adj - 25, ath - adj - 50, ath - adj - 75, ath - adj - 100, ath - adj - 125, ath - adj - 150, ath - adj - 175, ath - adj - 200, ath - 66, ath - adj],
#     'trade_volume': [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.1, 0.1],
#     'trade_sl': [ath - adj - factor, ath - adj - 25 - factor, ath - adj - 50 - factor, ath - adj - 75 - factor, ath - adj - 100 - factor, ath - adj - 125 - factor, ath - adj - 150 - factor, ath - adj - 175 - factor, ath - adj - 200 - factor, ath - 66 - 20, ath - adj - 20],
#     'trade_tp': [ath - adj2, ath - adj2, ath - adj2, ath - adj2, ath - adj2, ath - adj2, ath - adj2, ath - adj2, ath - adj2, ath, ath]

# }
In [20]:
df = pd.DataFrame(data)
df
Out [20]:
trade_type trade_price trade_volume trade_sl trade_tp
0 BuyStop01 3283.65 0.1 3250.26 3317.04
1 BuyStop02 3268.91 0.2 3235.52 3302.30
2 BuyStop03 3238.71 0.3 3205.32 3272.10
3 BuyStop04 3228.11 0.4 3194.72 3261.50

Set volume on BuyStops to 0.1

In [21]:
for index, row in df.iterrows():
    if bool(re.search('^BuyStop[0-9]{2}', row.trade_type)):
        df.loc[index, ['trade_volume']] = 0.1
    print(row.trade_type, row.trade_volume, index)
    
BuyStop01 0.1 0
BuyStop02 0.2 1
BuyStop03 0.3 2
BuyStop04 0.4 3
In [22]:
df
Out [22]:
trade_type trade_price trade_volume trade_sl trade_tp
0 BuyStop01 3283.65 0.1 3250.26 3317.04
1 BuyStop02 3268.91 0.1 3235.52 3302.30
2 BuyStop03 3238.71 0.1 3205.32 3272.10
3 BuyStop04 3228.11 0.1 3194.72 3261.50

Correct Volume Manuel

In [44]:
if bool(re.search('^BuyLimit[0-9]{2}', df.trade_type[2])) and df.trade_volume[1] == 0.1 and df.trade_volume[2] != 0.1:
    df.at[2, 'trade_volume'] = df.trade_volume[1] + 0.1

if bool(re.search('^BuyLimit[0-9]{2}', df.trade_type[3])) and df.trade_volume[2] != 0.1 and df.trade_volume[3] != 0.1:
    df.at[3, 'trade_volume'] = df.trade_volume[2] + 0.1

#df.at[3, 'trade_volume'] = df.trade_volume[2] + 0.1


df
Out [44]:
trade_type trade_price trade_volume trade_sl trade_tp
0 BuyStop01 3367.70 0.1 3302.47 3432.93
1 BuyStop02 3349.94 0.1 3284.71 3415.17
2 BuyLimit03 3313.56 0.2 3248.33 3378.79
3 BuyLimit04 3300.78 0.3 3235.55 3366.01

Place Order

Pending Orders in MT5

Pending orders allow you to execute trades at your predetermined levels rather than at the current market price. There are four types of pending orders:

  • Buy Limit: It is a pending order to buy an asset below the current market price. It is ideal for buying at a support level during correction.

  • Sell Limit: It is an order to sell an asset above the current market price. It helps to short-sell at the resistance level.

  • Buy Stop: It is a buy order used to catch the bullish breakouts. You can place a stop above the current market price.

  • Sell Stop: It is a sell order used to catch a bearish breakout by putting an order below the current market price.

In [23]:
# if bool(re.search('^StopLimit[0-9]{2}', 'BuyLimit01')):
#     print('Wahr')
# else:
#     print('Falsch')
In [24]:
def buyOrder(trade_type: str, trade_price: float, trade_volume: float, trade_sl: float, trade_tp: float, symbol: str):
    
    if bool(re.search('^BuyLimit[0-9]{2}', trade_type)):
        # Buy Stop
        request = {
        "action": mt.TRADE_ACTION_PENDING,
        "symbol": symbol,
        "volume": trade_volume, # FLOAT
        "type": mt.ORDER_TYPE_BUY_LIMIT,
        "price": trade_price,
        "sl": trade_sl, # FLOAT
        "tp": trade_tp, # FLOAT
        "deviation": 20, # INTERGER
        "magic": 0, # INTERGER
        "comment": trade_type,
        "type_time": mt.ORDER_TIME_GTC,
        "type_filling": mt.ORDER_FILLING_IOC,
        }
    else:
       #Sell Stop 
        request = {
        "action": mt.TRADE_ACTION_PENDING,
        "symbol": symbol,
        "volume": trade_volume, # FLOAT
        "type": mt.ORDER_TYPE_BUY_STOP,
        "price": trade_price,
        "sl": trade_sl, # FLOAT
        "tp": trade_tp, # FLOAT
        "deviation": 20, # INTERGER
        "magic": 0, # INTERGER
        "comment": trade_type,
        "type_time": mt.ORDER_TIME_GTC,
        "type_filling": mt.ORDER_FILLING_IOC,
        }

    order = mt.order_send(request)

Place Orders

In [25]:
for index, row in df.iterrows():
    #print(index, row)
    print(row['trade_type'], row['trade_price'], row['trade_volume'], row['trade_sl'], row['trade_tp'], symbol)
    buyOrder(row['trade_type'], row['trade_price'], row['trade_volume'], row['trade_sl'], row['trade_tp'], symbol)

    
BuyStop01 3283.65 0.1 3250.26 3317.04 XAUUSD
BuyStop02 3268.91 0.1 3235.52 3302.2999999999997 XAUUSD
BuyStop03 3238.71 0.1 3205.32 3272.1 XAUUSD
BuyStop04 3228.11 0.1 3194.7200000000003 3261.5 XAUUSD

Remove Pending Orders

In [50]:
# Remove Pending Order

def rm_pending_orders():

    while mt.orders_total() > 0:
        pending_orders = mt.orders_get()
        order1 = pending_orders[0]
        request = {
        'action': mt.TRADE_ACTION_REMOVE,
        'order': order1.ticket
        }
        mt.order_send(request)
In [51]:
rm_pending_orders()
---------------------------------------------------------------------------
KeyboardInterrupt                         Traceback (most recent call last)
Cell In[51], line 1
----> 1 rm_pending_orders()

Cell In[50], line 5, in rm_pending_orders()
      3 def rm_pending_orders():
----> 5     while mt.orders_total() > 0:
      6         pending_orders = mt.orders_get()
      7         order1 = pending_orders[0]

KeyboardInterrupt: 

Check pending Orders

In [ ]:
pos = mt.orders_get()
for i in pos:
    print(i.comment)
    df.loc[df['trade_type'] == i.comment, 'pending_trades'] = 1
df['pending_trades'] = df['pending_trades']. fillna(0)
In [ ]:
df.loc[df['trade_type'].isin(['BuyLimit02', 'BuyLimit03'])]
In [ ]:
row = df.loc[df['trade_type'] == 'BuyLimit02']
df.loc[df['trade_type'] == 'BuyLimit02', 'pending_trades'] = 1
In [ ]:
df
In [ ]:
tp_price = 30

pos = mt.positions_get()
pos[0].profit
pos[0].price_open + tp_price

Check for open trades

In [ ]:
pos = mt.positions_get()
for i in pos:
    print(i)
    pos_comment = i.comment
    pos_profit = i.profit
    print(pos_comment, pos_profit)
    df.loc[df['trade_type'] == i.comment, 'open_trades'] = 1
df['open_trades'] = df['open_trades']. fillna(0)
In [ ]:
df
In [ ]:
open_trades = df.loc[df['open_trades'] == 1]
open_trades
In [ ]:
for index, row in open_trades.iterrows():
    print(row.trade_type)
In [ ]: