{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Import Libaries" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "\n", "def dynamic_update_sl_tp(symbol, atr_mult=1.5, rrr_factor=None, check_tf='m5', trail_buffer=0.5, max_retries=2):\n", " \"\"\"\n", " Dynamisches Nachziehen von SL/TP für offene Trades.\n", " Läuft idealerweise bei jedem neuen Kerzenende von check_tf (z.B. m5) oder bei Intrabar-ATR-Sprüngen.\n", " \"\"\"\n", " # load recent bars for the timeframe\n", " df = get_rates(check_tf).iloc[-3:]\n", " if df is None or df.empty or len(df) < 2:\n", " return\n", " atr = float(df['atr'].iloc[-1]) if 'atr' in df.columns else None\n", " if atr is None or atr == 0:\n", " return\n", " # quick check for intrabar move (previous close -> current close)\n", " prev = float(df['close'].iloc[-2])\n", " curr = float(df['close'].iloc[-1])\n", " price_move = abs(curr - prev)\n", " # only update on new bar or large intrabar move (>= 0.5 * ATR)\n", " if price_move < 0.5 * atr and False:\n", " return\n", "\n", " positions = mt.positions_get(symbol=symbol) or []\n", " for pos in positions:\n", " # normalize pos interface (support dict-like or object)\n", " try:\n", " ticket = pos.ticket\n", " entry_price = pos.price_open\n", " pos_type = pos.type # 0=buy,1=sell\n", " cur_bid = mt.symbol_info_tick(symbol).bid\n", " cur_ask = mt.symbol_info_tick(symbol).ask\n", " except Exception:\n", " # fallback for dict-like\n", " ticket = pos.get('ticket', None)\n", " entry_price = pos.get('price_open', pos.get('entry_price'))\n", " pos_type = pos.get('type')\n", " cur_bid = mt.symbol_info_tick(symbol).bid\n", " cur_ask = mt.symbol_info_tick(symbol).ask\n", "\n", " current_price = cur_bid if pos_type == 0 else cur_ask\n", "\n", " # compute desired new SL/TP using update_trailing_sl_tp logic\n", " # profit in ATR\n", " profit_atr = (current_price - entry_price) / atr if pos_type == 0 else (entry_price - current_price) / atr\n", " # base sl\n", " if pos_type == 0:\n", " base_sl = current_price - atr_mult * atr\n", " new_sl = max((pos.sl or 0), base_sl)\n", " if profit_atr > 2:\n", " new_sl = max(new_sl, entry_price + 1.5 * atr)\n", " elif profit_atr > 1:\n", " new_sl = max(new_sl, entry_price + 1.0 * atr)\n", " elif profit_atr > 0.5:\n", " new_sl = max(new_sl, entry_price + 0.5 * atr)\n", " new_tp = entry_price + (entry_price - new_sl) * (rrr_factor or 2.0)\n", " else:\n", " base_sl = current_price + atr_mult * atr\n", " new_sl = min((pos.sl or 999999), base_sl)\n", " if profit_atr > 2:\n", " new_sl = min(new_sl, entry_price - 1.5 * atr)\n", " elif profit_atr > 1:\n", " new_sl = min(new_sl, entry_price - 1.0 * atr)\n", " elif profit_atr > 0.5:\n", " new_sl = min(new_sl, entry_price - 0.5 * atr)\n", " new_tp = entry_price - (new_sl - entry_price) * (rrr_factor or 2.0)\n", "\n", " # respect broker stops level and rounding\n", " info = mt.symbol_info(symbol)\n", " digits = info.digits\n", " point = info.point\n", " stops_level = info.trade_stops_level * point\n", "\n", " tick = mt.symbol_info_tick(symbol)\n", " bid, ask = tick.bid, tick.ask\n", " if pos_type == 0:\n", " if new_sl >= bid - stops_level:\n", " new_sl = bid - stops_level\n", " if new_tp <= ask + stops_level:\n", " new_tp = ask + stops_level\n", " else:\n", " if new_sl <= ask + stops_level:\n", " new_sl = ask + stops_level\n", " if new_tp >= bid - stops_level:\n", " new_tp = bid - stops_level\n", "\n", " new_sl = round(new_sl, digits)\n", " new_tp = round(new_tp, digits)\n", "\n", " # only update if change larger than point\n", " if (pos.sl is None or abs(new_sl - pos.sl) > point) or (pos.tp is None or abs(new_tp - pos.tp) > point):\n", " for attempt in range(max_retries):\n", " req = {\n", " 'action': mt.TRADE_ACTION_SLTP,\n", " 'symbol': symbol,\n", " 'position': ticket,\n", " 'sl': new_sl,\n", " 'tp': new_tp\n", " }\n", " res = mt.order_send(req)\n", " if getattr(res, 'retcode', None) == mt.TRADE_RETCODE_DONE:\n", " print(f\"Updated SL/TP for {symbol} #{ticket}: SL={new_sl}, TP={new_tp}\")\n", " break\n", " elif getattr(res, 'retcode', None) == mt.TRADE_RETCODE_INVALID_STOPS:\n", " adjust = 2 * stops_level\n", " if pos_type == 0:\n", " new_sl = round(bid - adjust, digits)\n", " new_tp = round(ask + adjust, digits)\n", " else:\n", " new_sl = round(ask + adjust, digits)\n", " new_tp = round(bid - adjust, digits)\n", " continue\n", " else:\n", " print('SL/TP update failed', getattr(res, 'retcode', None), getattr(res, 'comment', None))\n", " break\n", "\n", "\n", "\n", "def linreg_slope(series):\n", " \"\"\"Central linear regression slope helper (returns slope as float).\"\"\"\n", " from sklearn.linear_model import LinearRegression\n", " import numpy as np\n", " if series is None or len(series) < 3:\n", " return 0.0\n", " X = np.arange(len(series)).reshape(-1, 1)\n", " y = series.values.reshape(-1, 1)\n", " model = LinearRegression().fit(X, y)\n", " return float(model.coef_[0][0])\n", "\n", "\n", "#!pip install ta_lib-0.6.5-cp311-cp311-win_amd64.whl\n", "\n", "#%pip install talib\n", "\n", "#!pip install ta\n", "from ta.trend import ADXIndicator, EMAIndicator\n", "from ta.momentum import RSIIndicator\n", "from talib import CDLHAMMER, CDLSHOOTINGSTAR\n", "\n", "import pandas as pd\n", "import matplotlib.pyplot as plt\n", "import mplfinance as mpf\n", "import keyring as kr\n", "import MetaTrader5 as mt\n", "import requests\n", "import re\n", "from time import sleep\n", "import sqlite3 as db\n", "#import matplotlib.pyplot as plt\n", "import pandas_ta as ta\n", "import numpy as np\n", "\n", "from sklearn.linear_model import LinearRegression\n", "from scipy.signal import savgol_filter\n", "from scipy.signal import find_peaks\n", "\n", "\n", "\n", "\n", "# login to your Trading Account - sign up in the description\n", "mt.initialize()\n", " \n", "login = 10800246\n", "server = 'VantageInternational-Demo'\n", "password = kr.get_password(server, str(login))\n", "\n", "\n", "mt.login(login, password, server)\n", "\n", "project = \"trading-\" + server[-4::1]\n", "project = project.lower()\n", "project\n", "\n", "pause_trading = 0\n", "\n", "\n", "symbols = ['XAUUSD']\n", "#symbols = ['BTCUSD']\n", "\n", "#'BTCUSD', 'ETHUSD', \n", " #'XRPUSD', , 'EURNZD', 'EURUSD'\n", "\n", "volume_dict = {\n", " 'BTCUSD' : 0.1,\n", " 'BTCUSD_short' : 0.1,\n", "\n", " 'ETHUSD' : 1.0,\n", " 'ETHUSD_short' : 1.0,\n", " \n", " 'XRPUSD': 0.1,\n", " 'XRPUSD_short': 0.1,\n", "\n", " 'XAUUSD': 0.1,\n", " 'XAUUSD_short': 0.1,\n", "\n", " 'EURUSD': 0.1,\n", " 'EURUSD_short': 0.1,\n", "\n", " 'EURNZD': 0.1,\n", " 'EURNZD_short': 0.1,\n", "\n", "}\n", "\n", "periods_dict = {\n", " 'BTCUSD' : ['h1', 'm30', 'm15', 'm5', 'm1'],\n", " \n", " 'ETHUSD' : ['h1', 'm30', 'm15', 'm5', 'm1'],\n", "\n", " \n", " 'XRPUSD': ['h1', 'm30', 'm15', 'm5', 'm1'],\n", " \n", " 'XAUUSD': [ 'm15'],\n", "\n", " \n", " 'EURUSD': ['h1', 'm30', 'm15', 'm5', 'm1'],\n", "\n", "\n", " 'EURNZD': ['m5', 'm2', 'm1'],\n", "\n", "}\n", "\n", "def get_symbol():\n", " global symbols, pause_trading, periods_dict\n", " pricemovement = {}\n", "\n", " for s in symbols:\n", " items = mt.symbol_info(s)\n", " pricemovement[s] = round(items.price_change,2)\n", " #print(s, round(items.price_change,2))\n", "\n", " #percentage = pricemovement[max(pricemovement, key=pricemovement.get)]\n", " #symbol = max(pricemovement, key=pricemovement.get)\n", " #volume = volume_dict[symbol]\n", "\n", " sorted_pricemovement = sorted(pricemovement.items(), key=lambda x:x[1], reverse=True)\n", " converted_dict = dict(sorted_pricemovement)\n", "\n", " print(converted_dict)\n", "\n", " percentage = converted_dict[max(converted_dict, key=converted_dict.get)]\n", " symbol = max(converted_dict, key=converted_dict.get)\n", " volume = volume_dict[symbol]\n", "\n", "\n", " print(symbol, percentage, volume)\n", " # if percentage > 0: # and percentage < 0.8:\n", " # periods_dict[symbol] = ['m15', 'm5', 'm2', 'm1']\n", " # elif percentage > 0.8:\n", " # periods_dict[symbol] = ['h1', 'm30', 'm15', 'm5', 'm1']\n", "\n", " #\n", "\n", " #print(periods_dict)\n", "\n", " # if percentage > 0 and mt.positions_total() == 0:\n", " # pause_trading = 0 #0 no puase\n", " # return symbol, percentage, volume, periods_dict\n", " # elif percentage < 0.1 and mt.positions_total() == 0:\n", " # print(\"aktuell kein neues Symbol, pause Trading\")\n", " # pause_trading = 1 #1 pause\n", " # return None\n", "\n", " return symbol, percentage, volume, periods_dict\n", "\n", "get_symbol()\n", "\n", "def set_symbol():\n", " global symbol, volume, volume_dict\n", " symb = get_symbol()\n", " if symb != None:\n", " symbol = symb[0]\n", " volume = volume_dict[symb[0]]\n", " \n", "\n", "get_symbol()\n", "\n", "set_symbol()\n", "\n", "\n", "symbol, volume, pause_trading\n", "\n", "pos = mt.positions_get()\n", "for i in pos:\n", " #if i.comment == 'Retracement Bot':\n", " # print(i.ticket)\n", "\n", " if bool(re.search('^BuyStop[0-9]{2}', i.comment)):\n", " print(i.ticket)\n", "\n", "mt.positions_total()\n", "\n", "strategy_name = 'Retracement Bot'\n", "pos = mt.positions_get()\n", "for p in pos:\n", " if p.comment == strategy_name:\n", " print(p.comment)\n", "print(pos)\n", "\n", "def market_order(symbol, volume, order_type, deviation=20, magic=30, stoploss=0.0, take_profit=0.0,\n", " strategy_name='Retracement Bot'):\n", "\n", " global project, pause_trading\n", "\n", " project_id_dict = {\n", " 'trading-demo': 'a3f3ae',\n", " 'trading-live': '747543'\n", " }\n", "\n", " order_type_dict = {\n", " 'buy': mt.ORDER_TYPE_BUY,\n", " 'sell': mt.ORDER_TYPE_SELL\n", " }\n", "\n", " price_dict = {\n", " 'buy': mt.symbol_info_tick(symbol).ask,\n", " 'sell': mt.symbol_info_tick(symbol).bid\n", " }\n", "\n", " buypos = []\n", "\n", " pos = mt.positions_get()\n", " for p in pos:\n", " if p.comment == strategy_name:\n", " buypos.append('true')\n", " \n", " activepos = buypos.count('true')\n", "\n", " if order_type == 'buy' and activepos == 0 and pause_trading == 0: # and mt.positions_total() == 0:\n", " \n", " request = {\n", " \"action\": mt.TRADE_ACTION_DEAL,\n", " \"symbol\": symbol,\n", " \"volume\": volume, # FLOAT\n", " \"type\": order_type_dict[order_type],\n", " \"price\": price_dict[order_type],\n", " \"sl\": stoploss, # FLOAT\n", " \"tp\": take_profit, # FLOAT\n", " \"deviation\": deviation, # INTERGER\n", " \"magic\": magic, # INTERGER\n", " \"comment\": strategy_name,\n", " \"type_time\": mt.ORDER_TIME_GTC,\n", " \"type_filling\": mt.ORDER_FILLING_IOC, # mt.ORDER_FILLING_FOK if IOC does not work\n", " }\n", "\n", " requests.post('https://api.mynotifier.app', {\n", " \"apiKey\": 'beafb52e-3cb6-477a-92ef-2f10bff50e20',\n", " \"message\": \"Es wrude ein Handel eröffnet!\",\n", " \"description\": \"Bitte kontrolliere die Position\",\n", " \"type\": \"info\",#\"info\", # info, error, warning or success\n", " \"project\": project_id_dict[project]\n", " })\n", "\n", " order_result = mt.order_send(request)\n", " #return (order_result)\n", " \n", " elif order_type == 'sell' and mt.positions_total() > 0:\n", " pos = mt.positions_get()\n", " for p in pos:\n", " if p.comment == strategy_name:\n", " # while schleife ?\n", " positions = mt.positions_get()\n", " ticket = p.ticket\n", " request = {\n", " \"action\": mt.TRADE_ACTION_DEAL,\n", " \"symbol\": symbol,\n", " \"volume\": volume, # FLOAT\n", " \"type\": order_type_dict[order_type],\n", " \"price\": price_dict[order_type],\n", " \"position\": ticket,\n", " \"sl\": stoploss, # FLOAT\n", " \"tp\": take_profit, # FLOAT\n", " \"deviation\": deviation, # INTERGER\n", " \"magic\": magic, # INTERGER\n", " \"comment\": strategy_name,\n", " \"type_time\": mt.ORDER_TIME_GTC,\n", " \"type_filling\": mt.ORDER_FILLING_IOC, # mt.ORDER_FILLING_FOK if IOC does not work\n", " }\n", "\n", " requests.post('https://api.mynotifier.app', {\n", " \"apiKey\": 'beafb52e-3cb6-477a-92ef-2f10bff50e20',\n", " \"message\": \"Es wrude ein Handel geschlossen!\",\n", " \"description\": \"Bitte prüfe die Position\",\n", " \"type\": \"info\",#\"info\", # info, error, warning or success\n", " \"project\": project_id_dict[project]\n", " })\n", "\n", " order_result = mt.order_send(request)\n", " #return (order_result)\n", " \n", "\n", "debug = False\n", "\n", "trend_dict = {\n", " #'m5': '',\n", " #'m10': '',\n", " 'm15': '',\n", " #'m30': '',\n", " #'h4': '',\n", "}\n", "\n", "timeframes_dict = {\n", " 'm1': mt.TIMEFRAME_M1,\n", " 'm2': mt.TIMEFRAME_M2,\n", " 'm3': mt.TIMEFRAME_M3,\n", " 'm5': mt.TIMEFRAME_M5,\n", " 'm15': mt.TIMEFRAME_M15,\n", " 'm20': mt.TIMEFRAME_M20,\n", " 'm30': mt.TIMEFRAME_M30,\n", " 'h1': mt.TIMEFRAME_H1,\n", " 'h4': mt.TIMEFRAME_H4,\n", " 'd1': mt.TIMEFRAME_D1,\n", "}\n", "\n", "\n", "# timeframes = {\n", "# 'm1': mt.TIMEFRAME_M1,\n", "# 'm2': mt.TIMEFRAME_M2,\n", "# 'm3': mt.TIMEFRAME_M3,\n", "# 'm5': mt.TIMEFRAME_M5,\n", "# 'm15': mt.TIMEFRAME_M15,\n", "# 'm20': mt.TIMEFRAME_M20,\n", "# 'm30': mt.TIMEFRAME_M30,\n", "# 'h1': mt.TIMEFRAME_H1,\n", "# }\n", "\n", "print(trend_dict)\n", "\n", "def get_rates(periode, bars=300):\n", " #global symbol\n", "\n", " # OHLC abrufen\n", " ohlc = mt.copy_rates_from_pos(symbol, timeframes_dict[periode], 0, bars)\n", " df = pd.DataFrame(ohlc)\n", " df['time'] = pd.to_datetime(df['time'], unit='s')\n", "\n", " # Umwandeln in float\n", " df[\"open\"] = df[\"open\"].astype(float)\n", " df[\"high\"] = df[\"high\"].astype(float)\n", " df[\"low\"] = df[\"low\"].astype(float)\n", " df[\"close\"] = df[\"close\"].astype(float)\n", "\n", " # ATR berechnen (klassisch 14)\n", " df[\"atr\"] = ta.atr(high=df[\"high\"], low=df[\"low\"], close=df[\"close\"], length=14)\n", "\n", " # leichte Glättung (optional, um Rauschen zu reduzieren)\n", " df[\"atr\"] = df[\"atr\"].rolling(window=5).mean()\n", "\n", " # Index setzen\n", " df.set_index(\"time\", inplace=True)\n", "\n", " # NaNs entfernen (anfangs durch ATR-Berechnung)\n", " df = df.dropna()\n", "\n", " return df\n", "\n", "\n", "get_rates('h4', 200)\n", "\n", "\n", "def get_trend(timeframe=\"h4\", lookback=150):\n", " \"\"\"\n", " Bestimme Trendrichtung per Linear Regression.\n", " Liefert ein dict mit keys: trend (uptrend/downtrend/sideways), slope, atr, slope_threshold, price.\n", " \"\"\"\n", " import numpy as np\n", " df = get_rates(timeframe, bars=lookback)\n", " if df is None or df.empty:\n", " return {\"trend\": \"sideways\", \"slope\": 0.0, \"atr\": 0.0, \"slope_threshold\": 0.0, \"price\": None}\n", "\n", " slope = linreg_slope(df['close'].iloc[-lookback:])\n", "\n", " # Ensure ATR exists\n", " if 'atr' not in df.columns or df['atr'].isnull().all():\n", " # fallback ATR calc\n", " hl = df['high'] - df['low']\n", " hc = (df['high'] - df['close'].shift()).abs()\n", " lc = (df['low'] - df['close'].shift()).abs()\n", " tr = pd.concat([hl, hc, lc], axis=1).max(axis=1)\n", " atr_series = tr.rolling(14, min_periods=1).mean()\n", " atr = float(atr_series.iloc[-1])\n", " else:\n", " atr = float(df['atr'].iloc[-1])\n", "\n", " current_price = float(df['close'].iloc[-1])\n", "\n", " slope_threshold = (atr / current_price) * 1.2 if current_price and atr else 0.0\n", "\n", " if abs(slope) < slope_threshold:\n", " trend = 'sideways'\n", " else:\n", " trend = 'uptrend' if slope > 0 else 'downtrend'\n", "\n", " return {\"trend\": trend, \"slope\": float(slope), \"atr\": atr, \"slope_threshold\": float(slope_threshold), \"price\": current_price}\n", "\n", "\n", "def get_top_down_signal(symbol=symbol):\n", " \"\"\"\n", " Top-Down Ansatz:\n", " - D1 / H4: Trend bestimmen\n", " - H1 / M30: Setup identifizieren\n", " - M15 / M5: Einstiege optimieren (Signale ohne Tradeausführung)\n", " \"\"\"\n", " global trend_dict\n", "\n", " # --- Höhere Timeframes ---\n", " d1_trend_info = get_trend(\"d1\", lookback=200)\n", " h4_trend_info = get_trend(\"h4\", lookback=150)\n", "\n", " # --- Mittlere Timeframes für Setups ---\n", " h1_trend_info = get_trend(\"h1\", lookback=100)\n", " m30_trend_info = get_trend(\"m30\", lookback=60)\n", "\n", " # --- Niedrigere Timeframes für Einstiege (nur Signal, kein Trade) ---\n", " m15_trend_info = get_trend(\"m15\", lookback=50)\n", " m5_trend_info = get_trend(\"m5\", lookback=20)\n", "\n", " # --- Konsolidierte Trendanalyse ---\n", " top_down_trend = \"sideways\"\n", " if d1_trend_info[\"trend\"] == h4_trend_info[\"trend\"]:\n", " top_down_trend = d1_trend_info[\"trend\"]\n", "\n", " # --- Setup-Bedingungen ---\n", " setup_ready = False\n", " if top_down_trend != \"sideways\":\n", " if h1_trend_info[\"trend\"] == top_down_trend and m30_trend_info[\"trend\"] == top_down_trend:\n", " setup_ready = True\n", "\n", " # --- Einstiegsberechnung ---\n", " entry_signal = 0\n", " if setup_ready:\n", " if m15_trend_info[\"trend\"] == top_down_trend and m5_trend_info[\"trend\"] == top_down_trend:\n", " entry_signal = 1 if top_down_trend == \"uptrend\" else -1\n", "\n", " # --- Speichern ---\n", " trend_dict[\"top_down\"] = {\n", " \"D1\": d1_trend_info,\n", " \"H4\": h4_trend_info,\n", " \"H1\": h1_trend_info,\n", " \"M30\": m30_trend_info,\n", " \"M15\": m15_trend_info,\n", " \"M5\": m5_trend_info,\n", " \"top_down_trend\": top_down_trend,\n", " \"setup_ready\": setup_ready,\n", " \"entry_signal\": entry_signal\n", " }\n", "\n", " return trend_dict[\"top_down\"]\n", "\n", "\n", "get_trend(\"h1\")\n", "\n", "get_top_down_signal(symbol)\n", "\n", "get_trend()\n", "\n", "def get_trend_fast(period):\n", " global trend_dict, periods_dict, symbol\n", "\n", " df2 = get_rates(period).iloc[-200:]\n", " df2[\"close_smooth\"] = savgol_filter(df2.close, 15, 5) # kleinere Glättung\n", "\n", " atr = df2.atr.iloc[-1]\n", "\n", " # Weniger strenge Peak-Erkennung\n", " peaks_idx, _ = find_peaks(df2.close_smooth, distance=1, width=2, prominence=atr*0.5) #evtl kleiner 0.5\n", " troughs_idx, _ = find_peaks(-1*df2.close_smooth, distance=1, width=2, prominence=atr*0.5)\n", "\n", " # Trend über Peaks/Troughs\n", " if len(peaks_idx) > 0 and len(troughs_idx) > 0:\n", " if peaks_idx[-1] > troughs_idx[-1]:\n", " trend = \"downtrend\"\n", " else:\n", " trend = \"uptrend\"\n", " else:\n", " # Falls keine klaren Peaks gefunden wurden → Slope nutzen\n", " slope = df2.close_smooth.diff().iloc[-5:].mean()\n", " trend = \"downtrend\" if slope < 0 else \"uptrend\"\n", "\n", " trend_dict[period] = trend\n", " return trend\n", "\n", "\n", "get_trend_fast('m15')\n", "\n", "def set_trend():\n", "\n", " global pause_trading, periods_dict, trend_dict\n", "\n", " for k,v in trend_dict.items():\n", " get_trend_fast(k) \n", " print(k)\n", " \n", " for k,v in reversed(trend_dict.items()):\n", "\n", " if v == 'uptrend':\n", " print(k,v)\n", " periods_dict[symbol] = [k]\n", " pause_trading = 0\n", " print(f\"Pause Trading: {pause_trading}\")\n", " break\n", " elif v == 'downtrend':\n", " periods_dict[symbol] = [k] #['m15']\n", " pause_trading = 1\n", " print(f\"Pause Trading: {pause_trading}\")\n", "\n", "set_trend()\n", "\n", "pause_trading, trend_dict, periods_dict, symbols[0]\n", "\n", "set_trend()\n", "\n", "trend_dict[periods_dict[symbol][0]]\n", "\n", "periods_dict[symbol], pause_trading\n", "\n", "def get_mt5_data(symbol=symbol, timeframe=mt.TIMEFRAME_M15, n_bars=500):\n", " rates = mt.copy_rates_from_pos(symbol, timeframe, 0, n_bars)\n", " df = pd.DataFrame(rates)\n", " df[\"time\"] = pd.to_datetime(df[\"time\"], unit=\"s\")\n", " return df\n", "\n", "def get_m5_trade_signal(symbol, atr_mult=1.5):\n", " global trend_dict, periods_dict\n", "\n", " # Hole die letzten M5-Daten\n", " df = get_rates('m5').iloc[-200:]\n", "\n", " # Smoothen\n", " df[\"close_smooth_std\"] = savgol_filter(df.close, 25, 5)\n", " df[\"close_smooth_fast\"] = savgol_filter(df.close, 15, 5)\n", "\n", " atr = df.atr.iloc[-1]\n", "\n", " # --- Standard-Trend ---\n", " peaks_std, _ = find_peaks(df.close_smooth_std, distance=1, width=2, prominence=atr)\n", " troughs_std, _ = find_peaks(-df.close_smooth_std, distance=1, width=2, prominence=atr)\n", "\n", " if len(peaks_std) > 0 and len(troughs_std) > 0:\n", " if peaks_std[-1] > troughs_std[-1]:\n", " trend_standard = \"downtrend\"\n", " else:\n", " trend_standard = \"uptrend\"\n", " else:\n", " trend_standard = \"neutral\"\n", "\n", " # --- Fast-Trend ---\n", " peaks_fast, _ = find_peaks(df.close_smooth_fast, distance=1, width=2, prominence=atr*0.5)\n", " troughs_fast, _ = find_peaks(-df.close_smooth_fast, distance=1, width=2, prominence=atr*0.5)\n", "\n", " if len(peaks_fast) > 0 and len(troughs_fast) > 0:\n", " if peaks_fast[-1] > troughs_fast[-1]:\n", " trend_fast = \"downtrend\"\n", " else:\n", " trend_fast = \"uptrend\"\n", " else:\n", " slope = df.close_smooth_fast.diff().iloc[-5:].mean()\n", " trend_fast = \"downtrend\" if slope < 0 else \"uptrend\"\n", "\n", " # --- Kombiniertes Signal ---\n", " signal = 0 # 0 = neutral, 1 = long, -1 = short\n", " stop_loss = None\n", "\n", " if trend_standard == \"uptrend\" and trend_fast == \"uptrend\":\n", " signal = 1\n", " stop_loss = df.close.iloc[-1] - atr_mult * atr\n", " elif trend_standard == \"downtrend\" and trend_fast == \"downtrend\":\n", " signal = -1\n", " stop_loss = df.close.iloc[-1] + atr_mult * atr\n", "\n", " # Speichern\n", " trend_dict['m5'] = {\"standard\": trend_standard, \"fast\": trend_fast, \"signal\": signal}\n", "\n", " return {\n", " \"signal\": signal,\n", " \"price\": df.close.iloc[-1],\n", " \"stop_loss\": stop_loss,\n", " \"trends\": trend_dict['m15']\n", " }\n", "\n", "\n", "def generate_signal(df = get_mt5_data(symbol=symbol, timeframe=timeframes_dict['m15']), confirm_window=3):\n", " \"\"\"\n", " Berechnet drei Signalarten:\n", " - fast_signal: schnelle, aggressive Variante\n", " - standard_signal: konservative Basisstrategie\n", " - optimized_signal: zusätzliche Filter (ATR, ADX, strengerer RSI)\n", " \"\"\"\n", "\n", " # Indikatoren\n", " df[\"ema21\"] = df[\"close\"].ewm(span=3).mean()\n", " df[\"ema50\"] = df[\"close\"].ewm(span=9).mean()\n", " df[\"rsi9\"] = ta.rsi(df[\"close\"], length=9)\n", " df[\"rsi14\"] = ta.rsi(df[\"close\"], length=14)\n", " df[\"trend\"] = savgol_filter(df[\"close\"], 25, 3)\n", "\n", " # Zusätzliche Filterindikatoren\n", " df[\"atr\"] = ta.atr(df[\"high\"], df[\"low\"], df[\"close\"], length=14)\n", " df[\"adx\"] = ta.adx(df[\"high\"], df[\"low\"], df[\"close\"], length=14)[\"ADX_14\"]\n", "\n", " # Spalten für Signale\n", " df[\"fast_signal\"] = 0\n", " df[\"standard_signal\"] = 0\n", " df[\"optimized_signal\"] = 0\n", "\n", " for i in range(1, len(df)):\n", " # -----------------------\n", " # FAST SIGNAL (früh/aggressiv)\n", " # -----------------------\n", " if (\n", " df[\"ema21\"].iloc[i] > df[\"ema50\"].iloc[i]\n", " and df[\"rsi9\"].iloc[i] > 30\n", " ):\n", " df.at[i, \"fast_signal\"] = 1\n", " elif (\n", " df[\"ema21\"].iloc[i] < df[\"ema50\"].iloc[i]\n", " and df[\"rsi9\"].iloc[i] < 60\n", " ):\n", " df.at[i, \"fast_signal\"] = -1\n", "\n", " # -----------------------\n", " # STANDARD SIGNAL (konservativ, ursprüngliche Logik)\n", " # -----------------------\n", " if (\n", " df[\"ema21\"].iloc[i] > df[\"ema50\"].iloc[i]\n", " and df[\"ema21\"].iloc[i - 1] <= df[\"ema50\"].iloc[i - 1]\n", " and df[\"rsi14\"].iloc[i] < 70\n", " and df[\"rsi9\"].iloc[i] > 40\n", " and df[\"trend\"].iloc[i] > df[\"trend\"].iloc[i - 1]\n", " ):\n", " df.at[i, \"standard_signal\"] = 1\n", " elif (\n", " df[\"ema21\"].iloc[i] < df[\"ema50\"].iloc[i]\n", " and df[\"ema21\"].iloc[i - 1] >= df[\"ema50\"].iloc[i - 1]\n", " and df[\"rsi14\"].iloc[i] > 40\n", " and df[\"rsi9\"].iloc[i] < 70\n", " and df[\"trend\"].iloc[i] < df[\"trend\"].iloc[i - 1]\n", " ):\n", " df.at[i, \"standard_signal\"] = -1\n", "\n", " # -----------------------\n", " # OPTIMIZED SIGNAL (mit ADX + ATR + strengerem RSI)\n", " # -----------------------\n", " if (\n", " df[\"ema21\"].iloc[i] > df[\"ema50\"].iloc[i]\n", " and df[\"ema21\"].iloc[i - 1] <= df[\"ema50\"].iloc[i - 1]\n", " and df[\"rsi14\"].iloc[i] < 65 # strengerer Filter\n", " and df[\"rsi9\"].iloc[i] > 45 # Momentum klarer\n", " and df[\"adx\"].iloc[i] > 20 # Trendstärke vorhanden\n", " and df[\"atr\"].iloc[i] > df[\"atr\"].rolling(50).mean().iloc[i] # Volatilität über Durchschnitt\n", " ):\n", " df.at[i, \"optimized_signal\"] = 1\n", " elif (\n", " df[\"ema21\"].iloc[i] < df[\"ema50\"].iloc[i]\n", " and df[\"ema21\"].iloc[i - 1] >= df[\"ema50\"].iloc[i - 1]\n", " and df[\"rsi14\"].iloc[i] > 35 # strengerer Filter unten\n", " and df[\"rsi9\"].iloc[i] < 55\n", " and df[\"adx\"].iloc[i] > 20\n", " and df[\"atr\"].iloc[i] > df[\"atr\"].rolling(50).mean().iloc[i]\n", " ):\n", " df.at[i, \"optimized_signal\"] = -1\n", "\n", " return df\n", "\n", "\n", "generate_signal()\n", "\n", "pos = mt.positions_total()\n", "\n", "if pos > 0:\n", " open_positions = mt.positions_get() \n", " trail_factor = 0.5\n", " entry_price = open_positions[0].price_open\n", " tp_current = open_positions[0].tp\n", " current_price = open_positions[0].price_current\n", " profit = open_positions[0].profit\n", "\n", " profit = current_price - entry_price\n", " if profit > 0:\n", " new_tp = current_price - entry_price * trail_factor\n", " \n", " if profit < 0:\n", " new_tp = current_price - profit * trail_factor \n", "\n", " if new_tp > current_price:\n", " #update tp from open pos\n", " new_tp\n", " print(f\"Trailing +TP for BUY {symbol}: {new_tp} CP: {current_price}\")\n", " if new_tp < current_price:\n", " #update tp from open pos\n", " new_tp\n", " print(f\"Trailing -TP for BUY {symbol}: {new_tp} CP: {current_price}\")\n", "\n", "#open_positions\n", "\n", "\n", "def update_trailing_sl_tp(pos, atr, rrr=2.0, atr_mult=1.5, max_retries=2):\n", " \"\"\"\n", " Aktualisiert SL und TP für offene Positionen:\n", " - ATR-basiertes Trailing\n", " - Gewinn-stufenweises Nachziehen\n", " - Dynamische Anpassung mit Validierung\n", " - Fallback-Mechanismus bei RETCODE 1016\n", " \"\"\"\n", "\n", " symbol = pos.symbol\n", " info = mt.symbol_info(symbol)\n", " digits = info.digits\n", " point = info.point\n", " stops_level = info.trade_stops_level * point # Mindestabstand vom Broker\n", "\n", " entry_price = pos.price_open\n", " current_tick = mt.symbol_info_tick(symbol)\n", " bid, ask = current_tick.bid, current_tick.ask\n", " current_price = bid if pos.type == 0 else ask\n", " pos_type = pos.type # 0 = BUY, 1 = SELL\n", "\n", " # Gewinn in ATR berechnen\n", " if pos_type == 0: # LONG\n", " profit_atr = (current_price - entry_price) / atr\n", " base_sl = current_price - atr_mult * atr\n", " new_sl = max(pos.sl or 0, base_sl)\n", "\n", " if profit_atr > 2:\n", " new_sl = max(new_sl, entry_price + 1.5 * atr)\n", " elif profit_atr > 1:\n", " new_sl = max(new_sl, entry_price + 1.0 * atr)\n", " elif profit_atr > 0.5:\n", " new_sl = max(new_sl, entry_price + 0.5 * atr)\n", "\n", " new_tp = entry_price + (entry_price - new_sl) * rrr\n", "\n", " # Validierung BUY\n", " if new_sl >= bid - stops_level:\n", " new_sl = bid - stops_level\n", " if new_tp <= ask + stops_level:\n", " new_tp = ask + stops_level\n", "\n", " else: # SHORT\n", " profit_atr = (entry_price - current_price) / atr\n", " base_sl = current_price + atr_mult * atr\n", " new_sl = min(pos.sl or 999999, base_sl)\n", "\n", " if profit_atr > 2:\n", " new_sl = min(new_sl, entry_price - 1.5 * atr)\n", " elif profit_atr > 1:\n", " new_sl = min(new_sl, entry_price - 1.0 * atr)\n", " elif profit_atr > 0.5:\n", " new_sl = min(new_sl, entry_price - 0.5 * atr)\n", "\n", " new_tp = entry_price - (new_sl - entry_price) * rrr\n", "\n", " # Validierung SELL\n", " if new_sl <= ask + stops_level:\n", " new_sl = ask + stops_level\n", " if new_tp >= bid - stops_level:\n", " new_tp = bid - stops_level\n", "\n", " # Runden auf gültige Stellen\n", " new_sl = round(new_sl, digits)\n", " new_tp = round(new_tp, digits)\n", "\n", " # --- Nur updaten, wenn sich Werte geändert haben ---\n", " if (pos.sl is None or abs(new_sl - pos.sl) > point) or \\\n", " (pos.tp is None or abs(new_tp - pos.tp) > point):\n", "\n", " for attempt in range(max_retries):\n", " request = {\n", " \"action\": mt.TRADE_ACTION_SLTP,\n", " \"symbol\": symbol,\n", " \"sl\": new_sl,\n", " \"tp\": new_tp,\n", " \"position\": pos.ticket\n", " }\n", " result = mt.order_send(request)\n", "\n", " if result.retcode == mt.TRADE_RETCODE_DONE:\n", " print(f\"🔄 Updated {symbol} | SL: {new_sl:.5f} | TP: {new_tp:.5f}\")\n", " break\n", " elif result.retcode == mt.TRADE_RETCODE_INVALID_STOPS:\n", " # Fallback: Stops korrigieren\n", " print(f\"⚠️ RETCODE 1016 (Invalid stops) – Versuch {attempt+1}/{max_retries}\")\n", " adjust = 2 * stops_level # mehr Abstand\n", " if pos_type == 0: # BUY\n", " new_sl = bid - adjust\n", " new_tp = ask + adjust\n", " else: # SELL\n", " new_sl = ask + adjust\n", " new_tp = bid - adjust\n", "\n", " new_sl = round(new_sl, digits)\n", " new_tp = round(new_tp, digits)\n", " continue # retry\n", " else:\n", " print(f\"❌ SL/TP Update Fehler: {result.retcode} ({result.comment})\")\n", " break\n", "\n", " return {\"new_sl\": new_sl, \"new_tp\": new_tp, \"profit_atr\": profit_atr}\n", "\n", "\n", "def manual_update_trailing_sl_tp(atr_mult=1.5, slope_factor=1.5):\n", " # --- Hole die letzten M5-Daten ---\n", " df = get_rates('m5').iloc[-200:]\n", "\n", " # --- ATR Berechnung ---\n", " df[\"hl\"] = df[\"high\"] - df[\"low\"]\n", " df[\"hc\"] = (df[\"high\"] - df[\"close\"].shift()).abs()\n", " df[\"lc\"] = (df[\"low\"] - df[\"close\"].shift()).abs()\n", " df[\"tr\"] = df[[\"hl\",\"hc\",\"lc\"]].max(axis=1)\n", " df[\"atr\"] = df[\"tr\"].rolling(14).mean()\n", " atr = df[\"atr\"].iloc[-1]\n", "\n", " current_price = df[\"close\"].iloc[-1]\n", "\n", " # --- Trendrichtung per Linear Regression ---\n", " def linreg_slope(series):\n", " X = np.arange(len(series)).reshape(-1, 1)\n", " y = series.values.reshape(-1, 1)\n", " model = LinearRegression().fit(X, y)\n", " return model.coef_[0][0]\n", "\n", " slope_long = linreg_slope(df[\"close\"].iloc[-50:]) # 50 Balken (~4h)\n", " slope_short = linreg_slope(df[\"close\"].iloc[-15:]) # 15 Balken (~1h)\n", "\n", " # --- Dynamischer Seitwärtsfilter ---\n", " slope_threshold = slope_factor * atr / df[\"close\"].iloc[-1]\n", "\n", " # --- Dynamische RRR-Berechnung ---\n", " atr_norm = atr / current_price # relative Volatilität\n", " slope_strength = abs(slope_short) # Trendstärke aus Regression\n", "\n", " rrr_base = 1.2\n", " rrr_from_vol = atr_norm * 1500 # skaliert ATR-Einfluss\n", " rrr_from_slope = slope_strength / slope_threshold # Slope-Einfluss\n", "\n", " rrr = rrr_base + rrr_from_vol + rrr_from_slope\n", " rrr = max(1.2, min(rrr, 3.0)) # Begrenzung\n", "\n", "\n", " open_positions = mt.positions_get(symbol=symbol)\n", " for pos in open_positions:\n", " atr_value = df[\"atr\"].iloc[-1]\n", " update_trailing_sl_tp(pos, atr=atr_value, rrr=rrr, atr_mult=atr_mult)\n", " \n", "\n", "manual_update_trailing_sl_tp()\n", "\n", "\n", "def get_m5_trade_signals(symbol=symbol, atr_mult=1.5, base_rrr=2.0, atr_min=0.0005, slope_factor=1.5, place_orders=False):\n", " \"\"\"\n", " M5/M15 analysis-only signal generator. By default it does NOT place orders.\n", " Set place_orders=True to allow execution (not recommended when called from top-down analysis).\n", " Returns a dict with signal, price, stop_loss, take_profit, Risk Reward, atr and slopes.\n", " \"\"\"\n", " # use m15 data for setup if available, otherwise m5\n", " df = get_rates('m15').iloc[-200:]\n", " if df is None or df.empty or len(df) < 30:\n", " return {\"signal\": 0, \"reason\": \"not enough data\"}\n", "\n", " # ATR fallback (ensure column exists)\n", " if 'atr' not in df.columns or df['atr'].isnull().all():\n", " df['hl'] = df['high'] - df['low']\n", " df['hc'] = (df['high'] - df['close'].shift()).abs()\n", " df['lc'] = (df['low'] - df['close'].shift()).abs()\n", " df['tr'] = df[['hl','hc','lc']].max(axis=1)\n", " df['atr'] = df['tr'].rolling(14, min_periods=1).mean()\n", " atr = float(df['atr'].iloc[-1])\n", "\n", " if atr < atr_min:\n", " return {\"signal\": 0, \"reason\": \"ATR too low → sideways\", \"atr\": atr}\n", "\n", " slope_long = linreg_slope(df['close'].iloc[-50:])\n", " slope_short = linreg_slope(df['close'].iloc[-15:])\n", "\n", " slope_threshold = slope_factor * atr / float(df['close'].iloc[-1])\n", "\n", " if abs(slope_long) < slope_threshold and abs(slope_short) < slope_threshold:\n", " return {\"signal\": 0, \"reason\": \"Trend flat → sideways\", \"atr\": atr,\n", " \"slope_long\": slope_long, \"slope_short\": slope_short}\n", "\n", " trend_standard = 'uptrend' if slope_long > 0 else 'downtrend'\n", " trend_fast = 'uptrend' if slope_short > 0 else 'downtrend'\n", "\n", " current_price = float(df['close'].iloc[-1])\n", "\n", " # adaptive RRR\n", " atr_norm = atr / current_price\n", " slope_strength = abs(slope_short)\n", " rrr_base = 1.2\n", " rrr_from_vol = atr_norm * 1500\n", " rrr_from_slope = slope_strength / (slope_threshold if slope_threshold!=0 else 1e-9)\n", " rrr = rrr_base + rrr_from_vol + rrr_from_slope\n", " rrr = max(1.2, min(rrr, 3.0))\n", "\n", " stop_loss = None\n", " take_profit = None\n", " signal = 0\n", "\n", " if trend_standard == 'uptrend' and trend_fast == 'uptrend':\n", " signal = 1\n", " stop_loss = current_price - atr_mult * atr\n", " take_profit = current_price + atr_mult * atr * rrr\n", " if place_orders:\n", " market_order(symbol, volume_dict.get(symbol, 0.0), 'buy', stoploss=stop_loss, take_profit=take_profit)\n", "\n", " elif trend_standard == 'downtrend' and trend_fast == 'downtrend':\n", " signal = -1\n", " stop_loss = current_price + atr_mult * atr\n", " take_profit = current_price - atr_mult * atr * rrr\n", " if place_orders:\n", " market_order(symbol, volume_dict.get(symbol, 0.0), 'sell', stoploss=stop_loss, take_profit=take_profit)\n", "\n", " return {\n", " 'signal': signal,\n", " 'price': current_price,\n", " 'stop_loss': stop_loss,\n", " 'take_profit': take_profit,\n", " 'Risk Reward': rrr,\n", " 'atr': atr,\n", " 'slope_long': slope_long,\n", " 'slope_short': slope_short,\n", " 'trend_standard': trend_standard,\n", " 'trend_fast': trend_fast\n", " }\n", "\n", "\n", "def execute_m5_trade(symbol=symbol, atr_mult=1.5, base_rrr=2.0):\n", " \"\"\"Execute trade only if Top-Down approves. Uses get_top_down_signal and get_m5_trade_signals (analysis).\n", " \"\"\"\n", " global volume_dict, pause_trading\n", " if pause_trading == 1:\n", " print('Trading paused, skipping execution')\n", " return None\n", "\n", " top = get_top_down_signal(symbol)\n", " if not top.get('setup_ready') or top.get('entry_signal',0) == 0:\n", " print('Top-Down not ready or no entry signal, aborting execution')\n", " return None\n", "\n", " # get m5 analysis (no auto-order)\n", " m5 = get_m5_trade_signals(symbol=symbol, atr_mult=atr_mult, base_rrr=base_rrr, place_orders=False)\n", " if m5.get('signal',0) == 0:\n", " print('M5 analysis returned no entry, abort')\n", " return None\n", "\n", " # execute using the M5-calculated SL/TP\n", " direction = 'buy' if m5['signal'] == 1 else 'sell'\n", " print(f'Executing {direction} {symbol} @ {m5[\"price\"]} SL={m5[\"stop_loss\"]} TP={m5[\"take_profit\"]}')\n", " market_order(symbol, volume_dict.get(symbol,0.0), direction, stoploss=m5['stop_loss'], take_profit=m5['take_profit'])\n", "\n", " # after entry, run dynamic trailing update once\n", " dynamic_update_sl_tp(symbol, atr_mult=atr_mult, rrr_factor=m5['Risk Reward'], check_tf='m5')\n", "\n", " return {'executed': True, 'direction': direction, 'm5': m5, 'topdown': top}\n", "\n", "\n", "execute_m5_trade()\n", "\n", "from apscheduler.schedulers.background import BackgroundScheduler\n", "import time\n", "\n", "\n", "scheduler = BackgroundScheduler()\n", "#scheduler.add_job(main, 'date', run_date='2025-03-07 14:29:50')\n", "\n", "#scheduler.add_job(decide_order, 'interval', minutes=1) #intervall\n", "#scheduler.add_job(set_symbol, 'interval', minutes=30)\n", "#scheduler.add_job(set_trend, 'interval', minutes=1)\n", "\n", "#scheduler.add_job(decide_order, 'interval', minutes=1)\n", "#scheduler.add_job(decide_order, 'cron', year=\"*\", month=\"*\", day_of_week=\"mon, tue, wed, thu, fri\", hour='0-23', minute='*') #cron\n", "#scheduler.add_job(get_buy_sell_signal, 'cron', year=\"*\", month=\"*\", day_of_week=\"mon, tue, wed, thu, fri\", hour='0-23', minute='*/5') #cron\n", "#scheduler.add_job(get_m5_trade_signals, 'cron', year=\"*\", month=\"*\", day_of_week=\"mon, tue, wed, thu, fri\", hour='0-23', minute='*/5') #cron\n", "scheduler.add_job(execute_m5_trade, 'cron', year=\"*\", month=\"*\", day_of_week=\"mon, tue, wed, thu, fri\", hour='0-23', minute='*/5') #cron\n", "scheduler.add_job(manual_update_trailing_sl_tp, 'cron', year=\"*\", month=\"*\", day_of_week=\"mon, tue, wed, thu, fri\", hour='0-23', minute='*') #cron\n", "\n", "#scheduler.add_job(export_marketview, 'cron', year=\"*\", month='*', day_of_week='mon, tue, wed; thu, fri', hour='8-22', minute=00)\n", "\n", "#scheduler.add_job(pause_trading, 'cron', year=\"*\", month=\"*\", day_of_week=\"mon, tue, wed, thu, fri\", hour=22, minute=00) #cron\n", "scheduler.start()\n", "\n", "\n", "scheduler.get_jobs()\n", "\n", "scheduler.remove_all_jobs()\n", "\n", "scheduler.shutdown()" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "#%pip install talib" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "#!pip install ta\n", "from ta.trend import ADXIndicator, EMAIndicator\n", "from ta.momentum import RSIIndicator\n", "from talib import CDLHAMMER, CDLSHOOTINGSTAR" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "import matplotlib.pyplot as plt\n", "import mplfinance as mpf\n", "import keyring as kr\n", "import MetaTrader5 as mt\n", "import requests\n", "import re\n", "from time import sleep\n", "import sqlite3 as db\n", "#import matplotlib.pyplot as plt\n", "import pandas_ta as ta\n", "import numpy as np\n", "\n", "from sklearn.linear_model import LinearRegression\n", "from scipy.signal import savgol_filter\n", "from scipy.signal import find_peaks\n", "\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Login" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# login to your Trading Account - sign up in the description\n", "mt.initialize()\n", " \n", "login = 10800246\n", "server = 'VantageInternational-Demo'\n", "password = kr.get_password(server, str(login))\n", "\n", "\n", "mt.login(login, password, server)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'trading-demo'" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "project = \"trading-\" + server[-4::1]\n", "project = project.lower()\n", "project" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Set symbol and volume" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "pause_trading = 0\n" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "symbols = ['XAUUSD']\n", "#symbols = ['BTCUSD']\n", "\n", "#'BTCUSD', 'ETHUSD', \n", " #'XRPUSD', , 'EURNZD', 'EURUSD'" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "volume_dict = {\n", " 'BTCUSD' : 0.1,\n", " 'BTCUSD_short' : 0.1,\n", "\n", " 'ETHUSD' : 1.0,\n", " 'ETHUSD_short' : 1.0,\n", " \n", " 'XRPUSD': 0.1,\n", " 'XRPUSD_short': 0.1,\n", "\n", " 'XAUUSD': 0.1,\n", " 'XAUUSD_short': 0.1,\n", "\n", " 'EURUSD': 0.1,\n", " 'EURUSD_short': 0.1,\n", "\n", " 'EURNZD': 0.1,\n", " 'EURNZD_short': 0.1,\n", "\n", "}" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "periods_dict = {\n", " 'BTCUSD' : ['h1', 'm30', 'm15', 'm5', 'm1'],\n", " \n", " 'ETHUSD' : ['h1', 'm30', 'm15', 'm5', 'm1'],\n", "\n", " \n", " 'XRPUSD': ['h1', 'm30', 'm15', 'm5', 'm1'],\n", " \n", " 'XAUUSD': [ 'm15'],\n", "\n", " \n", " 'EURUSD': ['h1', 'm30', 'm15', 'm5', 'm1'],\n", "\n", "\n", " 'EURNZD': ['m5', 'm2', 'm1'],\n", "\n", "}" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "def get_symbol():\n", " global symbols, pause_trading, periods_dict\n", " pricemovement = {}\n", "\n", " for s in symbols:\n", " items = mt.symbol_info(s)\n", " pricemovement[s] = round(items.price_change,2)\n", " #print(s, round(items.price_change,2))\n", "\n", " #percentage = pricemovement[max(pricemovement, key=pricemovement.get)]\n", " #symbol = max(pricemovement, key=pricemovement.get)\n", " #volume = volume_dict[symbol]\n", "\n", " sorted_pricemovement = sorted(pricemovement.items(), key=lambda x:x[1], reverse=True)\n", " converted_dict = dict(sorted_pricemovement)\n", "\n", " print(converted_dict)\n", "\n", " percentage = converted_dict[max(converted_dict, key=converted_dict.get)]\n", " symbol = max(converted_dict, key=converted_dict.get)\n", " volume = volume_dict[symbol]\n", "\n", "\n", " print(symbol, percentage, volume)\n", " # if percentage > 0: # and percentage < 0.8:\n", " # periods_dict[symbol] = ['m15', 'm5', 'm2', 'm1']\n", " # elif percentage > 0.8:\n", " # periods_dict[symbol] = ['h1', 'm30', 'm15', 'm5', 'm1']\n", "\n", " #\n", "\n", " #print(periods_dict)\n", "\n", " # if percentage > 0 and mt.positions_total() == 0:\n", " # pause_trading = 0 #0 no puase\n", " # return symbol, percentage, volume, periods_dict\n", " # elif percentage < 0.1 and mt.positions_total() == 0:\n", " # print(\"aktuell kein neues Symbol, pause Trading\")\n", " # pause_trading = 1 #1 pause\n", " # return None\n", "\n", " return symbol, percentage, volume, periods_dict" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'XAUUSD': 1.08}\n", "XAUUSD 1.08 0.1\n" ] }, { "data": { "text/plain": [ "('XAUUSD',\n", " 1.08,\n", " 0.1,\n", " {'BTCUSD': ['h1', 'm30', 'm15', 'm5', 'm1'],\n", " 'ETHUSD': ['h1', 'm30', 'm15', 'm5', 'm1'],\n", " 'XRPUSD': ['h1', 'm30', 'm15', 'm5', 'm1'],\n", " 'XAUUSD': ['m15'],\n", " 'EURUSD': ['h1', 'm30', 'm15', 'm5', 'm1'],\n", " 'EURNZD': ['m5', 'm2', 'm1']})" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "get_symbol()" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "def set_symbol():\n", " global symbol, volume, volume_dict\n", " symb = get_symbol()\n", " if symb != None:\n", " symbol = symb[0]\n", " volume = volume_dict[symb[0]]\n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## set volume manuell" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'XAUUSD': 1.08}\n", "XAUUSD 1.08 0.1\n" ] }, { "data": { "text/plain": [ "('XAUUSD',\n", " 1.08,\n", " 0.1,\n", " {'BTCUSD': ['h1', 'm30', 'm15', 'm5', 'm1'],\n", " 'ETHUSD': ['h1', 'm30', 'm15', 'm5', 'm1'],\n", " 'XRPUSD': ['h1', 'm30', 'm15', 'm5', 'm1'],\n", " 'XAUUSD': ['m15'],\n", " 'EURUSD': ['h1', 'm30', 'm15', 'm5', 'm1'],\n", " 'EURNZD': ['m5', 'm2', 'm1']})" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "get_symbol()" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'XAUUSD': 1.08}\n", "XAUUSD 1.08 0.1\n" ] } ], "source": [ "set_symbol()\n" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "('XAUUSD', 0.1, 0)" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "symbol, volume, pause_trading" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Functions to place Orders on Market" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pos = mt.positions_get()\n", "for i in pos:\n", " #if i.comment == 'Retracement Bot':\n", " # print(i.ticket)\n", "\n", " if bool(re.search('^BuyStop[0-9]{2}', i.comment)):\n", " print(i.ticket)\n", "\n", "mt.positions_total()" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Retracement Bot\n", "(TradePosition(ticket=382221755, time=1756930501, time_msc=1756930501001, time_update=1756930501, time_update_msc=1756930501001, type=0, magic=30, identifier=382221755, reason=3, volume=0.1, price_open=3572.38, sl=3569.69, tp=3580.45, price_current=3572.1, swap=0.0, profit=-2.8, symbol='XAUUSD', comment='Retracement Bot', external_id=''),)\n" ] } ], "source": [ "strategy_name = 'Retracement Bot'\n", "pos = mt.positions_get()\n", "for p in pos:\n", " if p.comment == strategy_name:\n", " print(p.comment)\n", "print(pos)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Market Order Function" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [], "source": [ "def market_order(symbol, volume, order_type, deviation=20, magic=30, stoploss=0.0, take_profit=0.0,\n", " strategy_name='Retracement Bot'):\n", "\n", " global project, pause_trading\n", "\n", " project_id_dict = {\n", " 'trading-demo': 'a3f3ae',\n", " 'trading-live': '747543'\n", " }\n", "\n", " order_type_dict = {\n", " 'buy': mt.ORDER_TYPE_BUY,\n", " 'sell': mt.ORDER_TYPE_SELL\n", " }\n", "\n", " price_dict = {\n", " 'buy': mt.symbol_info_tick(symbol).ask,\n", " 'sell': mt.symbol_info_tick(symbol).bid\n", " }\n", "\n", " buypos = []\n", "\n", " pos = mt.positions_get()\n", " for p in pos:\n", " if p.comment == strategy_name:\n", " buypos.append('true')\n", " \n", " activepos = buypos.count('true')\n", "\n", " if order_type == 'buy' and activepos == 0 and pause_trading == 0: # and mt.positions_total() == 0:\n", " \n", " request = {\n", " \"action\": mt.TRADE_ACTION_DEAL,\n", " \"symbol\": symbol,\n", " \"volume\": volume, # FLOAT\n", " \"type\": order_type_dict[order_type],\n", " \"price\": price_dict[order_type],\n", " \"sl\": stoploss, # FLOAT\n", " \"tp\": take_profit, # FLOAT\n", " \"deviation\": deviation, # INTERGER\n", " \"magic\": magic, # INTERGER\n", " \"comment\": strategy_name,\n", " \"type_time\": mt.ORDER_TIME_GTC,\n", " \"type_filling\": mt.ORDER_FILLING_IOC, # mt.ORDER_FILLING_FOK if IOC does not work\n", " }\n", "\n", " requests.post('https://api.mynotifier.app', {\n", " \"apiKey\": 'beafb52e-3cb6-477a-92ef-2f10bff50e20',\n", " \"message\": \"Es wrude ein Handel eröffnet!\",\n", " \"description\": \"Bitte kontrolliere die Position\",\n", " \"type\": \"info\",#\"info\", # info, error, warning or success\n", " \"project\": project_id_dict[project]\n", " })\n", "\n", " order_result = mt.order_send(request)\n", " #return (order_result)\n", " \n", " elif order_type == 'sell' and mt.positions_total() > 0:\n", " pos = mt.positions_get()\n", " for p in pos:\n", " if p.comment == strategy_name:\n", " # while schleife ?\n", " positions = mt.positions_get()\n", " ticket = p.ticket\n", " request = {\n", " \"action\": mt.TRADE_ACTION_DEAL,\n", " \"symbol\": symbol,\n", " \"volume\": volume, # FLOAT\n", " \"type\": order_type_dict[order_type],\n", " \"price\": price_dict[order_type],\n", " \"position\": ticket,\n", " \"sl\": stoploss, # FLOAT\n", " \"tp\": take_profit, # FLOAT\n", " \"deviation\": deviation, # INTERGER\n", " \"magic\": magic, # INTERGER\n", " \"comment\": strategy_name,\n", " \"type_time\": mt.ORDER_TIME_GTC,\n", " \"type_filling\": mt.ORDER_FILLING_IOC, # mt.ORDER_FILLING_FOK if IOC does not work\n", " }\n", "\n", " requests.post('https://api.mynotifier.app', {\n", " \"apiKey\": 'beafb52e-3cb6-477a-92ef-2f10bff50e20',\n", " \"message\": \"Es wrude ein Handel geschlossen!\",\n", " \"description\": \"Bitte prüfe die Position\",\n", " \"type\": \"info\",#\"info\", # info, error, warning or success\n", " \"project\": project_id_dict[project]\n", " })\n", "\n", " order_result = mt.order_send(request)\n", " #return (order_result)\n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Trend Detection" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## timefame & trend dictionary" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "debug = False" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [], "source": [ "trend_dict = {\n", " #'m5': '',\n", " #'m10': '',\n", " 'm15': '',\n", " #'m30': '',\n", " #'h4': '',\n", "}" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [], "source": [ "timeframes_dict = {\n", " 'm1': mt.TIMEFRAME_M1,\n", " 'm2': mt.TIMEFRAME_M2,\n", " 'm3': mt.TIMEFRAME_M3,\n", " 'm5': mt.TIMEFRAME_M5,\n", " 'm15': mt.TIMEFRAME_M15,\n", " 'm20': mt.TIMEFRAME_M20,\n", " 'm30': mt.TIMEFRAME_M30,\n", " 'h1': mt.TIMEFRAME_H1,\n", " 'h4': mt.TIMEFRAME_H4,\n", " 'd1': mt.TIMEFRAME_D1,\n", "}\n", "\n", "\n", "# timeframes = {\n", "# 'm1': mt.TIMEFRAME_M1,\n", "# 'm2': mt.TIMEFRAME_M2,\n", "# 'm3': mt.TIMEFRAME_M3,\n", "# 'm5': mt.TIMEFRAME_M5,\n", "# 'm15': mt.TIMEFRAME_M15,\n", "# 'm20': mt.TIMEFRAME_M20,\n", "# 'm30': mt.TIMEFRAME_M30,\n", "# 'h1': mt.TIMEFRAME_H1,\n", "# }" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'m15': ''}\n" ] } ], "source": [ "print(trend_dict)" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "def get_rates(periode, bars=300):\n", " #global symbol\n", "\n", " # OHLC abrufen\n", " ohlc = mt.copy_rates_from_pos(symbol, timeframes_dict[periode], 0, bars)\n", " df = pd.DataFrame(ohlc)\n", " df['time'] = pd.to_datetime(df['time'], unit='s')\n", "\n", " # Umwandeln in float\n", " df[\"open\"] = df[\"open\"].astype(float)\n", " df[\"high\"] = df[\"high\"].astype(float)\n", " df[\"low\"] = df[\"low\"].astype(float)\n", " df[\"close\"] = df[\"close\"].astype(float)\n", "\n", " # ATR berechnen (klassisch 14)\n", " df[\"atr\"] = ta.atr(high=df[\"high\"], low=df[\"low\"], close=df[\"close\"], length=14)\n", "\n", " # leichte Glättung (optional, um Rauschen zu reduzieren)\n", " df[\"atr\"] = df[\"atr\"].rolling(window=5).mean()\n", "\n", " # Index setzen\n", " df.set_index(\"time\", inplace=True)\n", "\n", " # NaNs entfernen (anfangs durch ATR-Berechnung)\n", " df = df.dropna()\n", "\n", " return df\n" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
openhighlowclosetick_volumespreadreal_volumeatr
time
2025-07-23 16:00:003419.983420.523381.473387.388969219013.861980
2025-07-23 20:00:003387.333395.943385.743386.784953419014.128410
2025-07-24 00:00:003388.013393.163386.483391.441849619014.305667
2025-07-24 04:00:003391.443393.363374.713382.575631519014.547405
2025-07-24 08:00:003382.563382.923365.823369.685466319014.818019
...........................
2025-09-03 04:00:003536.073545.893529.363536.815969720018.731740
2025-09-03 08:00:003536.823541.193526.933539.995847620019.107330
2025-09-03 12:00:003540.043551.433532.293550.566300020019.007235
2025-09-03 16:00:003550.603572.573549.383572.438737520018.985718
2025-09-03 20:00:003572.453572.983570.243572.12442820018.713310
\n", "

182 rows × 8 columns

\n", "
" ], "text/plain": [ " open high low close tick_volume spread \\\n", "time \n", "2025-07-23 16:00:00 3419.98 3420.52 3381.47 3387.38 89692 19 \n", "2025-07-23 20:00:00 3387.33 3395.94 3385.74 3386.78 49534 19 \n", "2025-07-24 00:00:00 3388.01 3393.16 3386.48 3391.44 18496 19 \n", "2025-07-24 04:00:00 3391.44 3393.36 3374.71 3382.57 56315 19 \n", "2025-07-24 08:00:00 3382.56 3382.92 3365.82 3369.68 54663 19 \n", "... ... ... ... ... ... ... \n", "2025-09-03 04:00:00 3536.07 3545.89 3529.36 3536.81 59697 20 \n", "2025-09-03 08:00:00 3536.82 3541.19 3526.93 3539.99 58476 20 \n", "2025-09-03 12:00:00 3540.04 3551.43 3532.29 3550.56 63000 20 \n", "2025-09-03 16:00:00 3550.60 3572.57 3549.38 3572.43 87375 20 \n", "2025-09-03 20:00:00 3572.45 3572.98 3570.24 3572.12 4428 20 \n", "\n", " real_volume atr \n", "time \n", "2025-07-23 16:00:00 0 13.861980 \n", "2025-07-23 20:00:00 0 14.128410 \n", "2025-07-24 00:00:00 0 14.305667 \n", "2025-07-24 04:00:00 0 14.547405 \n", "2025-07-24 08:00:00 0 14.818019 \n", "... ... ... \n", "2025-09-03 04:00:00 0 18.731740 \n", "2025-09-03 08:00:00 0 19.107330 \n", "2025-09-03 12:00:00 0 19.007235 \n", "2025-09-03 16:00:00 0 18.985718 \n", "2025-09-03 20:00:00 0 18.713310 \n", "\n", "[182 rows x 8 columns]" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "get_rates('h4', 200)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "| Parameter | Wirkung |\n", "| ------------ | ------------------------------------------- |\n", "| `distance` | Wie **nah beieinander** Peaks liegen dürfen |\n", "| `width` | Wie **breit/flach** ein Peak sein muss |\n", "| `prominence` | Wie **stark auffällig** ein Peak sein muss |\n" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [], "source": [ "def get_trend(timeframe=\"h4\", lookback=150):\n", " \"\"\"\n", " Bestimme Trendrichtung per Linear Regression.\n", " Liefert:\n", " - trend: \"uptrend\" / \"downtrend\" / \"sideways\"\n", " - slope: numerischer Wert der Regression\n", " - atr: ATR des Zeitraums\n", " - slope_threshold: dynamische Schwelle für Seitwärtsbewegungen\n", " \"\"\"\n", " df = get_rates(timeframe, lookback)\n", " if df.empty:\n", " return {\"trend\": \"sideways\", \"slope\": 0, \"atr\": 0, \"slope_threshold\": 0}\n", "\n", " # Linear Regression\n", " X = np.arange(len(df)).reshape(-1, 1)\n", " y = df[\"close\"].values.reshape(-1, 1)\n", " slope = LinearRegression().fit(X, y).coef_[0][0]\n", "\n", " # ATR\n", " df[\"hl\"] = df[\"high\"] - df[\"low\"]\n", " df[\"hc\"] = (df[\"high\"] - df[\"close\"].shift()).abs()\n", " df[\"lc\"] = (df[\"low\"] - df[\"close\"].shift()).abs()\n", " df[\"tr\"] = df[[\"hl\",\"hc\",\"lc\"]].max(axis=1)\n", " atr = df[\"tr\"].rolling(14).mean().iloc[-1]\n", "\n", " slope_threshold = (atr / df[\"close\"].iloc[-1]) * 1.2\n", "\n", " if abs(slope) < slope_threshold:\n", " trend = \"sideways\"\n", " else:\n", " trend = \"uptrend\" if slope > 0 else \"downtrend\"\n", "\n", " return {\n", " \"trend\": trend,\n", " \"slope\": slope,\n", " \"atr\": atr,\n", " \"slope_threshold\": slope_threshold\n", " }\n" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [], "source": [ "def get_top_down_signal(symbol=symbol):\n", " \"\"\"\n", " Top-Down Ansatz:\n", " - D1 / H4: Trend bestimmen\n", " - H1 / M30: Setup identifizieren\n", " - M15 / M5: Einstiege optimieren (Signale ohne Tradeausführung)\n", " \"\"\"\n", " global trend_dict\n", "\n", " # --- Höhere Timeframes ---\n", " d1_trend_info = get_trend(\"d1\", lookback=200)\n", " h4_trend_info = get_trend(\"h4\", lookback=150)\n", "\n", " # --- Mittlere Timeframes für Setups ---\n", " h1_trend_info = get_trend(\"h1\", lookback=100)\n", " m30_trend_info = get_trend(\"m30\", lookback=60)\n", "\n", " # --- Niedrigere Timeframes für Einstiege (nur Signal, kein Trade) ---\n", " m15_trend_info = get_trend(\"m15\", lookback=50)\n", " m5_trend_info = get_trend(\"m5\", lookback=20)\n", "\n", " # --- Konsolidierte Trendanalyse ---\n", " top_down_trend = \"sideways\"\n", " if d1_trend_info[\"trend\"] == h4_trend_info[\"trend\"]:\n", " top_down_trend = d1_trend_info[\"trend\"]\n", "\n", " # --- Setup-Bedingungen ---\n", " setup_ready = False\n", " if top_down_trend != \"sideways\":\n", " if h1_trend_info[\"trend\"] == top_down_trend and m30_trend_info[\"trend\"] == top_down_trend:\n", " setup_ready = True\n", "\n", " # --- Einstiegsberechnung ---\n", " entry_signal = 0\n", " if setup_ready:\n", " if m15_trend_info[\"trend\"] == top_down_trend and m5_trend_info[\"trend\"] == top_down_trend:\n", " entry_signal = 1 if top_down_trend == \"uptrend\" else -1\n", "\n", " # --- Speichern ---\n", " trend_dict[\"top_down\"] = {\n", " \"D1\": d1_trend_info,\n", " \"H4\": h4_trend_info,\n", " \"H1\": h1_trend_info,\n", " \"M30\": m30_trend_info,\n", " \"M15\": m15_trend_info,\n", " \"M5\": m5_trend_info,\n", " \"top_down_trend\": top_down_trend,\n", " \"setup_ready\": setup_ready,\n", " \"entry_signal\": entry_signal\n", " }\n", "\n", " return trend_dict[\"top_down\"]\n" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'trend': 'uptrend',\n", " 'slope': 1.4477744934856227,\n", " 'atr': 9.130714285714314,\n", " 'slope_threshold': 0.0030673261656543383}" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "get_trend(\"h1\")" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'D1': {'trend': 'uptrend',\n", " 'slope': 4.621913228515892,\n", " 'atr': 39.36499999999988,\n", " 'slope_threshold': 0.013270331238569827},\n", " 'H4': {'trend': 'uptrend',\n", " 'slope': 0.8813408347377812,\n", " 'atr': 20.499285714285698,\n", " 'slope_threshold': 0.006910512170269389},\n", " 'H1': {'trend': 'uptrend',\n", " 'slope': 1.8054590176423853,\n", " 'atr': 9.649999999999993,\n", " 'slope_threshold': 0.0032531105411456656},\n", " 'M30': {'trend': 'uptrend',\n", " 'slope': 1.0648326715825298,\n", " 'atr': 6.73500000000003,\n", " 'slope_threshold': 0.0022704351807892403},\n", " 'M15': {'trend': 'uptrend',\n", " 'slope': 0.3136986803519024,\n", " 'atr': 4.114285714285676,\n", " 'slope_threshold': 0.0013869664483344836},\n", " 'M5': {'trend': 'downtrend',\n", " 'slope': -0.909999999999854,\n", " 'atr': nan,\n", " 'slope_threshold': nan},\n", " 'top_down_trend': 'uptrend',\n", " 'setup_ready': True,\n", " 'entry_signal': 0}" ] }, "execution_count": 56, "metadata": {}, "output_type": "execute_result" } ], "source": [ "get_top_down_signal(symbol)" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'trend': 'uptrend',\n", " 'slope': 0.8855957903085263,\n", " 'atr': 19.30285714285713,\n", " 'slope_threshold': 0.006484504599909453}" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "get_trend()" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [], "source": [ "def get_trend_fast(period):\n", " global trend_dict, periods_dict, symbol\n", "\n", " df2 = get_rates(period).iloc[-200:]\n", " df2[\"close_smooth\"] = savgol_filter(df2.close, 15, 5) # kleinere Glättung\n", "\n", " atr = df2.atr.iloc[-1]\n", "\n", " # Weniger strenge Peak-Erkennung\n", " peaks_idx, _ = find_peaks(df2.close_smooth, distance=1, width=2, prominence=atr*0.5) #evtl kleiner 0.5\n", " troughs_idx, _ = find_peaks(-1*df2.close_smooth, distance=1, width=2, prominence=atr*0.5)\n", "\n", " # Trend über Peaks/Troughs\n", " if len(peaks_idx) > 0 and len(troughs_idx) > 0:\n", " if peaks_idx[-1] > troughs_idx[-1]:\n", " trend = \"downtrend\"\n", " else:\n", " trend = \"uptrend\"\n", " else:\n", " # Falls keine klaren Peaks gefunden wurden → Slope nutzen\n", " slope = df2.close_smooth.diff().iloc[-5:].mean()\n", " trend = \"downtrend\" if slope < 0 else \"uptrend\"\n", "\n", " trend_dict[period] = trend\n", " return trend\n" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'uptrend'" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "get_trend_fast('m15')" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [], "source": [ "def set_trend():\n", "\n", " global pause_trading, periods_dict, trend_dict\n", "\n", " for k,v in trend_dict.items():\n", " get_trend_fast(k) \n", " print(k)\n", " \n", " for k,v in reversed(trend_dict.items()):\n", "\n", " if v == 'uptrend':\n", " print(k,v)\n", " periods_dict[symbol] = [k]\n", " pause_trading = 0\n", " print(f\"Pause Trading: {pause_trading}\")\n", " break\n", " elif v == 'downtrend':\n", " periods_dict[symbol] = [k] #['m15']\n", " pause_trading = 1\n", " print(f\"Pause Trading: {pause_trading}\")" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "m15\n" ] }, { "ename": "KeyError", "evalue": "'top_down'", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mKeyError\u001b[0m Traceback (most recent call last)", "Cell \u001b[1;32mIn[34], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m set_trend()\n", "Cell \u001b[1;32mIn[33], line 6\u001b[0m, in \u001b[0;36mset_trend\u001b[1;34m()\u001b[0m\n\u001b[0;32m 3\u001b[0m \u001b[38;5;28;01mglobal\u001b[39;00m pause_trading, periods_dict, trend_dict\n\u001b[0;32m 5\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m k,v \u001b[38;5;129;01min\u001b[39;00m trend_dict\u001b[38;5;241m.\u001b[39mitems():\n\u001b[1;32m----> 6\u001b[0m get_trend_fast(k) \n\u001b[0;32m 7\u001b[0m \u001b[38;5;28mprint\u001b[39m(k)\n\u001b[0;32m 9\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m k,v \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mreversed\u001b[39m(trend_dict\u001b[38;5;241m.\u001b[39mitems()):\n", "Cell \u001b[1;32mIn[31], line 4\u001b[0m, in \u001b[0;36mget_trend_fast\u001b[1;34m(period)\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mget_trend_fast\u001b[39m(period):\n\u001b[0;32m 2\u001b[0m \u001b[38;5;28;01mglobal\u001b[39;00m trend_dict, periods_dict, symbol\n\u001b[1;32m----> 4\u001b[0m df2 \u001b[38;5;241m=\u001b[39m get_rates(period)\u001b[38;5;241m.\u001b[39miloc[\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m200\u001b[39m:]\n\u001b[0;32m 5\u001b[0m df2[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mclose_smooth\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m=\u001b[39m savgol_filter(df2\u001b[38;5;241m.\u001b[39mclose, \u001b[38;5;241m15\u001b[39m, \u001b[38;5;241m5\u001b[39m) \u001b[38;5;66;03m# kleinere Glättung\u001b[39;00m\n\u001b[0;32m 7\u001b[0m atr \u001b[38;5;241m=\u001b[39m df2\u001b[38;5;241m.\u001b[39matr\u001b[38;5;241m.\u001b[39miloc[\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m1\u001b[39m]\n", "Cell \u001b[1;32mIn[24], line 5\u001b[0m, in \u001b[0;36mget_rates\u001b[1;34m(periode, bars)\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mget_rates\u001b[39m(periode, bars\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m300\u001b[39m):\n\u001b[0;32m 2\u001b[0m \u001b[38;5;66;03m#global symbol\u001b[39;00m\n\u001b[0;32m 3\u001b[0m \n\u001b[0;32m 4\u001b[0m \u001b[38;5;66;03m# OHLC abrufen\u001b[39;00m\n\u001b[1;32m----> 5\u001b[0m ohlc \u001b[38;5;241m=\u001b[39m mt\u001b[38;5;241m.\u001b[39mcopy_rates_from_pos(symbol, timeframes_dict[periode], \u001b[38;5;241m0\u001b[39m, bars)\n\u001b[0;32m 6\u001b[0m df \u001b[38;5;241m=\u001b[39m pd\u001b[38;5;241m.\u001b[39mDataFrame(ohlc)\n\u001b[0;32m 7\u001b[0m df[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtime\u001b[39m\u001b[38;5;124m'\u001b[39m] \u001b[38;5;241m=\u001b[39m pd\u001b[38;5;241m.\u001b[39mto_datetime(df[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtime\u001b[39m\u001b[38;5;124m'\u001b[39m], unit\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124ms\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", "\u001b[1;31mKeyError\u001b[0m: 'top_down'" ] } ], "source": [ "set_trend()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Set Trend manually" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(0,\n", " {'m15': 'uptrend',\n", " 'top_down': {'D1': {'trend': 'uptrend',\n", " 'slope': 4.621913228515892,\n", " 'atr': 39.36499999999988,\n", " 'slope_threshold': 0.013270331238569827},\n", " 'H4': {'trend': 'uptrend',\n", " 'slope': 0.8813408347377812,\n", " 'atr': 20.499285714285698,\n", " 'slope_threshold': 0.006910512170269389},\n", " 'H1': {'trend': 'uptrend',\n", " 'slope': 1.8054590176423853,\n", " 'atr': 9.649999999999993,\n", " 'slope_threshold': 0.0032531105411456656},\n", " 'M30': {'trend': 'uptrend',\n", " 'slope': 1.0648326715825298,\n", " 'atr': 6.73500000000003,\n", " 'slope_threshold': 0.0022704351807892403},\n", " 'M15': {'trend': 'uptrend',\n", " 'slope': 0.3136986803519024,\n", " 'atr': 4.114285714285676,\n", " 'slope_threshold': 0.0013869664483344836},\n", " 'M5': {'trend': 'downtrend',\n", " 'slope': -0.909999999999854,\n", " 'atr': nan,\n", " 'slope_threshold': nan},\n", " 'top_down_trend': 'uptrend',\n", " 'setup_ready': True,\n", " 'entry_signal': 0},\n", " 'm5': {'standard': 'downtrend', 'fast': 'downtrend', 'signal': -1}},\n", " {'BTCUSD': ['h1', 'm30', 'm15', 'm5', 'm1'],\n", " 'ETHUSD': ['h1', 'm30', 'm15', 'm5', 'm1'],\n", " 'XRPUSD': ['h1', 'm30', 'm15', 'm5', 'm1'],\n", " 'XAUUSD': ['m15'],\n", " 'EURUSD': ['h1', 'm30', 'm15', 'm5', 'm1'],\n", " 'EURNZD': ['m5', 'm2', 'm1']},\n", " 'XAUUSD')" ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" }, { "name": "stdout", "output_type": "stream", "text": [ "Kein Top-Down-Setup vorhanden. Kein Trade.\n" ] } ], "source": [ "pause_trading, trend_dict, periods_dict, symbols[0]" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "m15\n" ] }, { "ename": "KeyError", "evalue": "'top_down'", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mKeyError\u001b[0m Traceback (most recent call last)", "Cell \u001b[1;32mIn[36], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m set_trend()\n", "Cell \u001b[1;32mIn[33], line 6\u001b[0m, in \u001b[0;36mset_trend\u001b[1;34m()\u001b[0m\n\u001b[0;32m 3\u001b[0m \u001b[38;5;28;01mglobal\u001b[39;00m pause_trading, periods_dict, trend_dict\n\u001b[0;32m 5\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m k,v \u001b[38;5;129;01min\u001b[39;00m trend_dict\u001b[38;5;241m.\u001b[39mitems():\n\u001b[1;32m----> 6\u001b[0m get_trend_fast(k) \n\u001b[0;32m 7\u001b[0m \u001b[38;5;28mprint\u001b[39m(k)\n\u001b[0;32m 9\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m k,v \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mreversed\u001b[39m(trend_dict\u001b[38;5;241m.\u001b[39mitems()):\n", "Cell \u001b[1;32mIn[31], line 4\u001b[0m, in \u001b[0;36mget_trend_fast\u001b[1;34m(period)\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mget_trend_fast\u001b[39m(period):\n\u001b[0;32m 2\u001b[0m \u001b[38;5;28;01mglobal\u001b[39;00m trend_dict, periods_dict, symbol\n\u001b[1;32m----> 4\u001b[0m df2 \u001b[38;5;241m=\u001b[39m get_rates(period)\u001b[38;5;241m.\u001b[39miloc[\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m200\u001b[39m:]\n\u001b[0;32m 5\u001b[0m df2[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mclose_smooth\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m=\u001b[39m savgol_filter(df2\u001b[38;5;241m.\u001b[39mclose, \u001b[38;5;241m15\u001b[39m, \u001b[38;5;241m5\u001b[39m) \u001b[38;5;66;03m# kleinere Glättung\u001b[39;00m\n\u001b[0;32m 7\u001b[0m atr \u001b[38;5;241m=\u001b[39m df2\u001b[38;5;241m.\u001b[39matr\u001b[38;5;241m.\u001b[39miloc[\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m1\u001b[39m]\n", "Cell \u001b[1;32mIn[24], line 5\u001b[0m, in \u001b[0;36mget_rates\u001b[1;34m(periode, bars)\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mget_rates\u001b[39m(periode, bars\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m300\u001b[39m):\n\u001b[0;32m 2\u001b[0m \u001b[38;5;66;03m#global symbol\u001b[39;00m\n\u001b[0;32m 3\u001b[0m \n\u001b[0;32m 4\u001b[0m \u001b[38;5;66;03m# OHLC abrufen\u001b[39;00m\n\u001b[1;32m----> 5\u001b[0m ohlc \u001b[38;5;241m=\u001b[39m mt\u001b[38;5;241m.\u001b[39mcopy_rates_from_pos(symbol, timeframes_dict[periode], \u001b[38;5;241m0\u001b[39m, bars)\n\u001b[0;32m 6\u001b[0m df \u001b[38;5;241m=\u001b[39m pd\u001b[38;5;241m.\u001b[39mDataFrame(ohlc)\n\u001b[0;32m 7\u001b[0m df[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtime\u001b[39m\u001b[38;5;124m'\u001b[39m] \u001b[38;5;241m=\u001b[39m pd\u001b[38;5;241m.\u001b[39mto_datetime(df[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtime\u001b[39m\u001b[38;5;124m'\u001b[39m], unit\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124ms\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", "\u001b[1;31mKeyError\u001b[0m: 'top_down'" ] } ], "source": [ "set_trend()" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'uptrend'" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "trend_dict[periods_dict[symbol][0]]" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(['m15'], 0)" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "periods_dict[symbol], pause_trading" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Generate signals" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [], "source": [ "def get_mt5_data(symbol=symbol, timeframe=mt.TIMEFRAME_M15, n_bars=500):\n", " rates = mt.copy_rates_from_pos(symbol, timeframe, 0, n_bars)\n", " df = pd.DataFrame(rates)\n", " df[\"time\"] = pd.to_datetime(df[\"time\"], unit=\"s\")\n", " return df" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [], "source": [ "def get_m5_trade_signal(symbol, atr_mult=1.5):\n", " global trend_dict, periods_dict\n", "\n", " # Hole die letzten M5-Daten\n", " df = get_rates('m5').iloc[-200:]\n", "\n", " # Smoothen\n", " df[\"close_smooth_std\"] = savgol_filter(df.close, 25, 5)\n", " df[\"close_smooth_fast\"] = savgol_filter(df.close, 15, 5)\n", "\n", " atr = df.atr.iloc[-1]\n", "\n", " # --- Standard-Trend ---\n", " peaks_std, _ = find_peaks(df.close_smooth_std, distance=1, width=2, prominence=atr)\n", " troughs_std, _ = find_peaks(-df.close_smooth_std, distance=1, width=2, prominence=atr)\n", "\n", " if len(peaks_std) > 0 and len(troughs_std) > 0:\n", " if peaks_std[-1] > troughs_std[-1]:\n", " trend_standard = \"downtrend\"\n", " else:\n", " trend_standard = \"uptrend\"\n", " else:\n", " trend_standard = \"neutral\"\n", "\n", " # --- Fast-Trend ---\n", " peaks_fast, _ = find_peaks(df.close_smooth_fast, distance=1, width=2, prominence=atr*0.5)\n", " troughs_fast, _ = find_peaks(-df.close_smooth_fast, distance=1, width=2, prominence=atr*0.5)\n", "\n", " if len(peaks_fast) > 0 and len(troughs_fast) > 0:\n", " if peaks_fast[-1] > troughs_fast[-1]:\n", " trend_fast = \"downtrend\"\n", " else:\n", " trend_fast = \"uptrend\"\n", " else:\n", " slope = df.close_smooth_fast.diff().iloc[-5:].mean()\n", " trend_fast = \"downtrend\" if slope < 0 else \"uptrend\"\n", "\n", " # --- Kombiniertes Signal ---\n", " signal = 0 # 0 = neutral, 1 = long, -1 = short\n", " stop_loss = None\n", "\n", " if trend_standard == \"uptrend\" and trend_fast == \"uptrend\":\n", " signal = 1\n", " stop_loss = df.close.iloc[-1] - atr_mult * atr\n", " elif trend_standard == \"downtrend\" and trend_fast == \"downtrend\":\n", " signal = -1\n", " stop_loss = df.close.iloc[-1] + atr_mult * atr\n", "\n", " # Speichern\n", " trend_dict['m5'] = {\"standard\": trend_standard, \"fast\": trend_fast, \"signal\": signal}\n", "\n", " return {\n", " \"signal\": signal,\n", " \"price\": df.close.iloc[-1],\n", " \"stop_loss\": stop_loss,\n", " \"trends\": trend_dict['m15']\n", " }\n" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [], "source": [ "def generate_signal(df = get_mt5_data(symbol=symbol, timeframe=timeframes_dict['m15']), confirm_window=3):\n", " \"\"\"\n", " Berechnet drei Signalarten:\n", " - fast_signal: schnelle, aggressive Variante\n", " - standard_signal: konservative Basisstrategie\n", " - optimized_signal: zusätzliche Filter (ATR, ADX, strengerer RSI)\n", " \"\"\"\n", "\n", " # Indikatoren\n", " df[\"ema21\"] = df[\"close\"].ewm(span=3).mean()\n", " df[\"ema50\"] = df[\"close\"].ewm(span=9).mean()\n", " df[\"rsi9\"] = ta.rsi(df[\"close\"], length=9)\n", " df[\"rsi14\"] = ta.rsi(df[\"close\"], length=14)\n", " df[\"trend\"] = savgol_filter(df[\"close\"], 25, 3)\n", "\n", " # Zusätzliche Filterindikatoren\n", " df[\"atr\"] = ta.atr(df[\"high\"], df[\"low\"], df[\"close\"], length=14)\n", " df[\"adx\"] = ta.adx(df[\"high\"], df[\"low\"], df[\"close\"], length=14)[\"ADX_14\"]\n", "\n", " # Spalten für Signale\n", " df[\"fast_signal\"] = 0\n", " df[\"standard_signal\"] = 0\n", " df[\"optimized_signal\"] = 0\n", "\n", " for i in range(1, len(df)):\n", " # -----------------------\n", " # FAST SIGNAL (früh/aggressiv)\n", " # -----------------------\n", " if (\n", " df[\"ema21\"].iloc[i] > df[\"ema50\"].iloc[i]\n", " and df[\"rsi9\"].iloc[i] > 30\n", " ):\n", " df.at[i, \"fast_signal\"] = 1\n", " elif (\n", " df[\"ema21\"].iloc[i] < df[\"ema50\"].iloc[i]\n", " and df[\"rsi9\"].iloc[i] < 60\n", " ):\n", " df.at[i, \"fast_signal\"] = -1\n", "\n", " # -----------------------\n", " # STANDARD SIGNAL (konservativ, ursprüngliche Logik)\n", " # -----------------------\n", " if (\n", " df[\"ema21\"].iloc[i] > df[\"ema50\"].iloc[i]\n", " and df[\"ema21\"].iloc[i - 1] <= df[\"ema50\"].iloc[i - 1]\n", " and df[\"rsi14\"].iloc[i] < 70\n", " and df[\"rsi9\"].iloc[i] > 40\n", " and df[\"trend\"].iloc[i] > df[\"trend\"].iloc[i - 1]\n", " ):\n", " df.at[i, \"standard_signal\"] = 1\n", " elif (\n", " df[\"ema21\"].iloc[i] < df[\"ema50\"].iloc[i]\n", " and df[\"ema21\"].iloc[i - 1] >= df[\"ema50\"].iloc[i - 1]\n", " and df[\"rsi14\"].iloc[i] > 40\n", " and df[\"rsi9\"].iloc[i] < 70\n", " and df[\"trend\"].iloc[i] < df[\"trend\"].iloc[i - 1]\n", " ):\n", " df.at[i, \"standard_signal\"] = -1\n", "\n", " # -----------------------\n", " # OPTIMIZED SIGNAL (mit ADX + ATR + strengerem RSI)\n", " # -----------------------\n", " if (\n", " df[\"ema21\"].iloc[i] > df[\"ema50\"].iloc[i]\n", " and df[\"ema21\"].iloc[i - 1] <= df[\"ema50\"].iloc[i - 1]\n", " and df[\"rsi14\"].iloc[i] < 65 # strengerer Filter\n", " and df[\"rsi9\"].iloc[i] > 45 # Momentum klarer\n", " and df[\"adx\"].iloc[i] > 20 # Trendstärke vorhanden\n", " and df[\"atr\"].iloc[i] > df[\"atr\"].rolling(50).mean().iloc[i] # Volatilität über Durchschnitt\n", " ):\n", " df.at[i, \"optimized_signal\"] = 1\n", " elif (\n", " df[\"ema21\"].iloc[i] < df[\"ema50\"].iloc[i]\n", " and df[\"ema21\"].iloc[i - 1] >= df[\"ema50\"].iloc[i - 1]\n", " and df[\"rsi14\"].iloc[i] > 35 # strengerer Filter unten\n", " and df[\"rsi9\"].iloc[i] < 55\n", " and df[\"adx\"].iloc[i] > 20\n", " and df[\"atr\"].iloc[i] > df[\"atr\"].rolling(50).mean().iloc[i]\n", " ):\n", " df.at[i, \"optimized_signal\"] = -1\n", "\n", " return df\n" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
timeopenhighlowclosetick_volumespreadreal_volumeema21ema50rsi9rsi14trendatradxfast_signalstandard_signaloptimized_signal
02025-08-27 07:45:003374.933375.853373.943374.9324672003374.9300003374.930000NaNNaN3376.087631NaNNaN000
12025-08-27 08:00:003374.913376.213374.113374.7429042003374.8033333374.824444NaNNaN3375.914101NaNNaN000
22025-08-27 08:15:003374.733377.463374.213375.7723132003375.3557143375.211967NaNNaN3375.933879NaNNaN000
32025-08-27 08:30:003375.783378.813375.693377.6927452003376.6006673376.051409NaNNaN3376.121647NaNNaN000
42025-08-27 08:45:003377.683378.883375.853377.2323742003376.9254843376.402013NaNNaN3376.452085NaNNaN000
.........................................................
4952025-09-03 19:15:003565.403568.013564.183567.8338482003566.1953993562.94837671.92194069.3328493568.2193005.67787731.169524100
4962025-09-03 19:30:003567.833569.423566.973569.0134422003567.6026993564.16070173.43148570.3416903569.3603765.44731432.165951100
4972025-09-03 19:45:003569.013572.573568.593572.4335852003570.0163503565.81456177.39422173.1033863570.4686415.34250633.517576100
4982025-09-03 20:00:003572.453572.983570.243572.2238062003571.1181753567.09564976.60494272.6560043571.5395645.15661334.825121100
4992025-09-03 20:15:003572.263572.683571.433572.0610922003571.5890873568.08851975.94112072.2929903572.5686154.87756936.039270100
\n", "

500 rows × 18 columns

\n", "
" ], "text/plain": [ " time open high low close tick_volume \\\n", "0 2025-08-27 07:45:00 3374.93 3375.85 3373.94 3374.93 2467 \n", "1 2025-08-27 08:00:00 3374.91 3376.21 3374.11 3374.74 2904 \n", "2 2025-08-27 08:15:00 3374.73 3377.46 3374.21 3375.77 2313 \n", "3 2025-08-27 08:30:00 3375.78 3378.81 3375.69 3377.69 2745 \n", "4 2025-08-27 08:45:00 3377.68 3378.88 3375.85 3377.23 2374 \n", ".. ... ... ... ... ... ... \n", "495 2025-09-03 19:15:00 3565.40 3568.01 3564.18 3567.83 3848 \n", "496 2025-09-03 19:30:00 3567.83 3569.42 3566.97 3569.01 3442 \n", "497 2025-09-03 19:45:00 3569.01 3572.57 3568.59 3572.43 3585 \n", "498 2025-09-03 20:00:00 3572.45 3572.98 3570.24 3572.22 3806 \n", "499 2025-09-03 20:15:00 3572.26 3572.68 3571.43 3572.06 1092 \n", "\n", " spread real_volume ema21 ema50 rsi9 rsi14 \\\n", "0 20 0 3374.930000 3374.930000 NaN NaN \n", "1 20 0 3374.803333 3374.824444 NaN NaN \n", "2 20 0 3375.355714 3375.211967 NaN NaN \n", "3 20 0 3376.600667 3376.051409 NaN NaN \n", "4 20 0 3376.925484 3376.402013 NaN NaN \n", ".. ... ... ... ... ... ... \n", "495 20 0 3566.195399 3562.948376 71.921940 69.332849 \n", "496 20 0 3567.602699 3564.160701 73.431485 70.341690 \n", "497 20 0 3570.016350 3565.814561 77.394221 73.103386 \n", "498 20 0 3571.118175 3567.095649 76.604942 72.656004 \n", "499 20 0 3571.589087 3568.088519 75.941120 72.292990 \n", "\n", " trend atr adx fast_signal standard_signal \\\n", "0 3376.087631 NaN NaN 0 0 \n", "1 3375.914101 NaN NaN 0 0 \n", "2 3375.933879 NaN NaN 0 0 \n", "3 3376.121647 NaN NaN 0 0 \n", "4 3376.452085 NaN NaN 0 0 \n", ".. ... ... ... ... ... \n", "495 3568.219300 5.677877 31.169524 1 0 \n", "496 3569.360376 5.447314 32.165951 1 0 \n", "497 3570.468641 5.342506 33.517576 1 0 \n", "498 3571.539564 5.156613 34.825121 1 0 \n", "499 3572.568615 4.877569 36.039270 1 0 \n", "\n", " optimized_signal \n", "0 0 \n", "1 0 \n", "2 0 \n", "3 0 \n", "4 0 \n", ".. ... \n", "495 0 \n", "496 0 \n", "497 0 \n", "498 0 \n", "499 0 \n", "\n", "[500 rows x 18 columns]" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "generate_signal()" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Trailing +TP for BUY XAUUSD: 3572.2200000000003 CP: 3572.06\n" ] } ], "source": [ "pos = mt.positions_total()\n", "\n", "if pos > 0:\n", " open_positions = mt.positions_get() \n", " trail_factor = 0.5\n", " entry_price = open_positions[0].price_open\n", " tp_current = open_positions[0].tp\n", " current_price = open_positions[0].price_current\n", " profit = open_positions[0].profit\n", "\n", " profit = current_price - entry_price\n", " if profit > 0:\n", " new_tp = current_price - entry_price * trail_factor\n", " \n", " if profit < 0:\n", " new_tp = current_price - profit * trail_factor \n", "\n", " if new_tp > current_price:\n", " #update tp from open pos\n", " new_tp\n", " print(f\"Trailing +TP for BUY {symbol}: {new_tp} CP: {current_price}\")\n", " if new_tp < current_price:\n", " #update tp from open pos\n", " new_tp\n", " print(f\"Trailing -TP for BUY {symbol}: {new_tp} CP: {current_price}\")\n", "\n", "#open_positions\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Update TP-SL on open positions" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [], "source": [ "def update_trailing_sl_tp(pos, atr, rrr=2.0, atr_mult=1.5, max_retries=2):\n", " \"\"\"\n", " Aktualisiert SL und TP für offene Positionen:\n", " - ATR-basiertes Trailing\n", " - Gewinn-stufenweises Nachziehen\n", " - Dynamische Anpassung mit Validierung\n", " - Fallback-Mechanismus bei RETCODE 1016\n", " \"\"\"\n", "\n", " symbol = pos.symbol\n", " info = mt.symbol_info(symbol)\n", " digits = info.digits\n", " point = info.point\n", " stops_level = info.trade_stops_level * point # Mindestabstand vom Broker\n", "\n", " entry_price = pos.price_open\n", " current_tick = mt.symbol_info_tick(symbol)\n", " bid, ask = current_tick.bid, current_tick.ask\n", " current_price = bid if pos.type == 0 else ask\n", " pos_type = pos.type # 0 = BUY, 1 = SELL\n", "\n", " # Gewinn in ATR berechnen\n", " if pos_type == 0: # LONG\n", " profit_atr = (current_price - entry_price) / atr\n", " base_sl = current_price - atr_mult * atr\n", " new_sl = max(pos.sl or 0, base_sl)\n", "\n", " if profit_atr > 2:\n", " new_sl = max(new_sl, entry_price + 1.5 * atr)\n", " elif profit_atr > 1:\n", " new_sl = max(new_sl, entry_price + 1.0 * atr)\n", " elif profit_atr > 0.5:\n", " new_sl = max(new_sl, entry_price + 0.5 * atr)\n", "\n", " new_tp = entry_price + (entry_price - new_sl) * rrr\n", "\n", " # Validierung BUY\n", " if new_sl >= bid - stops_level:\n", " new_sl = bid - stops_level\n", " if new_tp <= ask + stops_level:\n", " new_tp = ask + stops_level\n", "\n", " else: # SHORT\n", " profit_atr = (entry_price - current_price) / atr\n", " base_sl = current_price + atr_mult * atr\n", " new_sl = min(pos.sl or 999999, base_sl)\n", "\n", " if profit_atr > 2:\n", " new_sl = min(new_sl, entry_price - 1.5 * atr)\n", " elif profit_atr > 1:\n", " new_sl = min(new_sl, entry_price - 1.0 * atr)\n", " elif profit_atr > 0.5:\n", " new_sl = min(new_sl, entry_price - 0.5 * atr)\n", "\n", " new_tp = entry_price - (new_sl - entry_price) * rrr\n", "\n", " # Validierung SELL\n", " if new_sl <= ask + stops_level:\n", " new_sl = ask + stops_level\n", " if new_tp >= bid - stops_level:\n", " new_tp = bid - stops_level\n", "\n", " # Runden auf gültige Stellen\n", " new_sl = round(new_sl, digits)\n", " new_tp = round(new_tp, digits)\n", "\n", " # --- Nur updaten, wenn sich Werte geändert haben ---\n", " if (pos.sl is None or abs(new_sl - pos.sl) > point) or \\\n", " (pos.tp is None or abs(new_tp - pos.tp) > point):\n", "\n", " for attempt in range(max_retries):\n", " request = {\n", " \"action\": mt.TRADE_ACTION_SLTP,\n", " \"symbol\": symbol,\n", " \"sl\": new_sl,\n", " \"tp\": new_tp,\n", " \"position\": pos.ticket\n", " }\n", " result = mt.order_send(request)\n", "\n", " if result.retcode == mt.TRADE_RETCODE_DONE:\n", " print(f\"🔄 Updated {symbol} | SL: {new_sl:.5f} | TP: {new_tp:.5f}\")\n", " break\n", " elif result.retcode == mt.TRADE_RETCODE_INVALID_STOPS:\n", " # Fallback: Stops korrigieren\n", " print(f\"⚠️ RETCODE 1016 (Invalid stops) – Versuch {attempt+1}/{max_retries}\")\n", " adjust = 2 * stops_level # mehr Abstand\n", " if pos_type == 0: # BUY\n", " new_sl = bid - adjust\n", " new_tp = ask + adjust\n", " else: # SELL\n", " new_sl = ask + adjust\n", " new_tp = bid - adjust\n", "\n", " new_sl = round(new_sl, digits)\n", " new_tp = round(new_tp, digits)\n", " continue # retry\n", " else:\n", " print(f\"❌ SL/TP Update Fehler: {result.retcode} ({result.comment})\")\n", " break\n", "\n", " return {\"new_sl\": new_sl, \"new_tp\": new_tp, \"profit_atr\": profit_atr}\n" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [], "source": [ "def manual_update_trailing_sl_tp(atr_mult=1.5, slope_factor=1.5):\n", " # --- Hole die letzten M5-Daten ---\n", " df = get_rates('m5').iloc[-200:]\n", "\n", " # --- ATR Berechnung ---\n", " df[\"hl\"] = df[\"high\"] - df[\"low\"]\n", " df[\"hc\"] = (df[\"high\"] - df[\"close\"].shift()).abs()\n", " df[\"lc\"] = (df[\"low\"] - df[\"close\"].shift()).abs()\n", " df[\"tr\"] = df[[\"hl\",\"hc\",\"lc\"]].max(axis=1)\n", " df[\"atr\"] = df[\"tr\"].rolling(14).mean()\n", " atr = df[\"atr\"].iloc[-1]\n", "\n", " current_price = df[\"close\"].iloc[-1]\n", "\n", " # --- Trendrichtung per Linear Regression ---\n", " def linreg_slope(series):\n", " X = np.arange(len(series)).reshape(-1, 1)\n", " y = series.values.reshape(-1, 1)\n", " model = LinearRegression().fit(X, y)\n", " return model.coef_[0][0]\n", "\n", " slope_long = linreg_slope(df[\"close\"].iloc[-50:]) # 50 Balken (~4h)\n", " slope_short = linreg_slope(df[\"close\"].iloc[-15:]) # 15 Balken (~1h)\n", "\n", " # --- Dynamischer Seitwärtsfilter ---\n", " slope_threshold = slope_factor * atr / df[\"close\"].iloc[-1]\n", "\n", " # --- Dynamische RRR-Berechnung ---\n", " atr_norm = atr / current_price # relative Volatilität\n", " slope_strength = abs(slope_short) # Trendstärke aus Regression\n", "\n", " rrr_base = 1.2\n", " rrr_from_vol = atr_norm * 1500 # skaliert ATR-Einfluss\n", " rrr_from_slope = slope_strength / slope_threshold # Slope-Einfluss\n", "\n", " rrr = rrr_base + rrr_from_vol + rrr_from_slope\n", " rrr = max(1.2, min(rrr, 3.0)) # Begrenzung\n", "\n", "\n", " open_positions = mt.positions_get(symbol=symbol)\n", " for pos in open_positions:\n", " atr_value = df[\"atr\"].iloc[-1]\n", " update_trailing_sl_tp(pos, atr=atr_value, rrr=rrr, atr_mult=atr_mult)\n", " " ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "🔄 Updated XAUUSD | SL: 3569.71000 | TP: 3580.40000\n" ] } ], "source": [ "manual_update_trailing_sl_tp()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Get M5 Trade Signals" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [], "source": [ "def get_m5_trade_signals(symbol=symbol, atr_mult=1.5, base_rrr=2.0, atr_min=0.0005, slope_factor=1.5, execute=False):\n", " \"\"\"\n", " Analyse von M5-Signalen mit ATR/Trend/Seitwärtsfilter\n", " - execute=False -> nur Analyse\n", " - execute=True -> führt Orders aus\n", " \"\"\"\n", "\n", " global trend_dict, volume_dict\n", "\n", " df = get_rates('m5').iloc[-200:]\n", "\n", " # --- ATR ---\n", " df[\"hl\"] = df[\"high\"] - df[\"low\"]\n", " df[\"hc\"] = (df[\"high\"] - df[\"close\"].shift()).abs()\n", " df[\"lc\"] = (df[\"low\"] - df[\"close\"].shift()).abs()\n", " df[\"tr\"] = df[[\"hl\",\"hc\",\"lc\"]].max(axis=1)\n", " df[\"atr\"] = df[\"tr\"].rolling(14).mean()\n", " atr = df[\"atr\"].iloc[-1]\n", "\n", " if atr < atr_min:\n", " return {\"signal\": 0, \"reason\": \"ATR too low → sideways\"}\n", "\n", " # --- Trend ---\n", " def linreg_slope(series):\n", " X = np.arange(len(series)).reshape(-1, 1)\n", " y = series.values.reshape(-1, 1)\n", " model = LinearRegression().fit(X, y)\n", " return model.coef_[0][0]\n", "\n", " slope_long = linreg_slope(df[\"close\"].iloc[-50:])\n", " slope_short = linreg_slope(df[\"close\"].iloc[-15:])\n", " slope_threshold = slope_factor * atr / df[\"close\"].iloc[-1]\n", "\n", " if abs(slope_long) < slope_threshold and abs(slope_short) < slope_threshold:\n", " return {\"signal\": 0, \"reason\": \"Trend flat → sideways\"}\n", "\n", " trend_standard = \"uptrend\" if slope_long > 0 else \"downtrend\"\n", " trend_fast = \"uptrend\" if slope_short > 0 else \"downtrend\"\n", "\n", " current_price = df[\"close\"].iloc[-1]\n", "\n", " # --- RRR ---\n", " atr_norm = atr / current_price\n", " slope_strength = abs(slope_short)\n", " rrr_base = 1.2\n", " rrr_from_vol = atr_norm * 1500\n", " rrr_from_slope = slope_strength / slope_threshold\n", " rrr = max(1.2, min(rrr_base + rrr_from_vol + rrr_from_slope, 3.0))\n", "\n", " # --- Signal ---\n", " signal, stop_loss, takeprofit = 0, None, None\n", " if trend_standard == \"uptrend\" and trend_fast == \"uptrend\":\n", " signal = 1\n", " stop_loss = current_price - atr_mult * atr\n", " takeprofit = current_price + atr_mult * atr * rrr\n", "\n", " if execute:\n", " print(f\"BUY {symbol} @ {current_price} | TP: {takeprofit} | SL: {stop_loss}\")\n", " market_order(symbol, volume_dict[symbol], \"buy\", stoploss=stop_loss, take_profit=takeprofit)\n", "\n", " elif trend_standard == \"downtrend\" and trend_fast == \"downtrend\":\n", " signal = -1\n", " stop_loss = current_price + atr_mult * atr\n", " takeprofit = current_price - atr_mult * atr * rrr\n", "\n", " if execute:\n", " print(f\"SELL {symbol} @ {current_price} | TP: {takeprofit} | SL: {stop_loss}\")\n", " market_order(symbol, volume_dict[symbol], \"sell\", stoploss=stop_loss, take_profit=takeprofit)\n", "\n", " # --- speichern ---\n", " trend_dict['m5'] = {\"standard\": trend_standard, \"fast\": trend_fast, \"signal\": signal}\n", "\n", " return {\n", " \"signal\": signal,\n", " \"price\": current_price,\n", " \"stop_loss\": stop_loss,\n", " \"take_profit\": takeprofit,\n", " \"Risk Reward\": rrr,\n", " \"trends\": trend_dict['m5'],\n", " \"atr\": atr,\n", " \"slope_long\": slope_long,\n", " \"slope_short\": slope_short\n", " }" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [], "source": [ "def execute_m5_trade(symbol=symbol, atr_mult=1.5, base_rrr=2.0):\n", " \"\"\"\n", " Führt einen Trade auf M5 nur aus, wenn das Top-Down-Setup ein positives Signal liefert.\n", " Nutzt adaptive ATR, dynamisches RRR und SL/TP.\n", " \"\"\"\n", "\n", " global trend_dict, volume_dict, pause_trading\n", "\n", " # --- Top-Down-Signal prüfen ---\n", " top_down = get_top_down_signal(symbol)\n", "\n", " if pause_trading == 1:\n", " print(\"⚠️ Trading pausiert. Keine Trades ausgeführt.\")\n", " return None\n", "\n", " if not top_down[\"setup_ready\"] or top_down[\"entry_signal\"] == 0:\n", " print(\"Kein Top-Down-Setup vorhanden. Kein Trade.\")\n", " return None\n", "\n", " # --- M5-Signal berechnen (nur Signal, keine automatische Order) ---\n", " m5_signal_info = get_m5_trade_signals(symbol=symbol, atr_mult=atr_mult, base_rrr=base_rrr)\n", "\n", " if m5_signal_info[\"signal\"] == 0:\n", " print(\"M5 Signal neutral. Kein Trade.\")\n", " return None\n", "\n", " # --- Trade ausführen ---\n", " current_price = m5_signal_info[\"price\"]\n", " stop_loss = m5_signal_info[\"stop_loss\"]\n", " take_profit = m5_signal_info[\"take_profit\"]\n", "\n", " if m5_signal_info[\"signal\"] == 1:\n", " # Long\n", " print(f\"✅ BUY {symbol} @ {current_price} | TP: {take_profit} | SL: {stop_loss}\")\n", " market_order(symbol, volume_dict[symbol], \"buy\", stoploss=stop_loss, take_profit=take_profit)\n", " elif m5_signal_info[\"signal\"] == -1:\n", " # Short\n", " print(f\"✅ SELL {symbol} @ {current_price} | TP: {take_profit} | SL: {stop_loss}\")\n", " market_order(symbol, volume_dict[symbol], \"sell\", stoploss=stop_loss, take_profit=take_profit)\n", "\n", " # --- Offene Trades aktualisieren (Trailing SL/TP) ---\n", " open_positions = mt.positions_get(symbol=symbol)\n", " for pos in open_positions:\n", " update_trailing_sl_tp(pos, atr=m5_signal_info[\"atr\"], rrr=m5_signal_info[\"Risk Reward\"], atr_mult=atr_mult)\n", "\n", " return {\n", " \"top_down\": top_down,\n", " \"m5_signal\": m5_signal_info\n", " }\n" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Kein Top-Down-Setup vorhanden. Kein Trade.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "✅ BUY XAUUSD @ 3571.06 | TP: 3578.2085714285713 | SL: 3568.677142857143\n", "✅ BUY XAUUSD @ 3571.81 | TP: 3579.604642857143 | SL: 3569.2117857142857\n", "🔄 Updated XAUUSD | SL: 3570.03000 | TP: 3579.44000\n", "🔄 Updated XAUUSD | SL: 3570.58000 | TP: 3577.77000\n", "🔄 Updated XAUUSD | SL: 3573.16000 | TP: 3573.77000\n", "✅ BUY XAUUSD @ 3573.65 | TP: 3581.7596428571433 | SL: 3570.946785714286\n", "🔄 Updated XAUUSD | SL: 3570.95000 | TP: 3582.31000\n", "🔄 Updated XAUUSD | SL: 3571.07000 | TP: 3581.95000\n", "✅ BUY XAUUSD @ 3573.67 | TP: 3581.6832142857143 | SL: 3570.9989285714287\n", "🔄 Updated XAUUSD | SL: 3571.77000 | TP: 3579.86000\n", "🔄 Updated XAUUSD | SL: 3571.77000 | TP: 3579.85000\n", "✅ BUY XAUUSD @ 3574.21 | TP: 3582.0914285714284 | SL: 3571.5828571428574\n", "🔄 Updated XAUUSD | SL: 3574.66000 | TP: 3575.40000\n", "🔄 Updated XAUUSD | SL: 3574.67000 | TP: 3575.60000\n", "🔄 Updated XAUUSD | SL: 3574.67000 | TP: 3575.39000\n", "🔄 Updated XAUUSD | SL: 3574.67000 | TP: 3575.63000\n", "🔄 Updated XAUUSD | SL: 3574.67000 | TP: 3575.68000\n", "✅ BUY XAUUSD @ 3575.28 | TP: 3582.5957142857146 | SL: 3572.841428571429\n", "✅ BUY XAUUSD @ 3575.47 | TP: 3583.2614285714285 | SL: 3572.872857142857\n", "🔄 Updated XAUUSD | SL: 3572.88000 | TP: 3584.11000\n", "Kein Top-Down-Setup vorhanden. Kein Trade.\n", "✅ BUY XAUUSD @ 3575.29 | TP: 3583.4285714285716 | SL: 3572.577142857143\n", "🔄 Updated XAUUSD | SL: 3573.59000 | TP: 3581.99000\n", "🔄 Updated XAUUSD | SL: 3573.90000 | TP: 3581.07000\n", "🔄 Updated XAUUSD | SL: 3573.90000 | TP: 3581.06000\n", "🔄 Updated XAUUSD | SL: 3576.56000 | TP: 3577.79000\n", "✅ BUY XAUUSD @ 3577.4 | TP: 3584.628928571429 | SL: 3574.990357142857\n", "⚠️ RETCODE 1016 (Invalid stops) – Versuch 1/2\n", "🔄 Updated XAUUSD | SL: 3577.00000 | TP: 3578.00000\n", "✅ BUY XAUUSD @ 3578.23 | TP: 3586.0310714285715 | SL: 3575.6296428571427\n", "🔄 Updated XAUUSD | SL: 3575.63000 | TP: 3586.63000\n", "Kein Top-Down-Setup vorhanden. Kein Trade.\n", "Kein Top-Down-Setup vorhanden. Kein Trade.\n", "Kein Top-Down-Setup vorhanden. Kein Trade.\n", "Kein Top-Down-Setup vorhanden. Kein Trade.\n", "M5 Signal neutral. Kein Trade.\n", "M5 Signal neutral. Kein Trade.\n", "M5 Signal neutral. Kein Trade.\n", "M5 Signal neutral. Kein Trade.\n", "Kein Top-Down-Setup vorhanden. Kein Trade.\n", "Kein Top-Down-Setup vorhanden. Kein Trade.\n", "M5 Signal neutral. Kein Trade.\n", "Kein Top-Down-Setup vorhanden. Kein Trade.\n", "Kein Top-Down-Setup vorhanden. Kein Trade.\n", "Kein Top-Down-Setup vorhanden. Kein Trade.\n", "M5 Signal neutral. Kein Trade.\n", "Kein Top-Down-Setup vorhanden. Kein Trade.\n", "Kein Top-Down-Setup vorhanden. Kein Trade.\n", "M5 Signal neutral. Kein Trade.\n", "Kein Top-Down-Setup vorhanden. Kein Trade.\n", "M5 Signal neutral. Kein Trade.\n", "✅ SELL XAUUSD @ 3563.72 | TP: 3551.165 | SL: 3567.9049999999997\n", "Kein Top-Down-Setup vorhanden. Kein Trade.\n", "✅ SELL XAUUSD @ 3563.47 | TP: 3551.0532142857146 | SL: 3567.6089285714284\n", "✅ SELL XAUUSD @ 3563.92 | TP: 3552.6603571428577 | SL: 3567.673214285714\n", "✅ SELL XAUUSD @ 3565.45 | TP: 3553.589285714286 | SL: 3569.403571428571\n", "Kein Top-Down-Setup vorhanden. Kein Trade.\n", "Kein Top-Down-Setup vorhanden. Kein Trade.\n", "Kein Top-Down-Setup vorhanden. Kein Trade.\n", "Kein Top-Down-Setup vorhanden. Kein Trade.\n", "✅ SELL XAUUSD @ 3562.22 | TP: 3553.2489285714287 | SL: 3565.210357142857\n", "Kein Top-Down-Setup vorhanden. Kein Trade.\n", "Kein Top-Down-Setup vorhanden. Kein Trade.\n", "Kein Top-Down-Setup vorhanden. Kein Trade.\n", "Kein Top-Down-Setup vorhanden. Kein Trade.\n" ] } ], "source": [ "execute_m5_trade()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Job-Scheduler\n", "\n", "[Doku Appscheduler Cronjob](https://apscheduler.readthedocs.io/en/3.x/modules/triggers/cron.html#id0)" ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [], "source": [ "from apscheduler.schedulers.background import BackgroundScheduler\n", "import time\n", "\n", "\n", "scheduler = BackgroundScheduler()\n", "#scheduler.add_job(main, 'date', run_date='2025-03-07 14:29:50')\n", "\n", "#scheduler.add_job(decide_order, 'interval', minutes=1) #intervall\n", "#scheduler.add_job(set_symbol, 'interval', minutes=30)\n", "#scheduler.add_job(set_trend, 'interval', minutes=1)\n", "\n", "#scheduler.add_job(decide_order, 'interval', minutes=1)\n", "#scheduler.add_job(decide_order, 'cron', year=\"*\", month=\"*\", day_of_week=\"mon, tue, wed, thu, fri\", hour='0-23', minute='*') #cron\n", "#scheduler.add_job(get_buy_sell_signal, 'cron', year=\"*\", month=\"*\", day_of_week=\"mon, tue, wed, thu, fri\", hour='0-23', minute='*/5') #cron\n", "#scheduler.add_job(get_m5_trade_signals, 'cron', year=\"*\", month=\"*\", day_of_week=\"mon, tue, wed, thu, fri\", hour='0-23', minute='*/5') #cron\n", "scheduler.add_job(execute_m5_trade, 'cron', year=\"*\", month=\"*\", day_of_week=\"mon, tue, wed, thu, fri\", hour='0-23', minute='*/5') #cron\n", "scheduler.add_job(manual_update_trailing_sl_tp, 'cron', year=\"*\", month=\"*\", day_of_week=\"mon, tue, wed, thu, fri\", hour='0-23', minute='*') #cron\n", "\n", "#scheduler.add_job(export_marketview, 'cron', year=\"*\", month='*', day_of_week='mon, tue, wed; thu, fri', hour='8-22', minute=00)\n", "\n", "#scheduler.add_job(pause_trading, 'cron', year=\"*\", month=\"*\", day_of_week=\"mon, tue, wed, thu, fri\", hour=22, minute=00) #cron\n", "scheduler.start()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Get Jobs" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[,\n", " ]" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "scheduler.get_jobs()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Remove all Jobs" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "scheduler.remove_all_jobs()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Shutdown AppScheduler" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "scheduler.shutdown()" ] } ], "metadata": { "kernelspec": { "display_name": "base", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.5" } }, "nbformat": 4, "nbformat_minor": 2 }