diff --git a/AutoTrading_MT5_with_Logging.ipynb b/AutoTrading_MT5_with_Logging.ipynb
new file mode 100644
index 0000000..b34bb94
--- /dev/null
+++ b/AutoTrading_MT5_with_Logging.ipynb
@@ -0,0 +1,771 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "4cb5824d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# 📦 Imports\n",
+ "import MetaTrader5 as mt\n",
+ "import pandas as pd\n",
+ "import sqlite3 as db\n",
+ "from datetime import datetime\n",
+ "import time\n",
+ "from scipy.signal import savgol_filter\n",
+ "import pandas_ta as ta\n",
+ "import keyring as kr"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "1279652c",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# 📊 Verbindung zu SQLite\n",
+ "def init_db(db_name=\"trading_log.db\"):\n",
+ " conn = db.connect(db_name)\n",
+ " c = conn.cursor()\n",
+ " c.execute(\"\"\"\n",
+ " CREATE TABLE IF NOT EXISTS trade_log (\n",
+ " timestamp TEXT,\n",
+ " symbol TEXT,\n",
+ " order_type TEXT,\n",
+ " price REAL,\n",
+ " sl REAL,\n",
+ " tp REAL,\n",
+ " volume REAL,\n",
+ " signal INTEGER,\n",
+ " comment TEXT\n",
+ " )\n",
+ " \"\"\")\n",
+ " conn.commit()\n",
+ " return conn"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "fc1eb959",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# 🔐 MT5 Login einmalig initialisieren\n",
+ "mt.initialize()\n",
+ "login = 10800246\n",
+ "server = \"VantageInternational-Demo\"\n",
+ "password = kr.get_password(server, str(login))\n",
+ "mt.login(login, password, server)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "840d41c6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# 📥 MT5 Daten abrufen\n",
+ "def get_mt5_data(symbol=\"XAUUSD\", timeframe=mt.TIMEFRAME_M5, 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": 9,
+ "id": "48445ef4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = get_mt5_data()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "964f927f",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# 🤖 Signale erzeugen\n",
+ "def generate_signal(df):\n",
+ " df[\"ema10\"] = df[\"close\"].ewm(span=10).mean()\n",
+ " df[\"ema30\"] = df[\"close\"].ewm(span=30).mean()\n",
+ " df[\"rsi\"] = ta.rsi(df[\"close\"], length=14)\n",
+ " df[\"trend\"] = savgol_filter(df[\"close\"], 15, 3)\n",
+ " df[\"signal\"] = 0\n",
+ "\n",
+ " for i in range(1, len(df)):\n",
+ " if (\n",
+ " df[\"ema10\"].iloc[i] > df[\"ema30\"].iloc[i]\n",
+ " and df[\"ema10\"].iloc[i - 1] <= df[\"ema30\"].iloc[i - 1]\n",
+ " and df[\"rsi\"].iloc[i] < 70\n",
+ " and df[\"trend\"].iloc[i] > df[\"trend\"].iloc[i - 1]\n",
+ " ):\n",
+ " df.at[i, \"signal\"] = 1\n",
+ " elif (\n",
+ " df[\"ema10\"].iloc[i] < df[\"ema30\"].iloc[i]\n",
+ " and df[\"ema10\"].iloc[i - 1] >= df[\"ema30\"].iloc[i - 1]\n",
+ " and df[\"rsi\"].iloc[i] > 30\n",
+ " and df[\"trend\"].iloc[i] < df[\"trend\"].iloc[i - 1]\n",
+ " ):\n",
+ " df.at[i, \"signal\"] = -1\n",
+ " return df"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "id": "7494a5da",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " time | \n",
+ " open | \n",
+ " high | \n",
+ " low | \n",
+ " close | \n",
+ " tick_volume | \n",
+ " spread | \n",
+ " real_volume | \n",
+ " ema10 | \n",
+ " ema30 | \n",
+ " rsi | \n",
+ " trend | \n",
+ " signal | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " 2025-07-17 04:30:00 | \n",
+ " 3340.74 | \n",
+ " 3341.46 | \n",
+ " 3337.21 | \n",
+ " 3338.04 | \n",
+ " 1293 | \n",
+ " 18 | \n",
+ " 0 | \n",
+ " 3338.040000 | \n",
+ " 3338.040000 | \n",
+ " NaN | \n",
+ " 3338.208386 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " 2025-07-17 04:35:00 | \n",
+ " 3338.03 | \n",
+ " 3341.03 | \n",
+ " 3337.72 | \n",
+ " 3341.03 | \n",
+ " 964 | \n",
+ " 18 | \n",
+ " 0 | \n",
+ " 3339.684500 | \n",
+ " 3339.584833 | \n",
+ " NaN | \n",
+ " 3340.377874 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 2025-07-17 04:40:00 | \n",
+ " 3341.03 | \n",
+ " 3341.48 | \n",
+ " 3339.96 | \n",
+ " 3341.26 | \n",
+ " 944 | \n",
+ " 18 | \n",
+ " 0 | \n",
+ " 3340.317841 | \n",
+ " 3340.180848 | \n",
+ " NaN | \n",
+ " 3341.873882 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 2025-07-17 04:45:00 | \n",
+ " 3341.27 | \n",
+ " 3343.45 | \n",
+ " 3341.27 | \n",
+ " 3342.47 | \n",
+ " 1099 | \n",
+ " 18 | \n",
+ " 0 | \n",
+ " 3341.026881 | \n",
+ " 3340.811593 | \n",
+ " NaN | \n",
+ " 3342.785860 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " 2025-07-17 04:50:00 | \n",
+ " 3342.47 | \n",
+ " 3343.61 | \n",
+ " 3342.20 | \n",
+ " 3342.84 | \n",
+ " 1070 | \n",
+ " 18 | \n",
+ " 0 | \n",
+ " 3341.547378 | \n",
+ " 3341.273104 | \n",
+ " NaN | \n",
+ " 3343.203260 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " | 495 | \n",
+ " 2025-07-18 22:45:00 | \n",
+ " 3349.29 | \n",
+ " 3349.71 | \n",
+ " 3348.47 | \n",
+ " 3348.78 | \n",
+ " 928 | \n",
+ " 19 | \n",
+ " 0 | \n",
+ " 3350.024962 | \n",
+ " 3351.232735 | \n",
+ " 34.935115 | \n",
+ " 3348.405247 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 496 | \n",
+ " 2025-07-18 22:50:00 | \n",
+ " 3348.79 | \n",
+ " 3348.80 | \n",
+ " 3347.62 | \n",
+ " 3348.15 | \n",
+ " 859 | \n",
+ " 19 | \n",
+ " 0 | \n",
+ " 3349.684060 | \n",
+ " 3351.033849 | \n",
+ " 32.290909 | \n",
+ " 3348.186635 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 497 | \n",
+ " 2025-07-18 22:55:00 | \n",
+ " 3348.16 | \n",
+ " 3348.53 | \n",
+ " 3347.65 | \n",
+ " 3348.25 | \n",
+ " 1028 | \n",
+ " 19 | \n",
+ " 0 | \n",
+ " 3349.423322 | \n",
+ " 3350.854245 | \n",
+ " 33.155760 | \n",
+ " 3348.153324 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 498 | \n",
+ " 2025-07-18 23:00:00 | \n",
+ " 3348.24 | \n",
+ " 3348.88 | \n",
+ " 3347.72 | \n",
+ " 3348.06 | \n",
+ " 599 | \n",
+ " 19 | \n",
+ " 0 | \n",
+ " 3349.175445 | \n",
+ " 3350.673972 | \n",
+ " 32.311285 | \n",
+ " 3348.346744 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 499 | \n",
+ " 2025-07-18 23:05:00 | \n",
+ " 3348.06 | \n",
+ " 3349.25 | \n",
+ " 3347.92 | \n",
+ " 3348.88 | \n",
+ " 450 | \n",
+ " 19 | \n",
+ " 0 | \n",
+ " 3349.121728 | \n",
+ " 3350.558231 | \n",
+ " 39.476021 | \n",
+ " 3348.808327 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
500 rows × 13 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " time open high low close tick_volume \\\n",
+ "0 2025-07-17 04:30:00 3340.74 3341.46 3337.21 3338.04 1293 \n",
+ "1 2025-07-17 04:35:00 3338.03 3341.03 3337.72 3341.03 964 \n",
+ "2 2025-07-17 04:40:00 3341.03 3341.48 3339.96 3341.26 944 \n",
+ "3 2025-07-17 04:45:00 3341.27 3343.45 3341.27 3342.47 1099 \n",
+ "4 2025-07-17 04:50:00 3342.47 3343.61 3342.20 3342.84 1070 \n",
+ ".. ... ... ... ... ... ... \n",
+ "495 2025-07-18 22:45:00 3349.29 3349.71 3348.47 3348.78 928 \n",
+ "496 2025-07-18 22:50:00 3348.79 3348.80 3347.62 3348.15 859 \n",
+ "497 2025-07-18 22:55:00 3348.16 3348.53 3347.65 3348.25 1028 \n",
+ "498 2025-07-18 23:00:00 3348.24 3348.88 3347.72 3348.06 599 \n",
+ "499 2025-07-18 23:05:00 3348.06 3349.25 3347.92 3348.88 450 \n",
+ "\n",
+ " spread real_volume ema10 ema30 rsi trend \\\n",
+ "0 18 0 3338.040000 3338.040000 NaN 3338.208386 \n",
+ "1 18 0 3339.684500 3339.584833 NaN 3340.377874 \n",
+ "2 18 0 3340.317841 3340.180848 NaN 3341.873882 \n",
+ "3 18 0 3341.026881 3340.811593 NaN 3342.785860 \n",
+ "4 18 0 3341.547378 3341.273104 NaN 3343.203260 \n",
+ ".. ... ... ... ... ... ... \n",
+ "495 19 0 3350.024962 3351.232735 34.935115 3348.405247 \n",
+ "496 19 0 3349.684060 3351.033849 32.290909 3348.186635 \n",
+ "497 19 0 3349.423322 3350.854245 33.155760 3348.153324 \n",
+ "498 19 0 3349.175445 3350.673972 32.311285 3348.346744 \n",
+ "499 19 0 3349.121728 3350.558231 39.476021 3348.808327 \n",
+ "\n",
+ " 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 13 columns]"
+ ]
+ },
+ "execution_count": 12,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "generate_signal(df)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "id": "0a8abc07",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0.01"
+ ]
+ },
+ "execution_count": 14,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "mt.symbol_info('XAUUSD').point"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "64757821",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# 📤 Order senden\n",
+ "def send_market_order(symbol, volume, order_type, signal, conn, sl_pips=20, tp_pips=40, magic=1001):\n",
+ " tick = mt.symbol_info_tick(symbol)\n",
+ " price = tick.ask if order_type == mt.ORDER_TYPE_BUY else tick.bid\n",
+ " point = mt.symbol_info(symbol).point\n",
+ "\n",
+ " sl = price - sl_pips * point if order_type == mt.ORDER_TYPE_BUY else price + sl_pips * point\n",
+ " tp = price + tp_pips * point if order_type == mt.ORDER_TYPE_BUY else price - tp_pips * point\n",
+ "\n",
+ " request = {\n",
+ " \"action\": mt.TRADE_ACTION_DEAL,\n",
+ " \"symbol\": symbol,\n",
+ " \"volume\": volume,\n",
+ " \"type\": order_type,\n",
+ " \"price\": price,\n",
+ " \"sl\": round(sl, 5),\n",
+ " \"tp\": round(tp, 5),\n",
+ " \"deviation\": 20,\n",
+ " \"magic\": magic,\n",
+ " \"comment\": \"AutoSignalBot\",\n",
+ " \"type_time\": mt.ORDER_TIME_GTC,\n",
+ " \"type_filling\": mt.ORDER_FILLING_IOC,\n",
+ " }\n",
+ "\n",
+ " result = mt.order_send(request)\n",
+ " print(f\"[TRADE] {symbol} - {'BUY' if order_type==0 else 'SELL'} @ {price} | SL: {sl} | TP: {tp}\")\n",
+ "\n",
+ " # Logging in DB\n",
+ " c = conn.cursor()\n",
+ " c.execute(\"\"\"\n",
+ " INSERT INTO trade_log (timestamp, symbol, order_type, price, sl, tp, volume, signal, comment)\n",
+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\n",
+ " \"\"\", (datetime.now(), symbol, \"BUY\" if order_type==0 else \"SELL\", price, sl, tp, volume, signal, \"AutoSignalBot\"))\n",
+ " conn.commit()\n",
+ " \n",
+ " return result"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "id": "3bc5f11e",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# 🔁 Hauptfunktion\n",
+ "def run_live_trading(symbol=\"XAUUSD\", interval=300, volume=0.1, db_name=\"trading_log.db\"):\n",
+ " conn = init_db(db_name)\n",
+ " last_signal = 0\n",
+ "\n",
+ " print(f\"✅ Starte Auto-Trading für {symbol} – Intervall {interval}s\")\n",
+ " while True:\n",
+ " df = get_mt5_data(symbol)\n",
+ " df = generate_signal(df)\n",
+ " signal = df[\"signal\"].iloc[-1]\n",
+ "\n",
+ " if signal != 0 and signal != last_signal:\n",
+ " order_type = mt.ORDER_TYPE_BUY if signal == 1 else mt.ORDER_TYPE_SELL\n",
+ " send_market_order(symbol, volume, order_type, signal, conn)\n",
+ " last_signal = signal\n",
+ " else:\n",
+ " print(f\"[{datetime.now()}] Kein neues Signal ({signal})\")\n",
+ "\n",
+ " time.sleep(interval)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 22,
+ "id": "71acdb0d",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "✅ Starte Auto-Trading für XAUUSD – Intervall 300s\n",
+ "[2025-07-18 12:11:30.004688] Kein neues Signal (0)\n",
+ "[2025-07-18 12:16:30.083605] Kein neues Signal (0)\n",
+ "[2025-07-18 12:21:30.121793] Kein neues Signal (0)\n",
+ "[2025-07-18 12:26:30.174396] Kein neues Signal (0)\n",
+ "[2025-07-18 12:31:30.216996] Kein neues Signal (0)\n",
+ "[2025-07-18 12:36:30.258849] Kein neues Signal (0)\n",
+ "[2025-07-18 12:41:30.313072] Kein neues Signal (0)\n",
+ "[2025-07-18 12:46:30.356620] Kein neues Signal (0)\n",
+ "[2025-07-18 12:51:30.396600] Kein neues Signal (0)\n",
+ "[2025-07-18 12:56:30.442114] Kein neues Signal (0)\n",
+ "[2025-07-18 13:01:30.481155] Kein neues Signal (0)\n",
+ "[2025-07-18 13:06:30.530619] Kein neues Signal (0)\n",
+ "[2025-07-18 13:11:30.566248] Kein neues Signal (0)\n",
+ "[2025-07-18 13:16:30.606701] Kein neues Signal (0)\n",
+ "[2025-07-18 13:21:30.645462] Kein neues Signal (0)\n",
+ "[2025-07-18 13:26:30.686722] Kein neues Signal (0)\n",
+ "[2025-07-18 13:31:31.130100] Kein neues Signal (0)\n",
+ "[2025-07-18 13:36:31.193825] Kein neues Signal (0)\n",
+ "[2025-07-18 13:41:31.381330] Kein neues Signal (0)\n",
+ "[2025-07-18 13:46:31.434187] Kein neues Signal (0)\n",
+ "[2025-07-18 13:51:31.471695] Kein neues Signal (0)\n",
+ "[2025-07-18 13:56:31.507322] Kein neues Signal (0)\n",
+ "[2025-07-18 14:01:31.550436] Kein neues Signal (0)\n",
+ "[2025-07-18 14:06:31.587884] Kein neues Signal (0)\n",
+ "[2025-07-18 14:11:31.665002] Kein neues Signal (0)\n",
+ "[2025-07-18 14:16:31.704012] Kein neues Signal (0)\n",
+ "[2025-07-18 14:21:31.745292] Kein neues Signal (0)\n",
+ "[2025-07-18 14:26:31.783905] Kein neues Signal (0)\n",
+ "[2025-07-18 14:31:31.822325] Kein neues Signal (0)\n",
+ "[2025-07-18 14:36:31.873271] Kein neues Signal (0)\n",
+ "[2025-07-18 14:41:31.914303] Kein neues Signal (0)\n",
+ "[2025-07-18 14:46:31.951585] Kein neues Signal (0)\n",
+ "[2025-07-18 14:51:32.005271] Kein neues Signal (0)\n",
+ "[2025-07-18 14:56:32.046384] Kein neues Signal (0)\n",
+ "[2025-07-18 15:01:32.083259] Kein neues Signal (0)\n",
+ "[2025-07-18 15:06:32.132835] Kein neues Signal (0)\n",
+ "[2025-07-18 15:11:32.176714] Kein neues Signal (0)\n",
+ "[2025-07-18 15:16:32.221857] Kein neues Signal (0)\n",
+ "[2025-07-18 15:21:32.269876] Kein neues Signal (0)\n",
+ "[2025-07-18 15:26:32.313363] Kein neues Signal (0)\n",
+ "[2025-07-18 15:31:32.356954] Kein neues Signal (0)\n",
+ "[2025-07-18 15:36:32.403653] Kein neues Signal (0)\n",
+ "[2025-07-18 15:41:32.449777] Kein neues Signal (0)\n",
+ "[2025-07-18 15:46:32.489053] Kein neues Signal (0)\n",
+ "[TRADE] XAUUSD - SELL @ 3354.56 | SL: 3354.7599999999998 | TP: 3354.16\n",
+ "[2025-07-18 15:56:32.609729] Kein neues Signal (0)\n",
+ "[2025-07-18 16:01:32.650996] Kein neues Signal (0)\n",
+ "[TRADE] XAUUSD - BUY @ 3358.95 | SL: 3358.75 | TP: 3359.35\n",
+ "[2025-07-18 16:11:32.744972] Kein neues Signal (0)\n",
+ "[2025-07-18 16:16:32.791366] Kein neues Signal (0)\n",
+ "[2025-07-18 16:21:32.829930] Kein neues Signal (0)\n",
+ "[2025-07-18 16:26:32.871934] Kein neues Signal (0)\n",
+ "[2025-07-18 16:31:32.912571] Kein neues Signal (0)\n",
+ "[2025-07-18 16:36:32.954745] Kein neues Signal (0)\n",
+ "[2025-07-18 16:41:32.994281] Kein neues Signal (0)\n",
+ "[2025-07-18 16:46:33.048113] Kein neues Signal (0)\n",
+ "[2025-07-18 16:51:33.086281] Kein neues Signal (0)\n",
+ "[2025-07-18 16:56:33.127117] Kein neues Signal (0)\n",
+ "[2025-07-18 17:01:33.177813] Kein neues Signal (0)\n",
+ "[2025-07-18 17:06:33.219713] Kein neues Signal (0)\n",
+ "[2025-07-18 17:11:33.260138] Kein neues Signal (0)\n",
+ "[2025-07-18 17:16:33.302870] Kein neues Signal (0)\n",
+ "[2025-07-18 17:21:33.346259] Kein neues Signal (0)\n",
+ "[2025-07-18 17:26:33.390947] Kein neues Signal (0)\n",
+ "[2025-07-18 17:31:33.434736] Kein neues Signal (0)\n",
+ "[2025-07-18 17:36:33.476901] Kein neues Signal (0)\n",
+ "[2025-07-18 17:41:33.520435] Kein neues Signal (0)\n",
+ "[2025-07-18 17:46:33.575426] Kein neues Signal (0)\n",
+ "[2025-07-18 17:51:33.622573] Kein neues Signal (0)\n",
+ "[2025-07-18 17:56:33.662664] Kein neues Signal (0)\n",
+ "[2025-07-18 18:01:33.703019] Kein neues Signal (0)\n",
+ "[2025-07-18 18:06:33.748220] Kein neues Signal (0)\n",
+ "[2025-07-18 18:11:33.788812] Kein neues Signal (0)\n",
+ "[2025-07-18 18:16:33.827200] Kein neues Signal (0)\n",
+ "[2025-07-18 18:21:33.880825] Kein neues Signal (0)\n",
+ "[2025-07-18 18:26:33.931042] Kein neues Signal (0)\n",
+ "[2025-07-18 18:31:33.982017] Kein neues Signal (0)\n",
+ "[2025-07-18 18:36:34.021865] Kein neues Signal (1)\n",
+ "[2025-07-18 18:41:34.059505] Kein neues Signal (0)\n",
+ "[2025-07-18 18:46:34.100395] Kein neues Signal (0)\n",
+ "[2025-07-18 18:51:34.148794] Kein neues Signal (0)\n",
+ "[2025-07-18 18:56:34.186791] Kein neues Signal (0)\n",
+ "[2025-07-18 19:01:34.227630] Kein neues Signal (0)\n",
+ "[2025-07-18 19:06:34.272331] Kein neues Signal (0)\n",
+ "[2025-07-18 19:11:34.309122] Kein neues Signal (0)\n",
+ "[2025-07-18 19:16:34.350483] Kein neues Signal (0)\n",
+ "[2025-07-18 19:21:34.391638] Kein neues Signal (0)\n",
+ "[2025-07-18 19:26:34.430235] Kein neues Signal (0)\n",
+ "[2025-07-18 19:31:34.476827] Kein neues Signal (0)\n",
+ "[2025-07-18 19:36:34.516804] Kein neues Signal (0)\n",
+ "[2025-07-18 19:41:34.551478] Kein neues Signal (0)\n",
+ "[2025-07-18 19:46:34.600704] Kein neues Signal (0)\n",
+ "[2025-07-18 19:51:34.657098] Kein neues Signal (0)\n",
+ "[2025-07-18 19:56:34.694871] Kein neues Signal (0)\n",
+ "[2025-07-18 20:01:34.750662] Kein neues Signal (0)\n",
+ "[2025-07-18 20:06:34.786445] Kein neues Signal (0)\n",
+ "[2025-07-18 20:11:34.941510] Kein neues Signal (0)\n",
+ "[2025-07-18 20:16:34.997686] Kein neues Signal (0)\n",
+ "[2025-07-18 20:21:35.041835] Kein neues Signal (0)\n",
+ "[2025-07-18 20:26:35.082677] Kein neues Signal (0)\n",
+ "[2025-07-18 20:31:35.135303] Kein neues Signal (0)\n",
+ "[2025-07-18 20:36:35.174403] Kein neues Signal (0)\n",
+ "[2025-07-18 20:41:35.211876] Kein neues Signal (0)\n",
+ "[2025-07-18 20:46:35.254113] Kein neues Signal (0)\n",
+ "[2025-07-18 20:51:35.297650] Kein neues Signal (0)\n",
+ "[2025-07-18 20:56:35.338598] Kein neues Signal (0)\n",
+ "[2025-07-18 21:01:35.378704] Kein neues Signal (0)\n",
+ "[2025-07-18 21:06:35.421315] Kein neues Signal (0)\n",
+ "[2025-07-18 21:11:35.446675] Kein neues Signal (0)\n",
+ "[2025-07-18 21:16:35.501085] Kein neues Signal (0)\n",
+ "[2025-07-18 21:21:35.547489] Kein neues Signal (0)\n",
+ "[2025-07-18 21:26:35.600292] Kein neues Signal (0)\n",
+ "[2025-07-18 21:31:35.642080] Kein neues Signal (0)\n",
+ "[2025-07-18 21:36:35.681283] Kein neues Signal (0)\n",
+ "[2025-07-18 21:41:35.719258] Kein neues Signal (0)\n",
+ "[2025-07-18 21:46:35.756743] Kein neues Signal (0)\n",
+ "[2025-07-18 21:51:35.802329] Kein neues Signal (0)\n",
+ "[2025-07-18 21:56:35.849136] Kein neues Signal (0)\n",
+ "[2025-07-18 22:01:35.907573] Kein neues Signal (0)\n"
+ ]
+ },
+ {
+ "ename": "KeyboardInterrupt",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[1;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)",
+ "Cell \u001b[1;32mIn[22], line 2\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;66;03m# ▶️ Live-Trading starten (z. B. alle 5 Minuten)\u001b[39;00m\n\u001b[1;32m----> 2\u001b[0m run_live_trading(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mXAUUSD\u001b[39m\u001b[38;5;124m\"\u001b[39m, interval\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m300\u001b[39m, volume\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m0.1\u001b[39m)\n",
+ "Cell \u001b[1;32mIn[13], line 19\u001b[0m, in \u001b[0;36mrun_live_trading\u001b[1;34m(symbol, interval, volume, db_name)\u001b[0m\n\u001b[0;32m 16\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m 17\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m[\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mdatetime\u001b[38;5;241m.\u001b[39mnow()\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m] Kein neues Signal (\u001b[39m\u001b[38;5;132;01m{\u001b[39;00msignal\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m)\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m---> 19\u001b[0m time\u001b[38;5;241m.\u001b[39msleep(interval)\n",
+ "\u001b[1;31mKeyboardInterrupt\u001b[0m: "
+ ]
+ }
+ ],
+ "source": [
+ "# ▶️ Live-Trading starten (z. B. alle 5 Minuten)\n",
+ "run_live_trading(\"XAUUSD\", interval=300, volume=0.1)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "id": "a7675469",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " timestamp | \n",
+ " symbol | \n",
+ " order_type | \n",
+ " price | \n",
+ " sl | \n",
+ " tp | \n",
+ " volume | \n",
+ " signal | \n",
+ " comment | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " 2025-07-18 16:06:32.701648 | \n",
+ " XAUUSD | \n",
+ " BUY | \n",
+ " 3358.95 | \n",
+ " 3358.75 | \n",
+ " 3359.35 | \n",
+ " 0.1 | \n",
+ " b'\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00' | \n",
+ " AutoSignalBot | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " 2025-07-18 15:51:32.545794 | \n",
+ " XAUUSD | \n",
+ " SELL | \n",
+ " 3354.56 | \n",
+ " 3354.76 | \n",
+ " 3354.16 | \n",
+ " 0.1 | \n",
+ " b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff' | \n",
+ " AutoSignalBot | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " timestamp symbol order_type price sl tp \\\n",
+ "0 2025-07-18 16:06:32.701648 XAUUSD BUY 3358.95 3358.75 3359.35 \n",
+ "1 2025-07-18 15:51:32.545794 XAUUSD SELL 3354.56 3354.76 3354.16 \n",
+ "\n",
+ " volume signal comment \n",
+ "0 0.1 b'\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00' AutoSignalBot \n",
+ "1 0.1 b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff' AutoSignalBot "
+ ]
+ },
+ "execution_count": 13,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# 🧾 Optional: SQLite-Datenbank anzeigen\n",
+ "conn = db.connect(\"trading_log.db\")\n",
+ "pd.read_sql(\"SELECT * FROM trade_log ORDER BY timestamp DESC LIMIT 10\", conn)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "b4512a2c",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "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": 5
+}
diff --git a/AutoTrading_MT5_with_Logging.ipynb:Zone.Identifier b/AutoTrading_MT5_with_Logging.ipynb:Zone.Identifier
new file mode 100644
index 0000000..a45e1ac
--- /dev/null
+++ b/AutoTrading_MT5_with_Logging.ipynb:Zone.Identifier
@@ -0,0 +1,2 @@
+[ZoneTransfer]
+ZoneId=3
diff --git a/AutoTrading_MT5_with_Logging_fib_atr.ipynb b/AutoTrading_MT5_with_Logging_fib_atr.ipynb
new file mode 100644
index 0000000..6f1dcd1
--- /dev/null
+++ b/AutoTrading_MT5_with_Logging_fib_atr.ipynb
@@ -0,0 +1,841 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "4cb5824d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# 📦 Imports\n",
+ "import MetaTrader5 as mt\n",
+ "import pandas as pd\n",
+ "import sqlite3 as db\n",
+ "from datetime import datetime\n",
+ "import time\n",
+ "from scipy.signal import savgol_filter\n",
+ "import pandas_ta as ta\n",
+ "import keyring as kr"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "1279652c",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# 📊 Verbindung zu SQLite\n",
+ "def init_db(db_name=\"trading_log.db\"):\n",
+ " conn = db.connect(db_name)\n",
+ " c = conn.cursor()\n",
+ " c.execute(\"\"\"\n",
+ " CREATE TABLE IF NOT EXISTS trade_log (\n",
+ " timestamp TEXT,\n",
+ " symbol TEXT,\n",
+ " order_type TEXT,\n",
+ " price REAL,\n",
+ " sl REAL,\n",
+ " tp REAL,\n",
+ " volume REAL,\n",
+ " signal INTEGER,\n",
+ " comment TEXT\n",
+ " )\n",
+ " \"\"\")\n",
+ " conn.commit()\n",
+ " return conn"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "fc1eb959",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# 🔐 MT5 Login einmalig initialisieren\n",
+ "mt.initialize()\n",
+ "login = 10800246\n",
+ "server = \"VantageInternational-Demo\"\n",
+ "password = kr.get_password(server, str(login))\n",
+ "mt.login(login, password, server)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "840d41c6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# 📥 MT5 Daten abrufen\n",
+ "def get_mt5_data(symbol=\"XAUUSD\", timeframe=mt.TIMEFRAME_M5, 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": 9,
+ "id": "48445ef4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = get_mt5_data()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "964f927f",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# 🤖 Signale erzeugen\n",
+ "def generate_signal(df):\n",
+ " df[\"ema10\"] = df[\"close\"].ewm(span=10).mean()\n",
+ " df[\"ema30\"] = df[\"close\"].ewm(span=30).mean()\n",
+ " df[\"rsi\"] = ta.rsi(df[\"close\"], length=14)\n",
+ " df[\"trend\"] = savgol_filter(df[\"close\"], 15, 3)\n",
+ " df[\"signal\"] = 0\n",
+ "\n",
+ " for i in range(1, len(df)):\n",
+ " if (\n",
+ " df[\"ema10\"].iloc[i] > df[\"ema30\"].iloc[i]\n",
+ " and df[\"ema10\"].iloc[i - 1] <= df[\"ema30\"].iloc[i - 1]\n",
+ " and df[\"rsi\"].iloc[i] < 70\n",
+ " and df[\"trend\"].iloc[i] > df[\"trend\"].iloc[i - 1]\n",
+ " ):\n",
+ " df.at[i, \"signal\"] = 1\n",
+ " elif (\n",
+ " df[\"ema10\"].iloc[i] < df[\"ema30\"].iloc[i]\n",
+ " and df[\"ema10\"].iloc[i - 1] >= df[\"ema30\"].iloc[i - 1]\n",
+ " and df[\"rsi\"].iloc[i] > 30\n",
+ " and df[\"trend\"].iloc[i] < df[\"trend\"].iloc[i - 1]\n",
+ " ):\n",
+ " df.at[i, \"signal\"] = -1\n",
+ " return df"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "id": "7494a5da",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " time | \n",
+ " open | \n",
+ " high | \n",
+ " low | \n",
+ " close | \n",
+ " tick_volume | \n",
+ " spread | \n",
+ " real_volume | \n",
+ " ema10 | \n",
+ " ema30 | \n",
+ " rsi | \n",
+ " trend | \n",
+ " signal | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " 2025-07-17 04:30:00 | \n",
+ " 3340.74 | \n",
+ " 3341.46 | \n",
+ " 3337.21 | \n",
+ " 3338.04 | \n",
+ " 1293 | \n",
+ " 18 | \n",
+ " 0 | \n",
+ " 3338.040000 | \n",
+ " 3338.040000 | \n",
+ " NaN | \n",
+ " 3338.208386 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " 2025-07-17 04:35:00 | \n",
+ " 3338.03 | \n",
+ " 3341.03 | \n",
+ " 3337.72 | \n",
+ " 3341.03 | \n",
+ " 964 | \n",
+ " 18 | \n",
+ " 0 | \n",
+ " 3339.684500 | \n",
+ " 3339.584833 | \n",
+ " NaN | \n",
+ " 3340.377874 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 2025-07-17 04:40:00 | \n",
+ " 3341.03 | \n",
+ " 3341.48 | \n",
+ " 3339.96 | \n",
+ " 3341.26 | \n",
+ " 944 | \n",
+ " 18 | \n",
+ " 0 | \n",
+ " 3340.317841 | \n",
+ " 3340.180848 | \n",
+ " NaN | \n",
+ " 3341.873882 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 2025-07-17 04:45:00 | \n",
+ " 3341.27 | \n",
+ " 3343.45 | \n",
+ " 3341.27 | \n",
+ " 3342.47 | \n",
+ " 1099 | \n",
+ " 18 | \n",
+ " 0 | \n",
+ " 3341.026881 | \n",
+ " 3340.811593 | \n",
+ " NaN | \n",
+ " 3342.785860 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " 2025-07-17 04:50:00 | \n",
+ " 3342.47 | \n",
+ " 3343.61 | \n",
+ " 3342.20 | \n",
+ " 3342.84 | \n",
+ " 1070 | \n",
+ " 18 | \n",
+ " 0 | \n",
+ " 3341.547378 | \n",
+ " 3341.273104 | \n",
+ " NaN | \n",
+ " 3343.203260 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " | 495 | \n",
+ " 2025-07-18 22:45:00 | \n",
+ " 3349.29 | \n",
+ " 3349.71 | \n",
+ " 3348.47 | \n",
+ " 3348.78 | \n",
+ " 928 | \n",
+ " 19 | \n",
+ " 0 | \n",
+ " 3350.024962 | \n",
+ " 3351.232735 | \n",
+ " 34.935115 | \n",
+ " 3348.405247 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 496 | \n",
+ " 2025-07-18 22:50:00 | \n",
+ " 3348.79 | \n",
+ " 3348.80 | \n",
+ " 3347.62 | \n",
+ " 3348.15 | \n",
+ " 859 | \n",
+ " 19 | \n",
+ " 0 | \n",
+ " 3349.684060 | \n",
+ " 3351.033849 | \n",
+ " 32.290909 | \n",
+ " 3348.186635 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 497 | \n",
+ " 2025-07-18 22:55:00 | \n",
+ " 3348.16 | \n",
+ " 3348.53 | \n",
+ " 3347.65 | \n",
+ " 3348.25 | \n",
+ " 1028 | \n",
+ " 19 | \n",
+ " 0 | \n",
+ " 3349.423322 | \n",
+ " 3350.854245 | \n",
+ " 33.155760 | \n",
+ " 3348.153324 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 498 | \n",
+ " 2025-07-18 23:00:00 | \n",
+ " 3348.24 | \n",
+ " 3348.88 | \n",
+ " 3347.72 | \n",
+ " 3348.06 | \n",
+ " 599 | \n",
+ " 19 | \n",
+ " 0 | \n",
+ " 3349.175445 | \n",
+ " 3350.673972 | \n",
+ " 32.311285 | \n",
+ " 3348.346744 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 499 | \n",
+ " 2025-07-18 23:05:00 | \n",
+ " 3348.06 | \n",
+ " 3349.25 | \n",
+ " 3347.92 | \n",
+ " 3348.88 | \n",
+ " 450 | \n",
+ " 19 | \n",
+ " 0 | \n",
+ " 3349.121728 | \n",
+ " 3350.558231 | \n",
+ " 39.476021 | \n",
+ " 3348.808327 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
500 rows × 13 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " time open high low close tick_volume \\\n",
+ "0 2025-07-17 04:30:00 3340.74 3341.46 3337.21 3338.04 1293 \n",
+ "1 2025-07-17 04:35:00 3338.03 3341.03 3337.72 3341.03 964 \n",
+ "2 2025-07-17 04:40:00 3341.03 3341.48 3339.96 3341.26 944 \n",
+ "3 2025-07-17 04:45:00 3341.27 3343.45 3341.27 3342.47 1099 \n",
+ "4 2025-07-17 04:50:00 3342.47 3343.61 3342.20 3342.84 1070 \n",
+ ".. ... ... ... ... ... ... \n",
+ "495 2025-07-18 22:45:00 3349.29 3349.71 3348.47 3348.78 928 \n",
+ "496 2025-07-18 22:50:00 3348.79 3348.80 3347.62 3348.15 859 \n",
+ "497 2025-07-18 22:55:00 3348.16 3348.53 3347.65 3348.25 1028 \n",
+ "498 2025-07-18 23:00:00 3348.24 3348.88 3347.72 3348.06 599 \n",
+ "499 2025-07-18 23:05:00 3348.06 3349.25 3347.92 3348.88 450 \n",
+ "\n",
+ " spread real_volume ema10 ema30 rsi trend \\\n",
+ "0 18 0 3338.040000 3338.040000 NaN 3338.208386 \n",
+ "1 18 0 3339.684500 3339.584833 NaN 3340.377874 \n",
+ "2 18 0 3340.317841 3340.180848 NaN 3341.873882 \n",
+ "3 18 0 3341.026881 3340.811593 NaN 3342.785860 \n",
+ "4 18 0 3341.547378 3341.273104 NaN 3343.203260 \n",
+ ".. ... ... ... ... ... ... \n",
+ "495 19 0 3350.024962 3351.232735 34.935115 3348.405247 \n",
+ "496 19 0 3349.684060 3351.033849 32.290909 3348.186635 \n",
+ "497 19 0 3349.423322 3350.854245 33.155760 3348.153324 \n",
+ "498 19 0 3349.175445 3350.673972 32.311285 3348.346744 \n",
+ "499 19 0 3349.121728 3350.558231 39.476021 3348.808327 \n",
+ "\n",
+ " 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 13 columns]"
+ ]
+ },
+ "execution_count": 12,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "generate_signal(df)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "id": "0a8abc07",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0.01"
+ ]
+ },
+ "execution_count": 14,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "mt.symbol_info('XAUUSD').point"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "64757821",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# 📤 Order senden\n",
+ "def send_market_order(symbol, volume, order_type, signal, conn, sl_pips=20, tp_pips=40, magic=1001):\n",
+ " tick = mt.symbol_info_tick(symbol)\n",
+ " price = tick.ask if order_type == mt.ORDER_TYPE_BUY else tick.bid\n",
+ " point = mt.symbol_info(symbol).point\n",
+ "\n",
+ " sl = price - sl_pips * point if order_type == mt.ORDER_TYPE_BUY else price + sl_pips * point\n",
+ " tp = price + tp_pips * point if order_type == mt.ORDER_TYPE_BUY else price - tp_pips * point\n",
+ "\n",
+ " request = {\n",
+ " \"action\": mt.TRADE_ACTION_DEAL,\n",
+ " \"symbol\": symbol,\n",
+ " \"volume\": volume,\n",
+ " \"type\": order_type,\n",
+ " \"price\": price,\n",
+ " \"sl\": round(sl, 5),\n",
+ " \"tp\": round(tp, 5),\n",
+ " \"deviation\": 20,\n",
+ " \"magic\": magic,\n",
+ " \"comment\": \"AutoSignalBot\",\n",
+ " \"type_time\": mt.ORDER_TIME_GTC,\n",
+ " \"type_filling\": mt.ORDER_FILLING_IOC,\n",
+ " }\n",
+ "\n",
+ " result = mt.order_send(request)\n",
+ " print(f\"[TRADE] {symbol} - {'BUY' if order_type==0 else 'SELL'} @ {price} | SL: {sl} | TP: {tp}\")\n",
+ "\n",
+ " # Logging in DB\n",
+ " c = conn.cursor()\n",
+ " c.execute(\"\"\"\n",
+ " INSERT INTO trade_log (timestamp, symbol, order_type, price, sl, tp, volume, signal, comment)\n",
+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\n",
+ " \"\"\", (datetime.now(), symbol, \"BUY\" if order_type==0 else \"SELL\", price, sl, tp, volume, signal, \"AutoSignalBot\"))\n",
+ " conn.commit()\n",
+ " \n",
+ " return result"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "id": "3bc5f11e",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# 🔁 Hauptfunktion\n",
+ "def run_live_trading(symbol=\"XAUUSD\", interval=300, volume=0.1, db_name=\"trading_log.db\"):\n",
+ " conn = init_db(db_name)\n",
+ " last_signal = 0\n",
+ "\n",
+ " print(f\"✅ Starte Auto-Trading für {symbol} – Intervall {interval}s\")\n",
+ " while True:\n",
+ " df = get_mt5_data(symbol)\n",
+ " df = generate_signal(df)\n",
+ " signal = df[\"signal\"].iloc[-1]\n",
+ "\n",
+ " if signal != 0 and signal != last_signal:\n",
+ " order_type = mt.ORDER_TYPE_BUY if signal == 1 else mt.ORDER_TYPE_SELL\n",
+ " send_market_order(symbol, volume, order_type, signal, conn)\n",
+ " last_signal = signal\n",
+ " else:\n",
+ " print(f\"[{datetime.now()}] Kein neues Signal ({signal})\")\n",
+ "\n",
+ " time.sleep(interval)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 22,
+ "id": "71acdb0d",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "✅ Starte Auto-Trading für XAUUSD – Intervall 300s\n",
+ "[2025-07-18 12:11:30.004688] Kein neues Signal (0)\n",
+ "[2025-07-18 12:16:30.083605] Kein neues Signal (0)\n",
+ "[2025-07-18 12:21:30.121793] Kein neues Signal (0)\n",
+ "[2025-07-18 12:26:30.174396] Kein neues Signal (0)\n",
+ "[2025-07-18 12:31:30.216996] Kein neues Signal (0)\n",
+ "[2025-07-18 12:36:30.258849] Kein neues Signal (0)\n",
+ "[2025-07-18 12:41:30.313072] Kein neues Signal (0)\n",
+ "[2025-07-18 12:46:30.356620] Kein neues Signal (0)\n",
+ "[2025-07-18 12:51:30.396600] Kein neues Signal (0)\n",
+ "[2025-07-18 12:56:30.442114] Kein neues Signal (0)\n",
+ "[2025-07-18 13:01:30.481155] Kein neues Signal (0)\n",
+ "[2025-07-18 13:06:30.530619] Kein neues Signal (0)\n",
+ "[2025-07-18 13:11:30.566248] Kein neues Signal (0)\n",
+ "[2025-07-18 13:16:30.606701] Kein neues Signal (0)\n",
+ "[2025-07-18 13:21:30.645462] Kein neues Signal (0)\n",
+ "[2025-07-18 13:26:30.686722] Kein neues Signal (0)\n",
+ "[2025-07-18 13:31:31.130100] Kein neues Signal (0)\n",
+ "[2025-07-18 13:36:31.193825] Kein neues Signal (0)\n",
+ "[2025-07-18 13:41:31.381330] Kein neues Signal (0)\n",
+ "[2025-07-18 13:46:31.434187] Kein neues Signal (0)\n",
+ "[2025-07-18 13:51:31.471695] Kein neues Signal (0)\n",
+ "[2025-07-18 13:56:31.507322] Kein neues Signal (0)\n",
+ "[2025-07-18 14:01:31.550436] Kein neues Signal (0)\n",
+ "[2025-07-18 14:06:31.587884] Kein neues Signal (0)\n",
+ "[2025-07-18 14:11:31.665002] Kein neues Signal (0)\n",
+ "[2025-07-18 14:16:31.704012] Kein neues Signal (0)\n",
+ "[2025-07-18 14:21:31.745292] Kein neues Signal (0)\n",
+ "[2025-07-18 14:26:31.783905] Kein neues Signal (0)\n",
+ "[2025-07-18 14:31:31.822325] Kein neues Signal (0)\n",
+ "[2025-07-18 14:36:31.873271] Kein neues Signal (0)\n",
+ "[2025-07-18 14:41:31.914303] Kein neues Signal (0)\n",
+ "[2025-07-18 14:46:31.951585] Kein neues Signal (0)\n",
+ "[2025-07-18 14:51:32.005271] Kein neues Signal (0)\n",
+ "[2025-07-18 14:56:32.046384] Kein neues Signal (0)\n",
+ "[2025-07-18 15:01:32.083259] Kein neues Signal (0)\n",
+ "[2025-07-18 15:06:32.132835] Kein neues Signal (0)\n",
+ "[2025-07-18 15:11:32.176714] Kein neues Signal (0)\n",
+ "[2025-07-18 15:16:32.221857] Kein neues Signal (0)\n",
+ "[2025-07-18 15:21:32.269876] Kein neues Signal (0)\n",
+ "[2025-07-18 15:26:32.313363] Kein neues Signal (0)\n",
+ "[2025-07-18 15:31:32.356954] Kein neues Signal (0)\n",
+ "[2025-07-18 15:36:32.403653] Kein neues Signal (0)\n",
+ "[2025-07-18 15:41:32.449777] Kein neues Signal (0)\n",
+ "[2025-07-18 15:46:32.489053] Kein neues Signal (0)\n",
+ "[TRADE] XAUUSD - SELL @ 3354.56 | SL: 3354.7599999999998 | TP: 3354.16\n",
+ "[2025-07-18 15:56:32.609729] Kein neues Signal (0)\n",
+ "[2025-07-18 16:01:32.650996] Kein neues Signal (0)\n",
+ "[TRADE] XAUUSD - BUY @ 3358.95 | SL: 3358.75 | TP: 3359.35\n",
+ "[2025-07-18 16:11:32.744972] Kein neues Signal (0)\n",
+ "[2025-07-18 16:16:32.791366] Kein neues Signal (0)\n",
+ "[2025-07-18 16:21:32.829930] Kein neues Signal (0)\n",
+ "[2025-07-18 16:26:32.871934] Kein neues Signal (0)\n",
+ "[2025-07-18 16:31:32.912571] Kein neues Signal (0)\n",
+ "[2025-07-18 16:36:32.954745] Kein neues Signal (0)\n",
+ "[2025-07-18 16:41:32.994281] Kein neues Signal (0)\n",
+ "[2025-07-18 16:46:33.048113] Kein neues Signal (0)\n",
+ "[2025-07-18 16:51:33.086281] Kein neues Signal (0)\n",
+ "[2025-07-18 16:56:33.127117] Kein neues Signal (0)\n",
+ "[2025-07-18 17:01:33.177813] Kein neues Signal (0)\n",
+ "[2025-07-18 17:06:33.219713] Kein neues Signal (0)\n",
+ "[2025-07-18 17:11:33.260138] Kein neues Signal (0)\n",
+ "[2025-07-18 17:16:33.302870] Kein neues Signal (0)\n",
+ "[2025-07-18 17:21:33.346259] Kein neues Signal (0)\n",
+ "[2025-07-18 17:26:33.390947] Kein neues Signal (0)\n",
+ "[2025-07-18 17:31:33.434736] Kein neues Signal (0)\n",
+ "[2025-07-18 17:36:33.476901] Kein neues Signal (0)\n",
+ "[2025-07-18 17:41:33.520435] Kein neues Signal (0)\n",
+ "[2025-07-18 17:46:33.575426] Kein neues Signal (0)\n",
+ "[2025-07-18 17:51:33.622573] Kein neues Signal (0)\n",
+ "[2025-07-18 17:56:33.662664] Kein neues Signal (0)\n",
+ "[2025-07-18 18:01:33.703019] Kein neues Signal (0)\n",
+ "[2025-07-18 18:06:33.748220] Kein neues Signal (0)\n",
+ "[2025-07-18 18:11:33.788812] Kein neues Signal (0)\n",
+ "[2025-07-18 18:16:33.827200] Kein neues Signal (0)\n",
+ "[2025-07-18 18:21:33.880825] Kein neues Signal (0)\n",
+ "[2025-07-18 18:26:33.931042] Kein neues Signal (0)\n",
+ "[2025-07-18 18:31:33.982017] Kein neues Signal (0)\n",
+ "[2025-07-18 18:36:34.021865] Kein neues Signal (1)\n",
+ "[2025-07-18 18:41:34.059505] Kein neues Signal (0)\n",
+ "[2025-07-18 18:46:34.100395] Kein neues Signal (0)\n",
+ "[2025-07-18 18:51:34.148794] Kein neues Signal (0)\n",
+ "[2025-07-18 18:56:34.186791] Kein neues Signal (0)\n",
+ "[2025-07-18 19:01:34.227630] Kein neues Signal (0)\n",
+ "[2025-07-18 19:06:34.272331] Kein neues Signal (0)\n",
+ "[2025-07-18 19:11:34.309122] Kein neues Signal (0)\n",
+ "[2025-07-18 19:16:34.350483] Kein neues Signal (0)\n",
+ "[2025-07-18 19:21:34.391638] Kein neues Signal (0)\n",
+ "[2025-07-18 19:26:34.430235] Kein neues Signal (0)\n",
+ "[2025-07-18 19:31:34.476827] Kein neues Signal (0)\n",
+ "[2025-07-18 19:36:34.516804] Kein neues Signal (0)\n",
+ "[2025-07-18 19:41:34.551478] Kein neues Signal (0)\n",
+ "[2025-07-18 19:46:34.600704] Kein neues Signal (0)\n",
+ "[2025-07-18 19:51:34.657098] Kein neues Signal (0)\n",
+ "[2025-07-18 19:56:34.694871] Kein neues Signal (0)\n",
+ "[2025-07-18 20:01:34.750662] Kein neues Signal (0)\n",
+ "[2025-07-18 20:06:34.786445] Kein neues Signal (0)\n",
+ "[2025-07-18 20:11:34.941510] Kein neues Signal (0)\n",
+ "[2025-07-18 20:16:34.997686] Kein neues Signal (0)\n",
+ "[2025-07-18 20:21:35.041835] Kein neues Signal (0)\n",
+ "[2025-07-18 20:26:35.082677] Kein neues Signal (0)\n",
+ "[2025-07-18 20:31:35.135303] Kein neues Signal (0)\n",
+ "[2025-07-18 20:36:35.174403] Kein neues Signal (0)\n",
+ "[2025-07-18 20:41:35.211876] Kein neues Signal (0)\n",
+ "[2025-07-18 20:46:35.254113] Kein neues Signal (0)\n",
+ "[2025-07-18 20:51:35.297650] Kein neues Signal (0)\n",
+ "[2025-07-18 20:56:35.338598] Kein neues Signal (0)\n",
+ "[2025-07-18 21:01:35.378704] Kein neues Signal (0)\n",
+ "[2025-07-18 21:06:35.421315] Kein neues Signal (0)\n",
+ "[2025-07-18 21:11:35.446675] Kein neues Signal (0)\n",
+ "[2025-07-18 21:16:35.501085] Kein neues Signal (0)\n",
+ "[2025-07-18 21:21:35.547489] Kein neues Signal (0)\n",
+ "[2025-07-18 21:26:35.600292] Kein neues Signal (0)\n",
+ "[2025-07-18 21:31:35.642080] Kein neues Signal (0)\n",
+ "[2025-07-18 21:36:35.681283] Kein neues Signal (0)\n",
+ "[2025-07-18 21:41:35.719258] Kein neues Signal (0)\n",
+ "[2025-07-18 21:46:35.756743] Kein neues Signal (0)\n",
+ "[2025-07-18 21:51:35.802329] Kein neues Signal (0)\n",
+ "[2025-07-18 21:56:35.849136] Kein neues Signal (0)\n",
+ "[2025-07-18 22:01:35.907573] Kein neues Signal (0)\n"
+ ]
+ },
+ {
+ "ename": "KeyboardInterrupt",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[1;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)",
+ "Cell \u001b[1;32mIn[22], line 2\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;66;03m# ▶️ Live-Trading starten (z. B. alle 5 Minuten)\u001b[39;00m\n\u001b[1;32m----> 2\u001b[0m run_live_trading(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mXAUUSD\u001b[39m\u001b[38;5;124m\"\u001b[39m, interval\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m300\u001b[39m, volume\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m0.1\u001b[39m)\n",
+ "Cell \u001b[1;32mIn[13], line 19\u001b[0m, in \u001b[0;36mrun_live_trading\u001b[1;34m(symbol, interval, volume, db_name)\u001b[0m\n\u001b[0;32m 16\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m 17\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m[\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mdatetime\u001b[38;5;241m.\u001b[39mnow()\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m] Kein neues Signal (\u001b[39m\u001b[38;5;132;01m{\u001b[39;00msignal\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m)\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m---> 19\u001b[0m time\u001b[38;5;241m.\u001b[39msleep(interval)\n",
+ "\u001b[1;31mKeyboardInterrupt\u001b[0m: "
+ ]
+ }
+ ],
+ "source": [
+ "# ▶️ Live-Trading starten (z. B. alle 5 Minuten)\n",
+ "run_live_trading(\"XAUUSD\", interval=300, volume=0.1)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "id": "a7675469",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " timestamp | \n",
+ " symbol | \n",
+ " order_type | \n",
+ " price | \n",
+ " sl | \n",
+ " tp | \n",
+ " volume | \n",
+ " signal | \n",
+ " comment | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " 2025-07-18 16:06:32.701648 | \n",
+ " XAUUSD | \n",
+ " BUY | \n",
+ " 3358.95 | \n",
+ " 3358.75 | \n",
+ " 3359.35 | \n",
+ " 0.1 | \n",
+ " b'\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00' | \n",
+ " AutoSignalBot | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " 2025-07-18 15:51:32.545794 | \n",
+ " XAUUSD | \n",
+ " SELL | \n",
+ " 3354.56 | \n",
+ " 3354.76 | \n",
+ " 3354.16 | \n",
+ " 0.1 | \n",
+ " b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff' | \n",
+ " AutoSignalBot | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " timestamp symbol order_type price sl tp \\\n",
+ "0 2025-07-18 16:06:32.701648 XAUUSD BUY 3358.95 3358.75 3359.35 \n",
+ "1 2025-07-18 15:51:32.545794 XAUUSD SELL 3354.56 3354.76 3354.16 \n",
+ "\n",
+ " volume signal comment \n",
+ "0 0.1 b'\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00' AutoSignalBot \n",
+ "1 0.1 b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff' AutoSignalBot "
+ ]
+ },
+ "execution_count": 13,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# 🧾 Optional: SQLite-Datenbank anzeigen\n",
+ "conn = db.connect(\"trading_log.db\")\n",
+ "pd.read_sql(\"SELECT * FROM trade_log ORDER BY timestamp DESC LIMIT 10\", conn)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "b4512a2c",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ec808aea",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "\n",
+ "import numpy as np\n",
+ "\n",
+ "def calculate_fib_levels(df, lookback=20):\n",
+ " swing_high = df['high'].rolling(lookback).max().iloc[-1]\n",
+ " swing_low = df['low'].rolling(lookback).min().iloc[-1]\n",
+ " diff = swing_high - swing_low\n",
+ " levels = {\n",
+ " '0.0': swing_low,\n",
+ " '0.236': swing_high - 0.236 * diff,\n",
+ " '0.382': swing_high - 0.382 * diff,\n",
+ " '0.5': swing_high - 0.5 * diff,\n",
+ " '0.618': swing_high - 0.618 * diff,\n",
+ " '0.786': swing_high - 0.786 * diff,\n",
+ " '1.0': swing_high\n",
+ " }\n",
+ " return levels\n",
+ "\n",
+ "def calculate_atr(df, period=14):\n",
+ " df['H-L'] = df['high'] - df['low']\n",
+ " df['H-C'] = abs(df['high'] - df['close'].shift())\n",
+ " df['L-C'] = abs(df['low'] - df['close'].shift())\n",
+ " df['TR'] = df[['H-L', 'H-C', 'L-C']].max(axis=1)\n",
+ " df['ATR'] = df['TR'].rolling(period).mean()\n",
+ " return df\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "09b3f9df",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "\n",
+ "def send_fib_trade(df, symbol, order_type, volume):\n",
+ " fib = calculate_fib_levels(df)\n",
+ " df = calculate_atr(df)\n",
+ " atr = df['ATR'].iloc[-1]\n",
+ " point = mt.symbol_info(symbol).point\n",
+ " tick = mt.symbol_info_tick(symbol)\n",
+ " price = tick.ask if order_type == mt.ORDER_TYPE_BUY else tick.bid\n",
+ "\n",
+ " sl = price - atr if order_type == mt.ORDER_TYPE_BUY else price + atr\n",
+ " tp = price + 2 * atr if order_type == mt.ORDER_TYPE_BUY else price - 2 * atr\n",
+ "\n",
+ " request = {\n",
+ " \"action\": mt.TRADE_ACTION_DEAL,\n",
+ " \"symbol\": symbol,\n",
+ " \"volume\": volume,\n",
+ " \"type\": order_type,\n",
+ " \"price\": price,\n",
+ " \"sl\": round(sl, 5),\n",
+ " \"tp\": round(tp, 5),\n",
+ " \"deviation\": 20,\n",
+ " \"magic\": 1010,\n",
+ " \"comment\": \"FibATR_Trade\",\n",
+ " \"type_time\": mt.ORDER_TIME_GTC,\n",
+ " \"type_filling\": mt.ORDER_FILLING_IOC,\n",
+ " }\n",
+ " return mt.order_send(request)\n"
+ ]
+ }
+ ],
+ "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": 5
+}
diff --git a/AutoTrading_MT5_with_Logging_fib_atr_final.ipynb b/AutoTrading_MT5_with_Logging_fib_atr_final.ipynb
new file mode 100644
index 0000000..1d4fbeb
--- /dev/null
+++ b/AutoTrading_MT5_with_Logging_fib_atr_final.ipynb
@@ -0,0 +1,885 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "4cb5824d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# 📦 Imports\n",
+ "import MetaTrader5 as mt\n",
+ "import pandas as pd\n",
+ "import sqlite3 as db\n",
+ "from datetime import datetime\n",
+ "import time\n",
+ "from scipy.signal import savgol_filter\n",
+ "import pandas_ta as ta\n",
+ "import keyring as kr"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "1279652c",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# 📊 Verbindung zu SQLite\n",
+ "def init_db(db_name=\"trading_log.db\"):\n",
+ " conn = db.connect(db_name)\n",
+ " c = conn.cursor()\n",
+ " c.execute(\"\"\"\n",
+ " CREATE TABLE IF NOT EXISTS trade_log (\n",
+ " timestamp TEXT,\n",
+ " symbol TEXT,\n",
+ " order_type TEXT,\n",
+ " price REAL,\n",
+ " sl REAL,\n",
+ " tp REAL,\n",
+ " volume REAL,\n",
+ " signal INTEGER,\n",
+ " comment TEXT\n",
+ " )\n",
+ " \"\"\")\n",
+ " conn.commit()\n",
+ " return conn"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "fc1eb959",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# 🔐 MT5 Login einmalig initialisieren\n",
+ "mt.initialize()\n",
+ "login = 10800246\n",
+ "server = \"VantageInternational-Demo\"\n",
+ "password = kr.get_password(server, str(login))\n",
+ "mt.login(login, password, server)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "840d41c6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# 📥 MT5 Daten abrufen\n",
+ "def get_mt5_data(symbol=\"XAUUSD\", timeframe=mt.TIMEFRAME_M5, 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": 9,
+ "id": "48445ef4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = get_mt5_data()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "964f927f",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# 🤖 Signale erzeugen\n",
+ "def generate_signal(df):\n",
+ " df[\"ema10\"] = df[\"close\"].ewm(span=10).mean()\n",
+ " df[\"ema30\"] = df[\"close\"].ewm(span=30).mean()\n",
+ " df[\"rsi\"] = ta.rsi(df[\"close\"], length=14)\n",
+ " df[\"trend\"] = savgol_filter(df[\"close\"], 15, 3)\n",
+ " df[\"signal\"] = 0\n",
+ "\n",
+ " for i in range(1, len(df)):\n",
+ " if (\n",
+ " df[\"ema10\"].iloc[i] > df[\"ema30\"].iloc[i]\n",
+ " and df[\"ema10\"].iloc[i - 1] <= df[\"ema30\"].iloc[i - 1]\n",
+ " and df[\"rsi\"].iloc[i] < 70\n",
+ " and df[\"trend\"].iloc[i] > df[\"trend\"].iloc[i - 1]\n",
+ " ):\n",
+ " df.at[i, \"signal\"] = 1\n",
+ " elif (\n",
+ " df[\"ema10\"].iloc[i] < df[\"ema30\"].iloc[i]\n",
+ " and df[\"ema10\"].iloc[i - 1] >= df[\"ema30\"].iloc[i - 1]\n",
+ " and df[\"rsi\"].iloc[i] > 30\n",
+ " and df[\"trend\"].iloc[i] < df[\"trend\"].iloc[i - 1]\n",
+ " ):\n",
+ " df.at[i, \"signal\"] = -1\n",
+ " return df"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "id": "7494a5da",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " time | \n",
+ " open | \n",
+ " high | \n",
+ " low | \n",
+ " close | \n",
+ " tick_volume | \n",
+ " spread | \n",
+ " real_volume | \n",
+ " ema10 | \n",
+ " ema30 | \n",
+ " rsi | \n",
+ " trend | \n",
+ " signal | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " 2025-07-17 04:30:00 | \n",
+ " 3340.74 | \n",
+ " 3341.46 | \n",
+ " 3337.21 | \n",
+ " 3338.04 | \n",
+ " 1293 | \n",
+ " 18 | \n",
+ " 0 | \n",
+ " 3338.040000 | \n",
+ " 3338.040000 | \n",
+ " NaN | \n",
+ " 3338.208386 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " 2025-07-17 04:35:00 | \n",
+ " 3338.03 | \n",
+ " 3341.03 | \n",
+ " 3337.72 | \n",
+ " 3341.03 | \n",
+ " 964 | \n",
+ " 18 | \n",
+ " 0 | \n",
+ " 3339.684500 | \n",
+ " 3339.584833 | \n",
+ " NaN | \n",
+ " 3340.377874 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 2025-07-17 04:40:00 | \n",
+ " 3341.03 | \n",
+ " 3341.48 | \n",
+ " 3339.96 | \n",
+ " 3341.26 | \n",
+ " 944 | \n",
+ " 18 | \n",
+ " 0 | \n",
+ " 3340.317841 | \n",
+ " 3340.180848 | \n",
+ " NaN | \n",
+ " 3341.873882 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 2025-07-17 04:45:00 | \n",
+ " 3341.27 | \n",
+ " 3343.45 | \n",
+ " 3341.27 | \n",
+ " 3342.47 | \n",
+ " 1099 | \n",
+ " 18 | \n",
+ " 0 | \n",
+ " 3341.026881 | \n",
+ " 3340.811593 | \n",
+ " NaN | \n",
+ " 3342.785860 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " 2025-07-17 04:50:00 | \n",
+ " 3342.47 | \n",
+ " 3343.61 | \n",
+ " 3342.20 | \n",
+ " 3342.84 | \n",
+ " 1070 | \n",
+ " 18 | \n",
+ " 0 | \n",
+ " 3341.547378 | \n",
+ " 3341.273104 | \n",
+ " NaN | \n",
+ " 3343.203260 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " | 495 | \n",
+ " 2025-07-18 22:45:00 | \n",
+ " 3349.29 | \n",
+ " 3349.71 | \n",
+ " 3348.47 | \n",
+ " 3348.78 | \n",
+ " 928 | \n",
+ " 19 | \n",
+ " 0 | \n",
+ " 3350.024962 | \n",
+ " 3351.232735 | \n",
+ " 34.935115 | \n",
+ " 3348.405247 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 496 | \n",
+ " 2025-07-18 22:50:00 | \n",
+ " 3348.79 | \n",
+ " 3348.80 | \n",
+ " 3347.62 | \n",
+ " 3348.15 | \n",
+ " 859 | \n",
+ " 19 | \n",
+ " 0 | \n",
+ " 3349.684060 | \n",
+ " 3351.033849 | \n",
+ " 32.290909 | \n",
+ " 3348.186635 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 497 | \n",
+ " 2025-07-18 22:55:00 | \n",
+ " 3348.16 | \n",
+ " 3348.53 | \n",
+ " 3347.65 | \n",
+ " 3348.25 | \n",
+ " 1028 | \n",
+ " 19 | \n",
+ " 0 | \n",
+ " 3349.423322 | \n",
+ " 3350.854245 | \n",
+ " 33.155760 | \n",
+ " 3348.153324 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 498 | \n",
+ " 2025-07-18 23:00:00 | \n",
+ " 3348.24 | \n",
+ " 3348.88 | \n",
+ " 3347.72 | \n",
+ " 3348.06 | \n",
+ " 599 | \n",
+ " 19 | \n",
+ " 0 | \n",
+ " 3349.175445 | \n",
+ " 3350.673972 | \n",
+ " 32.311285 | \n",
+ " 3348.346744 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 499 | \n",
+ " 2025-07-18 23:05:00 | \n",
+ " 3348.06 | \n",
+ " 3349.25 | \n",
+ " 3347.92 | \n",
+ " 3348.88 | \n",
+ " 450 | \n",
+ " 19 | \n",
+ " 0 | \n",
+ " 3349.121728 | \n",
+ " 3350.558231 | \n",
+ " 39.476021 | \n",
+ " 3348.808327 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
500 rows × 13 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " time open high low close tick_volume \\\n",
+ "0 2025-07-17 04:30:00 3340.74 3341.46 3337.21 3338.04 1293 \n",
+ "1 2025-07-17 04:35:00 3338.03 3341.03 3337.72 3341.03 964 \n",
+ "2 2025-07-17 04:40:00 3341.03 3341.48 3339.96 3341.26 944 \n",
+ "3 2025-07-17 04:45:00 3341.27 3343.45 3341.27 3342.47 1099 \n",
+ "4 2025-07-17 04:50:00 3342.47 3343.61 3342.20 3342.84 1070 \n",
+ ".. ... ... ... ... ... ... \n",
+ "495 2025-07-18 22:45:00 3349.29 3349.71 3348.47 3348.78 928 \n",
+ "496 2025-07-18 22:50:00 3348.79 3348.80 3347.62 3348.15 859 \n",
+ "497 2025-07-18 22:55:00 3348.16 3348.53 3347.65 3348.25 1028 \n",
+ "498 2025-07-18 23:00:00 3348.24 3348.88 3347.72 3348.06 599 \n",
+ "499 2025-07-18 23:05:00 3348.06 3349.25 3347.92 3348.88 450 \n",
+ "\n",
+ " spread real_volume ema10 ema30 rsi trend \\\n",
+ "0 18 0 3338.040000 3338.040000 NaN 3338.208386 \n",
+ "1 18 0 3339.684500 3339.584833 NaN 3340.377874 \n",
+ "2 18 0 3340.317841 3340.180848 NaN 3341.873882 \n",
+ "3 18 0 3341.026881 3340.811593 NaN 3342.785860 \n",
+ "4 18 0 3341.547378 3341.273104 NaN 3343.203260 \n",
+ ".. ... ... ... ... ... ... \n",
+ "495 19 0 3350.024962 3351.232735 34.935115 3348.405247 \n",
+ "496 19 0 3349.684060 3351.033849 32.290909 3348.186635 \n",
+ "497 19 0 3349.423322 3350.854245 33.155760 3348.153324 \n",
+ "498 19 0 3349.175445 3350.673972 32.311285 3348.346744 \n",
+ "499 19 0 3349.121728 3350.558231 39.476021 3348.808327 \n",
+ "\n",
+ " 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 13 columns]"
+ ]
+ },
+ "execution_count": 12,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "generate_signal(df)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "id": "0a8abc07",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0.01"
+ ]
+ },
+ "execution_count": 14,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "mt.symbol_info('XAUUSD').point"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "64757821",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# 📤 Order senden\n",
+ "def send_market_order(symbol, volume, order_type, signal, conn, sl_pips=20, tp_pips=40, magic=1001):\n",
+ " tick = mt.symbol_info_tick(symbol)\n",
+ " price = tick.ask if order_type == mt.ORDER_TYPE_BUY else tick.bid\n",
+ " point = mt.symbol_info(symbol).point\n",
+ "\n",
+ " sl = price - sl_pips * point if order_type == mt.ORDER_TYPE_BUY else price + sl_pips * point\n",
+ " tp = price + tp_pips * point if order_type == mt.ORDER_TYPE_BUY else price - tp_pips * point\n",
+ "\n",
+ " request = {\n",
+ " \"action\": mt.TRADE_ACTION_DEAL,\n",
+ " \"symbol\": symbol,\n",
+ " \"volume\": volume,\n",
+ " \"type\": order_type,\n",
+ " \"price\": price,\n",
+ " \"sl\": round(sl, 5),\n",
+ " \"tp\": round(tp, 5),\n",
+ " \"deviation\": 20,\n",
+ " \"magic\": magic,\n",
+ " \"comment\": \"AutoSignalBot\",\n",
+ " \"type_time\": mt.ORDER_TIME_GTC,\n",
+ " \"type_filling\": mt.ORDER_FILLING_IOC,\n",
+ " }\n",
+ "\n",
+ " result = mt.order_send(request)\n",
+ " print(f\"[TRADE] {symbol} - {'BUY' if order_type==0 else 'SELL'} @ {price} | SL: {sl} | TP: {tp}\")\n",
+ "\n",
+ " # Logging in DB\n",
+ " c = conn.cursor()\n",
+ " c.execute(\"\"\"\n",
+ " INSERT INTO trade_log (timestamp, symbol, order_type, price, sl, tp, volume, signal, comment)\n",
+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\n",
+ " \"\"\", (datetime.now(), symbol, \"BUY\" if order_type==0 else \"SELL\", price, sl, tp, volume, signal, \"AutoSignalBot\"))\n",
+ " conn.commit()\n",
+ " \n",
+ " return result"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "id": "3bc5f11e",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# 🔁 Hauptfunktion\n",
+ "def run_live_trading(symbol=\"XAUUSD\", interval=300, volume=0.1, db_name=\"trading_log.db\"):\n",
+ " conn = init_db(db_name)\n",
+ " last_signal = 0\n",
+ "\n",
+ " print(f\"✅ Starte Auto-Trading für {symbol} – Intervall {interval}s\")\n",
+ " while True:\n",
+ " df = get_mt5_data(symbol)\n",
+ " df = generate_signal(df)\n",
+ " signal = df[\"signal\"].iloc[-1]\n",
+ "\n",
+ " if signal != 0 and signal != last_signal:\n",
+ " order_type = mt.ORDER_TYPE_BUY if signal == 1 else mt.ORDER_TYPE_SELL\n",
+ " send_market_order(symbol, volume, order_type, signal, conn)\n",
+ " last_signal = signal\n",
+ " else:\n",
+ " print(f\"[{datetime.now()}] Kein neues Signal ({signal})\")\n",
+ "\n",
+ " time.sleep(interval)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 22,
+ "id": "71acdb0d",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "✅ Starte Auto-Trading für XAUUSD – Intervall 300s\n",
+ "[2025-07-18 12:11:30.004688] Kein neues Signal (0)\n",
+ "[2025-07-18 12:16:30.083605] Kein neues Signal (0)\n",
+ "[2025-07-18 12:21:30.121793] Kein neues Signal (0)\n",
+ "[2025-07-18 12:26:30.174396] Kein neues Signal (0)\n",
+ "[2025-07-18 12:31:30.216996] Kein neues Signal (0)\n",
+ "[2025-07-18 12:36:30.258849] Kein neues Signal (0)\n",
+ "[2025-07-18 12:41:30.313072] Kein neues Signal (0)\n",
+ "[2025-07-18 12:46:30.356620] Kein neues Signal (0)\n",
+ "[2025-07-18 12:51:30.396600] Kein neues Signal (0)\n",
+ "[2025-07-18 12:56:30.442114] Kein neues Signal (0)\n",
+ "[2025-07-18 13:01:30.481155] Kein neues Signal (0)\n",
+ "[2025-07-18 13:06:30.530619] Kein neues Signal (0)\n",
+ "[2025-07-18 13:11:30.566248] Kein neues Signal (0)\n",
+ "[2025-07-18 13:16:30.606701] Kein neues Signal (0)\n",
+ "[2025-07-18 13:21:30.645462] Kein neues Signal (0)\n",
+ "[2025-07-18 13:26:30.686722] Kein neues Signal (0)\n",
+ "[2025-07-18 13:31:31.130100] Kein neues Signal (0)\n",
+ "[2025-07-18 13:36:31.193825] Kein neues Signal (0)\n",
+ "[2025-07-18 13:41:31.381330] Kein neues Signal (0)\n",
+ "[2025-07-18 13:46:31.434187] Kein neues Signal (0)\n",
+ "[2025-07-18 13:51:31.471695] Kein neues Signal (0)\n",
+ "[2025-07-18 13:56:31.507322] Kein neues Signal (0)\n",
+ "[2025-07-18 14:01:31.550436] Kein neues Signal (0)\n",
+ "[2025-07-18 14:06:31.587884] Kein neues Signal (0)\n",
+ "[2025-07-18 14:11:31.665002] Kein neues Signal (0)\n",
+ "[2025-07-18 14:16:31.704012] Kein neues Signal (0)\n",
+ "[2025-07-18 14:21:31.745292] Kein neues Signal (0)\n",
+ "[2025-07-18 14:26:31.783905] Kein neues Signal (0)\n",
+ "[2025-07-18 14:31:31.822325] Kein neues Signal (0)\n",
+ "[2025-07-18 14:36:31.873271] Kein neues Signal (0)\n",
+ "[2025-07-18 14:41:31.914303] Kein neues Signal (0)\n",
+ "[2025-07-18 14:46:31.951585] Kein neues Signal (0)\n",
+ "[2025-07-18 14:51:32.005271] Kein neues Signal (0)\n",
+ "[2025-07-18 14:56:32.046384] Kein neues Signal (0)\n",
+ "[2025-07-18 15:01:32.083259] Kein neues Signal (0)\n",
+ "[2025-07-18 15:06:32.132835] Kein neues Signal (0)\n",
+ "[2025-07-18 15:11:32.176714] Kein neues Signal (0)\n",
+ "[2025-07-18 15:16:32.221857] Kein neues Signal (0)\n",
+ "[2025-07-18 15:21:32.269876] Kein neues Signal (0)\n",
+ "[2025-07-18 15:26:32.313363] Kein neues Signal (0)\n",
+ "[2025-07-18 15:31:32.356954] Kein neues Signal (0)\n",
+ "[2025-07-18 15:36:32.403653] Kein neues Signal (0)\n",
+ "[2025-07-18 15:41:32.449777] Kein neues Signal (0)\n",
+ "[2025-07-18 15:46:32.489053] Kein neues Signal (0)\n",
+ "[TRADE] XAUUSD - SELL @ 3354.56 | SL: 3354.7599999999998 | TP: 3354.16\n",
+ "[2025-07-18 15:56:32.609729] Kein neues Signal (0)\n",
+ "[2025-07-18 16:01:32.650996] Kein neues Signal (0)\n",
+ "[TRADE] XAUUSD - BUY @ 3358.95 | SL: 3358.75 | TP: 3359.35\n",
+ "[2025-07-18 16:11:32.744972] Kein neues Signal (0)\n",
+ "[2025-07-18 16:16:32.791366] Kein neues Signal (0)\n",
+ "[2025-07-18 16:21:32.829930] Kein neues Signal (0)\n",
+ "[2025-07-18 16:26:32.871934] Kein neues Signal (0)\n",
+ "[2025-07-18 16:31:32.912571] Kein neues Signal (0)\n",
+ "[2025-07-18 16:36:32.954745] Kein neues Signal (0)\n",
+ "[2025-07-18 16:41:32.994281] Kein neues Signal (0)\n",
+ "[2025-07-18 16:46:33.048113] Kein neues Signal (0)\n",
+ "[2025-07-18 16:51:33.086281] Kein neues Signal (0)\n",
+ "[2025-07-18 16:56:33.127117] Kein neues Signal (0)\n",
+ "[2025-07-18 17:01:33.177813] Kein neues Signal (0)\n",
+ "[2025-07-18 17:06:33.219713] Kein neues Signal (0)\n",
+ "[2025-07-18 17:11:33.260138] Kein neues Signal (0)\n",
+ "[2025-07-18 17:16:33.302870] Kein neues Signal (0)\n",
+ "[2025-07-18 17:21:33.346259] Kein neues Signal (0)\n",
+ "[2025-07-18 17:26:33.390947] Kein neues Signal (0)\n",
+ "[2025-07-18 17:31:33.434736] Kein neues Signal (0)\n",
+ "[2025-07-18 17:36:33.476901] Kein neues Signal (0)\n",
+ "[2025-07-18 17:41:33.520435] Kein neues Signal (0)\n",
+ "[2025-07-18 17:46:33.575426] Kein neues Signal (0)\n",
+ "[2025-07-18 17:51:33.622573] Kein neues Signal (0)\n",
+ "[2025-07-18 17:56:33.662664] Kein neues Signal (0)\n",
+ "[2025-07-18 18:01:33.703019] Kein neues Signal (0)\n",
+ "[2025-07-18 18:06:33.748220] Kein neues Signal (0)\n",
+ "[2025-07-18 18:11:33.788812] Kein neues Signal (0)\n",
+ "[2025-07-18 18:16:33.827200] Kein neues Signal (0)\n",
+ "[2025-07-18 18:21:33.880825] Kein neues Signal (0)\n",
+ "[2025-07-18 18:26:33.931042] Kein neues Signal (0)\n",
+ "[2025-07-18 18:31:33.982017] Kein neues Signal (0)\n",
+ "[2025-07-18 18:36:34.021865] Kein neues Signal (1)\n",
+ "[2025-07-18 18:41:34.059505] Kein neues Signal (0)\n",
+ "[2025-07-18 18:46:34.100395] Kein neues Signal (0)\n",
+ "[2025-07-18 18:51:34.148794] Kein neues Signal (0)\n",
+ "[2025-07-18 18:56:34.186791] Kein neues Signal (0)\n",
+ "[2025-07-18 19:01:34.227630] Kein neues Signal (0)\n",
+ "[2025-07-18 19:06:34.272331] Kein neues Signal (0)\n",
+ "[2025-07-18 19:11:34.309122] Kein neues Signal (0)\n",
+ "[2025-07-18 19:16:34.350483] Kein neues Signal (0)\n",
+ "[2025-07-18 19:21:34.391638] Kein neues Signal (0)\n",
+ "[2025-07-18 19:26:34.430235] Kein neues Signal (0)\n",
+ "[2025-07-18 19:31:34.476827] Kein neues Signal (0)\n",
+ "[2025-07-18 19:36:34.516804] Kein neues Signal (0)\n",
+ "[2025-07-18 19:41:34.551478] Kein neues Signal (0)\n",
+ "[2025-07-18 19:46:34.600704] Kein neues Signal (0)\n",
+ "[2025-07-18 19:51:34.657098] Kein neues Signal (0)\n",
+ "[2025-07-18 19:56:34.694871] Kein neues Signal (0)\n",
+ "[2025-07-18 20:01:34.750662] Kein neues Signal (0)\n",
+ "[2025-07-18 20:06:34.786445] Kein neues Signal (0)\n",
+ "[2025-07-18 20:11:34.941510] Kein neues Signal (0)\n",
+ "[2025-07-18 20:16:34.997686] Kein neues Signal (0)\n",
+ "[2025-07-18 20:21:35.041835] Kein neues Signal (0)\n",
+ "[2025-07-18 20:26:35.082677] Kein neues Signal (0)\n",
+ "[2025-07-18 20:31:35.135303] Kein neues Signal (0)\n",
+ "[2025-07-18 20:36:35.174403] Kein neues Signal (0)\n",
+ "[2025-07-18 20:41:35.211876] Kein neues Signal (0)\n",
+ "[2025-07-18 20:46:35.254113] Kein neues Signal (0)\n",
+ "[2025-07-18 20:51:35.297650] Kein neues Signal (0)\n",
+ "[2025-07-18 20:56:35.338598] Kein neues Signal (0)\n",
+ "[2025-07-18 21:01:35.378704] Kein neues Signal (0)\n",
+ "[2025-07-18 21:06:35.421315] Kein neues Signal (0)\n",
+ "[2025-07-18 21:11:35.446675] Kein neues Signal (0)\n",
+ "[2025-07-18 21:16:35.501085] Kein neues Signal (0)\n",
+ "[2025-07-18 21:21:35.547489] Kein neues Signal (0)\n",
+ "[2025-07-18 21:26:35.600292] Kein neues Signal (0)\n",
+ "[2025-07-18 21:31:35.642080] Kein neues Signal (0)\n",
+ "[2025-07-18 21:36:35.681283] Kein neues Signal (0)\n",
+ "[2025-07-18 21:41:35.719258] Kein neues Signal (0)\n",
+ "[2025-07-18 21:46:35.756743] Kein neues Signal (0)\n",
+ "[2025-07-18 21:51:35.802329] Kein neues Signal (0)\n",
+ "[2025-07-18 21:56:35.849136] Kein neues Signal (0)\n",
+ "[2025-07-18 22:01:35.907573] Kein neues Signal (0)\n"
+ ]
+ },
+ {
+ "ename": "KeyboardInterrupt",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[1;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)",
+ "Cell \u001b[1;32mIn[22], line 2\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;66;03m# ▶️ Live-Trading starten (z. B. alle 5 Minuten)\u001b[39;00m\n\u001b[1;32m----> 2\u001b[0m run_live_trading(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mXAUUSD\u001b[39m\u001b[38;5;124m\"\u001b[39m, interval\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m300\u001b[39m, volume\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m0.1\u001b[39m)\n",
+ "Cell \u001b[1;32mIn[13], line 19\u001b[0m, in \u001b[0;36mrun_live_trading\u001b[1;34m(symbol, interval, volume, db_name)\u001b[0m\n\u001b[0;32m 16\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m 17\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m[\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mdatetime\u001b[38;5;241m.\u001b[39mnow()\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m] Kein neues Signal (\u001b[39m\u001b[38;5;132;01m{\u001b[39;00msignal\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m)\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m---> 19\u001b[0m time\u001b[38;5;241m.\u001b[39msleep(interval)\n",
+ "\u001b[1;31mKeyboardInterrupt\u001b[0m: "
+ ]
+ }
+ ],
+ "source": [
+ "# ▶️ Live-Trading starten (z. B. alle 5 Minuten)\n",
+ "run_live_trading(\"XAUUSD\", interval=300, volume=0.1)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "id": "a7675469",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " timestamp | \n",
+ " symbol | \n",
+ " order_type | \n",
+ " price | \n",
+ " sl | \n",
+ " tp | \n",
+ " volume | \n",
+ " signal | \n",
+ " comment | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " 2025-07-18 16:06:32.701648 | \n",
+ " XAUUSD | \n",
+ " BUY | \n",
+ " 3358.95 | \n",
+ " 3358.75 | \n",
+ " 3359.35 | \n",
+ " 0.1 | \n",
+ " b'\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00' | \n",
+ " AutoSignalBot | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " 2025-07-18 15:51:32.545794 | \n",
+ " XAUUSD | \n",
+ " SELL | \n",
+ " 3354.56 | \n",
+ " 3354.76 | \n",
+ " 3354.16 | \n",
+ " 0.1 | \n",
+ " b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff' | \n",
+ " AutoSignalBot | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " timestamp symbol order_type price sl tp \\\n",
+ "0 2025-07-18 16:06:32.701648 XAUUSD BUY 3358.95 3358.75 3359.35 \n",
+ "1 2025-07-18 15:51:32.545794 XAUUSD SELL 3354.56 3354.76 3354.16 \n",
+ "\n",
+ " volume signal comment \n",
+ "0 0.1 b'\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00' AutoSignalBot \n",
+ "1 0.1 b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff' AutoSignalBot "
+ ]
+ },
+ "execution_count": 13,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# 🧾 Optional: SQLite-Datenbank anzeigen\n",
+ "conn = db.connect(\"trading_log.db\")\n",
+ "pd.read_sql(\"SELECT * FROM trade_log ORDER BY timestamp DESC LIMIT 10\", conn)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "b4512a2c",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ec808aea",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "\n",
+ "import numpy as np\n",
+ "\n",
+ "def calculate_fib_levels(df, lookback=20):\n",
+ " swing_high = df['high'].rolling(lookback).max().iloc[-1]\n",
+ " swing_low = df['low'].rolling(lookback).min().iloc[-1]\n",
+ " diff = swing_high - swing_low\n",
+ " levels = {\n",
+ " '0.0': swing_low,\n",
+ " '0.236': swing_high - 0.236 * diff,\n",
+ " '0.382': swing_high - 0.382 * diff,\n",
+ " '0.5': swing_high - 0.5 * diff,\n",
+ " '0.618': swing_high - 0.618 * diff,\n",
+ " '0.786': swing_high - 0.786 * diff,\n",
+ " '1.0': swing_high\n",
+ " }\n",
+ " return levels\n",
+ "\n",
+ "def calculate_atr(df, period=14):\n",
+ " df['H-L'] = df['high'] - df['low']\n",
+ " df['H-C'] = abs(df['high'] - df['close'].shift())\n",
+ " df['L-C'] = abs(df['low'] - df['close'].shift())\n",
+ " df['TR'] = df[['H-L', 'H-C', 'L-C']].max(axis=1)\n",
+ " df['ATR'] = df['TR'].rolling(period).mean()\n",
+ " return df\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "09b3f9df",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "\n",
+ "def send_fib_trade(df, symbol, order_type, volume):\n",
+ " fib = calculate_fib_levels(df)\n",
+ " df = calculate_atr(df)\n",
+ " atr = df['ATR'].iloc[-1]\n",
+ " point = mt.symbol_info(symbol).point\n",
+ " tick = mt.symbol_info_tick(symbol)\n",
+ " price = tick.ask if order_type == mt.ORDER_TYPE_BUY else tick.bid\n",
+ "\n",
+ " sl = price - atr if order_type == mt.ORDER_TYPE_BUY else price + atr\n",
+ " tp = price + 2 * atr if order_type == mt.ORDER_TYPE_BUY else price - 2 * atr\n",
+ "\n",
+ " request = {\n",
+ " \"action\": mt.TRADE_ACTION_DEAL,\n",
+ " \"symbol\": symbol,\n",
+ " \"volume\": volume,\n",
+ " \"type\": order_type,\n",
+ " \"price\": price,\n",
+ " \"sl\": round(sl, 5),\n",
+ " \"tp\": round(tp, 5),\n",
+ " \"deviation\": 20,\n",
+ " \"magic\": 1010,\n",
+ " \"comment\": \"FibATR_Trade\",\n",
+ " \"type_time\": mt.ORDER_TIME_GTC,\n",
+ " \"type_filling\": mt.ORDER_FILLING_IOC,\n",
+ " }\n",
+ " return mt.order_send(request)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "8878e31f",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "\n",
+ "import matplotlib.pyplot as plt\n",
+ "\n",
+ "def plot_fib_levels(df, levels):\n",
+ " plt.figure(figsize=(12, 6))\n",
+ " plt.plot(df['close'], label='Close Price', alpha=0.5)\n",
+ " last_index = df.index[-1]\n",
+ " start_index = df.index[-50] if len(df) >= 50 else df.index[0]\n",
+ "\n",
+ " for level, price in levels.items():\n",
+ " plt.hlines(price, start_index, last_index, label=f'Fibo {level}: {round(price, 2)}', linestyles='--')\n",
+ "\n",
+ " plt.title(\"Fibonacci Retracement Levels\")\n",
+ " plt.xlabel(\"Zeit\")\n",
+ " plt.ylabel(\"Preis\")\n",
+ " plt.legend()\n",
+ " plt.grid(True)\n",
+ " plt.tight_layout()\n",
+ " plt.show()\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ffa9c58a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "\n",
+ "def check_fib_entry(df, fib_levels, tolerance=0.01):\n",
+ " current_price = df['close'].iloc[-1]\n",
+ " level_price = fib_levels['0.382']\n",
+ " diff = abs(current_price - level_price)\n",
+ " fib_range = fib_levels['1.0'] - fib_levels['0.0']\n",
+ " return diff < tolerance * fib_range\n"
+ ]
+ }
+ ],
+ "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": 5
+}
diff --git a/Backtest_5minXAUUSD.py b/Backtest_5minXAUUSD.py
new file mode 100644
index 0000000..4e7d69e
--- /dev/null
+++ b/Backtest_5minXAUUSD.py
@@ -0,0 +1,66 @@
+import pandas as pd
+import numpy as np
+from backtesting import Backtest, Strategy
+from backtesting.lib import crossover
+from ta.momentum import rsi
+from scipy.signal import savgol_filter
+
+# Daten vorbereiten (df muss OHLCV-Daten enthalten: 'open', 'high', 'low', 'close', 'volume')
+df = pd.read_csv('xauusd_5min.csv', parse_dates=['time'])
+df.set_index('time', inplace=True)
+
+# Indikatoren berechnen
+def calculate_indicators(df):
+ df['ema21'] = df['close'].ewm(span=21).mean()
+ df['ema50'] = df['close'].ewm(span=50).mean()
+ df['rsi9'] = rsi(df['close'], length=9)
+ df['rsi14'] = rsi(df['close'], length=14)
+ df['trend'] = savgol_filter(df['close'], window_length=25, polyorder=3)
+ return df
+
+df = calculate_indicators(df)
+
+# Strategie definieren
+class Gold5MinStrategy(Strategy):
+ def init(self):
+ # Indikatoren für den Plot
+ self.add_indicator('EMA21', self.data.ema21)
+ self.add_indicator('EMA50', self.data.ema50)
+
+ def next(self):
+ current_index = len(self.data.close) - 1
+
+ # Long-Signal (Kauf)
+ if (
+ crossover(self.data.ema21, self.data.ema50)
+ and self.data.rsi14[-1] < 65
+ and self.data.rsi9[-1] > 50
+ and self.data.trend[-1] > self.data.trend[-2]
+ and not self.position.is_long
+ ):
+ self.buy(sl=self.data.low[-1] * 0.995, tp=self.data.close[-1] * 1.01) # 0.5% SL, 1% TP
+
+ # Short-Signal (Verkauf)
+ elif (
+ crossover(self.data.ema50, self.data.ema21)
+ and self.data.rsi14[-1] > 35
+ and self.data.rsi9[-1] < 50
+ and self.data.trend[-1] < self.data.trend[-2]
+ and not self.position.is_short
+ ):
+ self.sell(sl=self.data.high[-1] * 1.005, tp=self.data.close[-1] * 0.99) # 0.5% SL, 1% TP
+
+# Backtest ausführen
+bt = Backtest(df, Gold5MinStrategy, commission=0.0002, margin=0.05) # 0.02% Kommission, 5% Margin
+stats = bt.run()
+print(stats)
+
+# Optimierung (optional)
+# stats_opt = bt.optimize(
+# rsi_long_upper=[60, 65, 70],
+# rsi_short_lower=[30, 35, 40],
+# maximize='Return [%]'
+# )
+
+# Ergebnisse plotten
+bt.plot()
\ No newline at end of file
diff --git a/TradingBot_V1.1.ipynb b/TradingBot_V1.1.ipynb
new file mode 100644
index 0000000..53ce238
--- /dev/null
+++ b/TradingBot_V1.1.ipynb
@@ -0,0 +1,2466 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Import Libaries"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#!pip install ta_lib-0.6.5-cp311-cp311-win_amd64.whl"
+ ]
+ },
+ {
+ "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",
+ " open | \n",
+ " high | \n",
+ " low | \n",
+ " close | \n",
+ " tick_volume | \n",
+ " spread | \n",
+ " real_volume | \n",
+ " atr | \n",
+ "
\n",
+ " \n",
+ " | time | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 2025-07-23 16:00:00 | \n",
+ " 3419.98 | \n",
+ " 3420.52 | \n",
+ " 3381.47 | \n",
+ " 3387.38 | \n",
+ " 89692 | \n",
+ " 19 | \n",
+ " 0 | \n",
+ " 13.861980 | \n",
+ "
\n",
+ " \n",
+ " | 2025-07-23 20:00:00 | \n",
+ " 3387.33 | \n",
+ " 3395.94 | \n",
+ " 3385.74 | \n",
+ " 3386.78 | \n",
+ " 49534 | \n",
+ " 19 | \n",
+ " 0 | \n",
+ " 14.128410 | \n",
+ "
\n",
+ " \n",
+ " | 2025-07-24 00:00:00 | \n",
+ " 3388.01 | \n",
+ " 3393.16 | \n",
+ " 3386.48 | \n",
+ " 3391.44 | \n",
+ " 18496 | \n",
+ " 19 | \n",
+ " 0 | \n",
+ " 14.305667 | \n",
+ "
\n",
+ " \n",
+ " | 2025-07-24 04:00:00 | \n",
+ " 3391.44 | \n",
+ " 3393.36 | \n",
+ " 3374.71 | \n",
+ " 3382.57 | \n",
+ " 56315 | \n",
+ " 19 | \n",
+ " 0 | \n",
+ " 14.547405 | \n",
+ "
\n",
+ " \n",
+ " | 2025-07-24 08:00:00 | \n",
+ " 3382.56 | \n",
+ " 3382.92 | \n",
+ " 3365.82 | \n",
+ " 3369.68 | \n",
+ " 54663 | \n",
+ " 19 | \n",
+ " 0 | \n",
+ " 14.818019 | \n",
+ "
\n",
+ " \n",
+ " | ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " | 2025-09-03 04:00:00 | \n",
+ " 3536.07 | \n",
+ " 3545.89 | \n",
+ " 3529.36 | \n",
+ " 3536.81 | \n",
+ " 59697 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 18.731740 | \n",
+ "
\n",
+ " \n",
+ " | 2025-09-03 08:00:00 | \n",
+ " 3536.82 | \n",
+ " 3541.19 | \n",
+ " 3526.93 | \n",
+ " 3539.99 | \n",
+ " 58476 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 19.107330 | \n",
+ "
\n",
+ " \n",
+ " | 2025-09-03 12:00:00 | \n",
+ " 3540.04 | \n",
+ " 3551.43 | \n",
+ " 3532.29 | \n",
+ " 3550.56 | \n",
+ " 63000 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 19.007235 | \n",
+ "
\n",
+ " \n",
+ " | 2025-09-03 16:00:00 | \n",
+ " 3550.60 | \n",
+ " 3572.57 | \n",
+ " 3549.38 | \n",
+ " 3572.43 | \n",
+ " 87375 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 18.985718 | \n",
+ "
\n",
+ " \n",
+ " | 2025-09-03 20:00:00 | \n",
+ " 3572.45 | \n",
+ " 3572.98 | \n",
+ " 3570.24 | \n",
+ " 3572.12 | \n",
+ " 4428 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 18.713310 | \n",
+ "
\n",
+ " \n",
+ "
\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",
+ " time | \n",
+ " open | \n",
+ " high | \n",
+ " low | \n",
+ " close | \n",
+ " tick_volume | \n",
+ " spread | \n",
+ " real_volume | \n",
+ " ema21 | \n",
+ " ema50 | \n",
+ " rsi9 | \n",
+ " rsi14 | \n",
+ " trend | \n",
+ " atr | \n",
+ " adx | \n",
+ " fast_signal | \n",
+ " standard_signal | \n",
+ " optimized_signal | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " 2025-08-27 07:45:00 | \n",
+ " 3374.93 | \n",
+ " 3375.85 | \n",
+ " 3373.94 | \n",
+ " 3374.93 | \n",
+ " 2467 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 3374.930000 | \n",
+ " 3374.930000 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 3376.087631 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " 2025-08-27 08:00:00 | \n",
+ " 3374.91 | \n",
+ " 3376.21 | \n",
+ " 3374.11 | \n",
+ " 3374.74 | \n",
+ " 2904 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 3374.803333 | \n",
+ " 3374.824444 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 3375.914101 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 2025-08-27 08:15:00 | \n",
+ " 3374.73 | \n",
+ " 3377.46 | \n",
+ " 3374.21 | \n",
+ " 3375.77 | \n",
+ " 2313 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 3375.355714 | \n",
+ " 3375.211967 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 3375.933879 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 2025-08-27 08:30:00 | \n",
+ " 3375.78 | \n",
+ " 3378.81 | \n",
+ " 3375.69 | \n",
+ " 3377.69 | \n",
+ " 2745 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 3376.600667 | \n",
+ " 3376.051409 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 3376.121647 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " 2025-08-27 08:45:00 | \n",
+ " 3377.68 | \n",
+ " 3378.88 | \n",
+ " 3375.85 | \n",
+ " 3377.23 | \n",
+ " 2374 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 3376.925484 | \n",
+ " 3376.402013 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 3376.452085 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " | 495 | \n",
+ " 2025-09-03 19:15:00 | \n",
+ " 3565.40 | \n",
+ " 3568.01 | \n",
+ " 3564.18 | \n",
+ " 3567.83 | \n",
+ " 3848 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 3566.195399 | \n",
+ " 3562.948376 | \n",
+ " 71.921940 | \n",
+ " 69.332849 | \n",
+ " 3568.219300 | \n",
+ " 5.677877 | \n",
+ " 31.169524 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 496 | \n",
+ " 2025-09-03 19:30:00 | \n",
+ " 3567.83 | \n",
+ " 3569.42 | \n",
+ " 3566.97 | \n",
+ " 3569.01 | \n",
+ " 3442 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 3567.602699 | \n",
+ " 3564.160701 | \n",
+ " 73.431485 | \n",
+ " 70.341690 | \n",
+ " 3569.360376 | \n",
+ " 5.447314 | \n",
+ " 32.165951 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 497 | \n",
+ " 2025-09-03 19:45:00 | \n",
+ " 3569.01 | \n",
+ " 3572.57 | \n",
+ " 3568.59 | \n",
+ " 3572.43 | \n",
+ " 3585 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 3570.016350 | \n",
+ " 3565.814561 | \n",
+ " 77.394221 | \n",
+ " 73.103386 | \n",
+ " 3570.468641 | \n",
+ " 5.342506 | \n",
+ " 33.517576 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 498 | \n",
+ " 2025-09-03 20:00:00 | \n",
+ " 3572.45 | \n",
+ " 3572.98 | \n",
+ " 3570.24 | \n",
+ " 3572.22 | \n",
+ " 3806 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 3571.118175 | \n",
+ " 3567.095649 | \n",
+ " 76.604942 | \n",
+ " 72.656004 | \n",
+ " 3571.539564 | \n",
+ " 5.156613 | \n",
+ " 34.825121 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 499 | \n",
+ " 2025-09-03 20:15:00 | \n",
+ " 3572.26 | \n",
+ " 3572.68 | \n",
+ " 3571.43 | \n",
+ " 3572.06 | \n",
+ " 1092 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 3571.589087 | \n",
+ " 3568.088519 | \n",
+ " 75.941120 | \n",
+ " 72.292990 | \n",
+ " 3572.568615 | \n",
+ " 4.877569 | \n",
+ " 36.039270 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ "
\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
+}
diff --git a/TradingBot_V1.ipynb b/TradingBot_V1.ipynb
new file mode 100644
index 0000000..99651ac
--- /dev/null
+++ b/TradingBot_V1.ipynb
@@ -0,0 +1,2060 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Import Libaries"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#!pip install ta_lib-0.6.5-cp311-cp311-win_amd64.whl"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#%pip install talib"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "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": 9,
+ "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": 10,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 10,
+ "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": 11,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'trading-demo'"
+ ]
+ },
+ "execution_count": 11,
+ "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": 12,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pause_trading = 0\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "symbols = ['XAUUSD']\n",
+ "#symbols = ['BTCUSD']\n",
+ "\n",
+ "#'BTCUSD', 'ETHUSD', \n",
+ " #'XRPUSD', , 'EURNZD', 'EURUSD'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "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": 15,
+ "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': [ 'm5'],\n",
+ "\n",
+ " \n",
+ " 'EURUSD': ['h1', 'm30', 'm15', 'm5', 'm1'],\n",
+ "\n",
+ "\n",
+ " 'EURNZD': ['m5', 'm2', 'm1'],\n",
+ "\n",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "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": 17,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "{'XAUUSD': 0.93}\n",
+ "XAUUSD 0.93 0.1\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "('XAUUSD',\n",
+ " 0.93,\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': ['m5'],\n",
+ " 'EURUSD': ['h1', 'm30', 'm15', 'm5', 'm1'],\n",
+ " 'EURNZD': ['m5', 'm2', 'm1']})"
+ ]
+ },
+ "execution_count": 17,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "get_symbol()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "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": 19,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "{'XAUUSD': 0.93}\n",
+ "XAUUSD 0.93 0.1\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "('XAUUSD',\n",
+ " 0.93,\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': ['m5'],\n",
+ " 'EURUSD': ['h1', 'm30', 'm15', 'm5', 'm1'],\n",
+ " 'EURNZD': ['m5', 'm2', 'm1']})"
+ ]
+ },
+ "execution_count": 19,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "get_symbol()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "{'XAUUSD': 0.93}\n",
+ "XAUUSD 0.93 0.1\n"
+ ]
+ }
+ ],
+ "source": [
+ "set_symbol()\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 21,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "('XAUUSD', 0.1, 0)"
+ ]
+ },
+ "execution_count": 21,
+ "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": 22,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0"
+ ]
+ },
+ "execution_count": 22,
+ "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": 23,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "()\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": 25,
+ "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": 26,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "debug = False"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 27,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "trend_dict = {\n",
+ " 'm5': '',\n",
+ " #'m10': '',\n",
+ " #'m15': '',\n",
+ " #'m30': '',\n",
+ " #'h4': '',\n",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 28,
+ "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",
+ "}\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": 29,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "{'m5': ''}\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(trend_dict)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 30,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def get_rates(periode):\n",
+ "\n",
+ " global symbol\n",
+ "\n",
+ " ohlc = mt.copy_rates_from_pos(symbol, timeframes_dict[periode], 0, 300)\n",
+ " df = pd.DataFrame(ohlc)\n",
+ " df['time']=pd.to_datetime(df['time'], unit='s')\n",
+ "\n",
+ " #df = df[[\"time\",\"open\",\"high\",\"low\",\"close\"]]\n",
+ "\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",
+ " ## Take the rolling atr so the yaxis doesn't shake too much \n",
+ " df[\"atr\"] = ta.atr(high=df.high, low=df.low, close=df.close)\n",
+ " df[\"atr\"] = df.atr.rolling(window=30).mean()\n",
+ "\n",
+ "\n",
+ " df.set_index(\"time\", inplace = True)\n",
+ "\n",
+ " return df"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 31,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " open | \n",
+ " high | \n",
+ " low | \n",
+ " close | \n",
+ " tick_volume | \n",
+ " spread | \n",
+ " real_volume | \n",
+ " atr | \n",
+ "
\n",
+ " \n",
+ " | time | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 2025-08-28 22:00:00 | \n",
+ " 3420.04 | \n",
+ " 3420.35 | \n",
+ " 3419.77 | \n",
+ " 3419.85 | \n",
+ " 1045 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " | 2025-08-28 22:05:00 | \n",
+ " 3419.82 | \n",
+ " 3420.01 | \n",
+ " 3418.74 | \n",
+ " 3418.90 | \n",
+ " 1057 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " | 2025-08-28 22:10:00 | \n",
+ " 3418.93 | \n",
+ " 3419.20 | \n",
+ " 3418.27 | \n",
+ " 3418.62 | \n",
+ " 1003 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " | 2025-08-28 22:15:00 | \n",
+ " 3418.62 | \n",
+ " 3419.81 | \n",
+ " 3418.55 | \n",
+ " 3419.69 | \n",
+ " 1218 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " | 2025-08-28 22:20:00 | \n",
+ " 3419.67 | \n",
+ " 3420.01 | \n",
+ " 3419.15 | \n",
+ " 3419.17 | \n",
+ " 956 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " | ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " | 2025-08-29 23:35:00 | \n",
+ " 3447.78 | \n",
+ " 3448.55 | \n",
+ " 3447.18 | \n",
+ " 3448.21 | \n",
+ " 546 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 1.968904 | \n",
+ "
\n",
+ " \n",
+ " | 2025-08-29 23:40:00 | \n",
+ " 3448.21 | \n",
+ " 3449.35 | \n",
+ " 3447.78 | \n",
+ " 3449.17 | \n",
+ " 421 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 1.961315 | \n",
+ "
\n",
+ " \n",
+ " | 2025-08-29 23:45:00 | \n",
+ " 3449.15 | \n",
+ " 3449.18 | \n",
+ " 3447.64 | \n",
+ " 3447.90 | \n",
+ " 578 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 1.955341 | \n",
+ "
\n",
+ " \n",
+ " | 2025-08-29 23:50:00 | \n",
+ " 3447.86 | \n",
+ " 3448.36 | \n",
+ " 3447.68 | \n",
+ " 3448.22 | \n",
+ " 467 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 1.947173 | \n",
+ "
\n",
+ " \n",
+ " | 2025-08-29 23:55:00 | \n",
+ " 3448.20 | \n",
+ " 3448.91 | \n",
+ " 3447.97 | \n",
+ " 3448.87 | \n",
+ " 228 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 1.938756 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
300 rows × 8 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " open high low close tick_volume spread \\\n",
+ "time \n",
+ "2025-08-28 22:00:00 3420.04 3420.35 3419.77 3419.85 1045 20 \n",
+ "2025-08-28 22:05:00 3419.82 3420.01 3418.74 3418.90 1057 20 \n",
+ "2025-08-28 22:10:00 3418.93 3419.20 3418.27 3418.62 1003 20 \n",
+ "2025-08-28 22:15:00 3418.62 3419.81 3418.55 3419.69 1218 20 \n",
+ "2025-08-28 22:20:00 3419.67 3420.01 3419.15 3419.17 956 20 \n",
+ "... ... ... ... ... ... ... \n",
+ "2025-08-29 23:35:00 3447.78 3448.55 3447.18 3448.21 546 20 \n",
+ "2025-08-29 23:40:00 3448.21 3449.35 3447.78 3449.17 421 20 \n",
+ "2025-08-29 23:45:00 3449.15 3449.18 3447.64 3447.90 578 20 \n",
+ "2025-08-29 23:50:00 3447.86 3448.36 3447.68 3448.22 467 20 \n",
+ "2025-08-29 23:55:00 3448.20 3448.91 3447.97 3448.87 228 20 \n",
+ "\n",
+ " real_volume atr \n",
+ "time \n",
+ "2025-08-28 22:00:00 0 NaN \n",
+ "2025-08-28 22:05:00 0 NaN \n",
+ "2025-08-28 22:10:00 0 NaN \n",
+ "2025-08-28 22:15:00 0 NaN \n",
+ "2025-08-28 22:20:00 0 NaN \n",
+ "... ... ... \n",
+ "2025-08-29 23:35:00 0 1.968904 \n",
+ "2025-08-29 23:40:00 0 1.961315 \n",
+ "2025-08-29 23:45:00 0 1.955341 \n",
+ "2025-08-29 23:50:00 0 1.947173 \n",
+ "2025-08-29 23:55:00 0 1.938756 \n",
+ "\n",
+ "[300 rows x 8 columns]"
+ ]
+ },
+ "execution_count": 31,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "get_rates('m5')"
+ ]
+ },
+ {
+ "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": 32,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def get_trend(period):\n",
+ "\n",
+ " global trend_dict, periods_dict, symbol, debug\n",
+ "\n",
+ " #current_periods = periods_dict[symbol][0]\n",
+ "\n",
+ " df2 = get_rates(period).iloc[-200:]\n",
+ "\n",
+ " df2[\"close_smooth\"] = savgol_filter(df2.close, 25, 5)\n",
+ "\n",
+ " fig, ax = plt.subplots()\n",
+ " plt.xticks(rotation=-30)\n",
+ " price, = ax.plot(df2.index, df2.close, c='grey', lw=2, alpha=0.5, zorder=5)\n",
+ " price_smooth, = ax.plot(df2.index, df2.close_smooth, c='b', lw=2, zorder=5)\n",
+ "\n",
+ " atr = df2.atr.iloc[-1] # all the first atrs are NaN\n",
+ "\n",
+ " peaks_idx, _ = find_peaks(df2.close_smooth, distance = 1, \n",
+ " width = 2, prominence=atr)\n",
+ "\n",
+ " troughs_idx, _ = find_peaks(-1*df2.close_smooth, distance = 1, \n",
+ " width = 2, prominence=atr)\n",
+ "\n",
+ " \n",
+ "\n",
+ " peaks, = ax.plot(df2.index[peaks_idx], df2.close_smooth.iloc[peaks_idx], \\\n",
+ " c=\"r\", linestyle='None', markersize = 10.0, marker = \"o\", zorder=10)\n",
+ "\n",
+ " troughs, = ax.plot(df2.index[troughs_idx], df2.close_smooth.iloc[troughs_idx], \\\n",
+ " c=\"g\", linestyle='None', markersize = 10.0, marker = \"o\", zorder=10)\n",
+ "\n",
+ "\n",
+ " plt.show()\n",
+ "\n",
+ " #print(peaks_idx[-1], troughs_idx[-1])\n",
+ "\n",
+ " if peaks_idx[-1] > troughs_idx[-1]:\n",
+ " print(\"downtrend\")\n",
+ "\n",
+ " trend_dict[period] = 'downtrend'\n",
+ " else:\n",
+ " print(\"uptrend\")\n",
+ "\n",
+ " trend_dict[period] = 'uptrend'\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 33,
+ "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": 57,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'downtrend'"
+ ]
+ },
+ "execution_count": 57,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "get_trend_fast('m5')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 35,
+ "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": 56,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "m5\n",
+ "Pause Trading: 1\n"
+ ]
+ }
+ ],
+ "source": [
+ "set_trend()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Set Trend manually"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pause_trading, trend_dict, periods_dict, symbols[0]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 36,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "m5\n",
+ "m5 uptrend\n",
+ "Pause Trading: 0\n"
+ ]
+ }
+ ],
+ "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": [
+ "(['m5'], 0)"
+ ]
+ },
+ "execution_count": 38,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "periods_dict[symbol], pause_trading"
+ ]
+ },
+ {
+ "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": null,
+ "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",
+ "\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": null,
+ "metadata": {},
+ "outputs": [],
+ "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()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Generate signals"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 48,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def get_mt5_data(symbol=symbol, timeframe=mt.TIMEFRAME_M5, 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": 39,
+ "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['m5']\n",
+ " }\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 49,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def generate_signal(df = get_mt5_data(symbol=symbol, timeframe=timeframes_dict['m5']), 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": 58,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " time | \n",
+ " open | \n",
+ " high | \n",
+ " low | \n",
+ " close | \n",
+ " tick_volume | \n",
+ " spread | \n",
+ " real_volume | \n",
+ " ema21 | \n",
+ " ema50 | \n",
+ " rsi9 | \n",
+ " rsi14 | \n",
+ " trend | \n",
+ " atr | \n",
+ " adx | \n",
+ " fast_signal | \n",
+ " standard_signal | \n",
+ " optimized_signal | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " 2025-08-28 05:25:00 | \n",
+ " 3386.52 | \n",
+ " 3386.74 | \n",
+ " 3385.71 | \n",
+ " 3386.64 | \n",
+ " 714 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 3386.640000 | \n",
+ " 3386.640000 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 3385.220875 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " 2025-08-28 05:30:00 | \n",
+ " 3386.75 | \n",
+ " 3386.98 | \n",
+ " 3385.81 | \n",
+ " 3385.85 | \n",
+ " 985 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 3386.113333 | \n",
+ " 3386.201111 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 3386.775285 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 2025-08-28 05:35:00 | \n",
+ " 3385.86 | \n",
+ " 3387.38 | \n",
+ " 3384.59 | \n",
+ " 3387.17 | \n",
+ " 1151 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 3386.717143 | \n",
+ " 3386.598197 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 3388.065491 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 2025-08-28 05:40:00 | \n",
+ " 3387.12 | \n",
+ " 3388.36 | \n",
+ " 3386.82 | \n",
+ " 3388.18 | \n",
+ " 798 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 3387.497333 | \n",
+ " 3387.134038 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 3389.112151 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " 2025-08-28 05:45:00 | \n",
+ " 3388.16 | \n",
+ " 3390.56 | \n",
+ " 3387.94 | \n",
+ " 3390.46 | \n",
+ " 947 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 3389.026452 | \n",
+ " 3388.123436 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 3389.935928 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " | 495 | \n",
+ " 2025-08-29 23:40:00 | \n",
+ " 3448.21 | \n",
+ " 3449.35 | \n",
+ " 3447.78 | \n",
+ " 3449.17 | \n",
+ " 421 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 3448.743230 | \n",
+ " 3448.456881 | \n",
+ " 56.591716 | \n",
+ " 56.452748 | \n",
+ " 3448.267585 | \n",
+ " 2.002968 | \n",
+ " 15.874639 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 496 | \n",
+ " 2025-08-29 23:45:00 | \n",
+ " 3449.15 | \n",
+ " 3449.18 | \n",
+ " 3447.64 | \n",
+ " 3447.90 | \n",
+ " 578 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 3448.321615 | \n",
+ " 3448.345505 | \n",
+ " 50.150670 | \n",
+ " 52.209309 | \n",
+ " 3447.941698 | \n",
+ " 1.969899 | \n",
+ " 15.547755 | \n",
+ " -1 | \n",
+ " -1 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 497 | \n",
+ " 2025-08-29 23:50:00 | \n",
+ " 3447.86 | \n",
+ " 3448.36 | \n",
+ " 3447.68 | \n",
+ " 3448.22 | \n",
+ " 467 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 3448.270808 | \n",
+ " 3448.320404 | \n",
+ " 51.708684 | \n",
+ " 53.164605 | \n",
+ " 3447.570685 | \n",
+ " 1.877764 | \n",
+ " 15.244220 | \n",
+ " -1 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 498 | \n",
+ " 2025-08-29 23:55:00 | \n",
+ " 3448.20 | \n",
+ " 3448.91 | \n",
+ " 3447.97 | \n",
+ " 3448.87 | \n",
+ " 228 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 3448.570404 | \n",
+ " 3448.430323 | \n",
+ " 54.927801 | \n",
+ " 55.126747 | \n",
+ " 3447.156651 | \n",
+ " 1.810780 | \n",
+ " 15.232676 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 499 | \n",
+ " 2025-09-01 01:00:00 | \n",
+ " 3444.73 | \n",
+ " 3449.27 | \n",
+ " 3444.67 | \n",
+ " 3445.14 | \n",
+ " 245 | \n",
+ " 20 | \n",
+ " 0 | \n",
+ " 3446.855202 | \n",
+ " 3447.772258 | \n",
+ " 38.401814 | \n",
+ " 43.789528 | \n",
+ " 3446.701703 | \n",
+ " 2.010010 | \n",
+ " 14.843679 | \n",
+ " -1 | \n",
+ " -1 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
500 rows × 18 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " time open high low close tick_volume \\\n",
+ "0 2025-08-28 05:25:00 3386.52 3386.74 3385.71 3386.64 714 \n",
+ "1 2025-08-28 05:30:00 3386.75 3386.98 3385.81 3385.85 985 \n",
+ "2 2025-08-28 05:35:00 3385.86 3387.38 3384.59 3387.17 1151 \n",
+ "3 2025-08-28 05:40:00 3387.12 3388.36 3386.82 3388.18 798 \n",
+ "4 2025-08-28 05:45:00 3388.16 3390.56 3387.94 3390.46 947 \n",
+ ".. ... ... ... ... ... ... \n",
+ "495 2025-08-29 23:40:00 3448.21 3449.35 3447.78 3449.17 421 \n",
+ "496 2025-08-29 23:45:00 3449.15 3449.18 3447.64 3447.90 578 \n",
+ "497 2025-08-29 23:50:00 3447.86 3448.36 3447.68 3448.22 467 \n",
+ "498 2025-08-29 23:55:00 3448.20 3448.91 3447.97 3448.87 228 \n",
+ "499 2025-09-01 01:00:00 3444.73 3449.27 3444.67 3445.14 245 \n",
+ "\n",
+ " spread real_volume ema21 ema50 rsi9 rsi14 \\\n",
+ "0 20 0 3386.640000 3386.640000 NaN NaN \n",
+ "1 20 0 3386.113333 3386.201111 NaN NaN \n",
+ "2 20 0 3386.717143 3386.598197 NaN NaN \n",
+ "3 20 0 3387.497333 3387.134038 NaN NaN \n",
+ "4 20 0 3389.026452 3388.123436 NaN NaN \n",
+ ".. ... ... ... ... ... ... \n",
+ "495 20 0 3448.743230 3448.456881 56.591716 56.452748 \n",
+ "496 20 0 3448.321615 3448.345505 50.150670 52.209309 \n",
+ "497 20 0 3448.270808 3448.320404 51.708684 53.164605 \n",
+ "498 20 0 3448.570404 3448.430323 54.927801 55.126747 \n",
+ "499 20 0 3446.855202 3447.772258 38.401814 43.789528 \n",
+ "\n",
+ " trend atr adx fast_signal standard_signal \\\n",
+ "0 3385.220875 NaN NaN 0 0 \n",
+ "1 3386.775285 NaN NaN 0 0 \n",
+ "2 3388.065491 NaN NaN 0 0 \n",
+ "3 3389.112151 NaN NaN 0 0 \n",
+ "4 3389.935928 NaN NaN 0 0 \n",
+ ".. ... ... ... ... ... \n",
+ "495 3448.267585 2.002968 15.874639 1 0 \n",
+ "496 3447.941698 1.969899 15.547755 -1 -1 \n",
+ "497 3447.570685 1.877764 15.244220 -1 0 \n",
+ "498 3447.156651 1.810780 15.232676 1 0 \n",
+ "499 3446.701703 2.010010 14.843679 -1 -1 \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": 58,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "generate_signal()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 51,
+ "metadata": {},
+ "outputs": [],
+ "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": 52,
+ "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": "markdown",
+ "metadata": {},
+ "source": [
+ "### Get M5 Trade Signals"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "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):\n",
+ " \"\"\"\n",
+ " M5 Trade Signal mit dynamischem Seitwärtsfilter + dynamischer RRR-Berechnung:\n",
+ " - ATR-Minimum prüft ob Markt volatil genug ist\n",
+ " - Linear Regression ersetzt Savitzky-Golay für Trenddetektion\n",
+ " - adaptive Filterung nach ATR und Trend-Slope\n",
+ " - dynamisches RRR (Chance-Risiko-Verhältnis) auf Basis von ATR + Slope\n",
+ " \"\"\"\n",
+ "\n",
+ " global trend_dict, periods_dict, pause_trading, volume_dict\n",
+ " set_trend()\n",
+ "\n",
+ " # if pause_trading == 1:\n",
+ " # pos = mt.positions_total()\n",
+ " # if pos > 0:\n",
+ " # open_positions = mt.positions_get()\n",
+ " # print(f\"⚠️ Trading pausiert, offene Positionen auf {symbol} werden geschlossen...\")\n",
+ " # for pos in open_positions:\n",
+ " # market_order(symbol, volume_dict[symbol], \"sell\")\n",
+ " # return {\"signal\": 0, \"reason\": \"Trading paused\"}\n",
+ "\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",
+ " if atr < atr_min:\n",
+ " return {\"signal\": 0, \"reason\": \"ATR too low → sideways\"}\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",
+ " if abs(slope_long) < slope_threshold and abs(slope_short) < slope_threshold:\n",
+ " return {\"signal\": 0, \"reason\": \"Trend flat → sideways\"}\n",
+ "\n",
+ " # --- Trendlogik ---\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",
+ " # --- 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",
+ " print(f\"[RRR-DEBUG] ATR_norm={atr_norm:.5f} | slope_strength={slope_strength:.5f} | \"\n",
+ " f\"rrr_vol={rrr_from_vol:.2f} | rrr_slope={rrr_from_slope:.2f} | FINAL_RRR={rrr:.2f}\")\n",
+ "\n",
+ " # --- Signale ---\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",
+ " 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",
+ " 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",
+ " # --- SL/TP sowohl mit ATR als auch mit Gewinn-Trailing\n",
+ " # manage_open_trades()\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",
+ " # --- 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",
+ " }\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 60,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "m5\n",
+ "Pause Trading: 1\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "{'signal': 0, 'reason': 'Trading paused'}"
+ ]
+ },
+ "execution_count": 60,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "get_m5_trade_signals()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "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
+}
diff --git a/retracementLevel.ipynb b/retracementLevel.ipynb
index 24e4e51..7cff116 100644
--- a/retracementLevel.ipynb
+++ b/retracementLevel.ipynb
@@ -88,6 +88,7 @@
"outputs": [],
"source": [
"symbols = ['XAUUSD']\n",
+ "#symbols = ['BTCUSD']\n",
"\n",
"#'BTCUSD', 'ETHUSD', \n",
" #'XRPUSD', , 'EURNZD', 'EURUSD'"
@@ -517,7 +518,7 @@
"def get_supres_signal(period: str):\n",
"\n",
"\n",
- " ohlc = mt.copy_rates_from_pos(symbol, timeframes_dict[period], 0, 50)\n",
+ " ohlc = mt.copy_rates_from_pos(symbol, timeframes_dict[period], 0, 120)\n",
" df = pd.DataFrame(ohlc)\n",
" df['time']=pd.to_datetime(df['time'], unit='s')\n",
"\n",
@@ -530,14 +531,18 @@
" df.resistance.fillna(0, inplace=True)\n",
" df = df[(df.support != 0) | (df.resistance != 0)]\n",
"\n",
- " if df.resistance.iloc[-1] != 0:\n",
+ " if df.resistance.iloc[-1] != 0 or df.ma3.iloc[-1] > df.close.iloc[-1]:\n",
" signal = 'sell'\n",
" print(f'sell at: {df.resistance.iloc[-1]}')\n",
- " elif df.support.iloc[-1] !=0:\n",
+ " elif df.support.iloc[-1] !=0 or df.ma3.iloc[-1] < df.close.iloc[-1]:\n",
" signal = 'buy'\n",
" print(f'buy at: {df.support.iloc[-1]}')\n",
+ " else:\n",
+ " signal = 'none'\n",
"\n",
" return signal\n",
+ "\n",
+ "\n",
"\n"
]
},
@@ -547,7 +552,7 @@
"metadata": {},
"outputs": [],
"source": [
- "get_supres_signal('m30')"
+ "get_supres_signal('m15')"
]
},
{
@@ -839,7 +844,7 @@
"source": [
"def decide_order():\n",
"\n",
- " global symbol, volume_dict, periods_dict\n",
+ " global symbol, volume_dict, periods_dict, trend_dict\n",
" \n",
"\n",
" ## SMA Version 2\n",
@@ -849,18 +854,44 @@
" for ts in tsignals:\n",
" sma_signals = get_sma(ts)\n",
"\n",
- " supress_signal = get_supres_signal(ts)\n",
- " print(f\"surpress Signal: {supress_signal}\")\n",
- " signals.append(supress_signal)\n",
- " \n",
- " if sma_signals.buy.iloc[-1] == 1: #sma_signals.diff5.tail(2).sum() > 0: \n",
- " print(ts, 'buy', sma_signals.diff5.tail(2).sum(), sma_signals.diff10.tail(2).sum())\n",
+ "\n",
+ " if sma_signals.buy.iloc[-1] == 1 and sma_signals.sell.iloc[-1] != 1:\n",
+ " print(sma_signals.buy.iloc[-1] )\n",
" signals.append('buy')\n",
+ " elif sma_signals.sell.iloc[-1] == 1 and sma_signals.buy.iloc[-1] != 1:\n",
+ " print(sma_signals.sell.iloc[-1])\n",
+ " signals.append('sell')\n",
" else:\n",
- " print(ts, 'sell', sma_signals.diff5.tail(2).sum(), sma_signals.diff10.tail(2).sum())\n",
" signals.append('sell')\n",
"\n",
- " \n",
+ " # support resistance signal\n",
+ " # supress_signal = get_supres_signal(ts)\n",
+ " # if supress_signal != 'none':\n",
+ " # print(f\"surpress Signal: {supress_signal}\")\n",
+ " # signals.append(supress_signal)\n",
+ "\n",
+ " # if sma_signals.ma10.iloc[-1] < sma_signals.close.iloc[-1]: # or sma_signals.buy.iloc[-1] == 1: #sma_signals.diff5.tail(2).sum() > 0: # and sma_signals.buy.iloc[-1] == 1:\n",
+ " # #print(ts, 'buy', sma_signals.ma10.iloc[-1], sma_signals.close.iloc[-1])\n",
+ " # signals.append('buy')\n",
+ " # elif sma_signals.ma10.iloc[-1] > sma_signals.close.iloc[-1]: # or sma_signals.sell.iloc[-1] == 1:\n",
+ " # #print(ts, 'sell', sma_signals.ma10.iloc[-1], sma_signals.close.iloc[-1])\n",
+ " # signals.append('sell')\n",
+ " \n",
+ " # if sma_signals.ma10.iloc[-1] < sma_signals.ma5.iloc[-1]:# or sma_signals.buy.iloc[-1] == 1: #sma_signals.diff5.tail(2).sum() > 0: # and sma_signals.buy.iloc[-1] == 1:\n",
+ " # print(ts, 'buy', sma_signals.ma10.iloc[-1], sma_signals.ma5.iloc[-1])\n",
+ " # signals.append('buy')\n",
+ " # elif sma_signals.ma10.iloc[-1] > sma_signals.ma5.iloc[-1]: # or sma_signals.sell.iloc[-1] == 1:\n",
+ " # print(ts, 'sell', sma_signals.ma10.iloc[-1], sma_signals.ma5.iloc[-1])\n",
+ " # signals.append('sell')\n",
+ "\n",
+ " current_period = periods_dict[symbol]\n",
+ " if trend_dict[current_period[0]] == 'uptrend':\n",
+ " signals.append('buy')\n",
+ " #signals.append('buy')\n",
+ " elif trend_dict[current_period[0]] == 'downtrend':\n",
+ " signals.append('sell')\n",
+ " #signals.append('sell')\n",
+ "\n",
"\n",
" cbuy = signals.count('buy')\n",
" csell = signals.count('sell')\n",
@@ -869,7 +900,7 @@
" if cbuy > csell:\n",
" signal = 'buy'\n",
" print(signal)\n",
- " else:\n",
+ " elif cbuy <= csell:\n",
" signal = 'sell'\n",
" print(signal)\n",
"\n",
@@ -963,6 +994,13 @@
"# Trend Detection"
]
},
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## timefame & trend dictionary"
+ ]
+ },
{
"cell_type": "code",
"execution_count": null,
@@ -970,9 +1008,11 @@
"outputs": [],
"source": [
"trend_dict = {\n",
- " 'm5': '',\n",
+ " #'m5': '',\n",
+ " #'m10': '',\n",
" 'm15': '',\n",
" #'m30': '',\n",
+ " #'h4': '',\n",
"}"
]
},
@@ -991,6 +1031,7 @@
" 'm20': mt.TIMEFRAME_M20,\n",
" 'm30': mt.TIMEFRAME_M30,\n",
" 'h1': mt.TIMEFRAME_H1,\n",
+ " 'h4': mt.TIMEFRAME_H4,\n",
"}\n",
"\n",
"\n",
@@ -1025,7 +1066,7 @@
"\n",
" global symbol\n",
"\n",
- " ohlc = mt.copy_rates_from_pos(symbol, timeframes_dict[periode], 0, 200)\n",
+ " ohlc = mt.copy_rates_from_pos(symbol, timeframes_dict[periode], 0, 300)\n",
" df = pd.DataFrame(ohlc)\n",
" df['time']=pd.to_datetime(df['time'], unit='s')\n",
"\n",
@@ -1046,6 +1087,17 @@
" return df"
]
},
+ {
+ "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": null,
@@ -1069,10 +1121,10 @@
"\n",
" atr = df2.atr.iloc[-1] # all the first atrs are NaN\n",
"\n",
- " peaks_idx, _ = find_peaks(df2.close_smooth, distance = 15, \n",
+ " peaks_idx, _ = find_peaks(df2.close_smooth, distance = 2, \n",
" width = 3, prominence=atr)\n",
"\n",
- " troughs_idx, _ = find_peaks(-1*df2.close_smooth, distance = 15, \n",
+ " troughs_idx, _ = find_peaks(-1*df2.close_smooth, distance = 2, \n",
" width = 3, prominence=atr)\n",
"\n",
" peaks, = ax.plot(df2.index[peaks_idx], df2.close_smooth.iloc[peaks_idx], \\\n",
@@ -1096,6 +1148,15 @@
"\n"
]
},
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "get_trend('m15')"
+ ]
+ },
{
"cell_type": "code",
"execution_count": null,
@@ -1135,14 +1196,26 @@
"metadata": {},
"outputs": [],
"source": [
- "pause_trading, trend_dict, periods_dict"
+ "pause_trading, trend_dict, periods_dict, symbols[0]"
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 1,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "ename": "NameError",
+ "evalue": "name 'set_trend' is not defined",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)",
+ "Cell \u001b[1;32mIn[1], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m set_trend()\n",
+ "\u001b[1;31mNameError\u001b[0m: name 'set_trend' is not defined"
+ ]
+ }
+ ],
"source": [
"set_trend()"
]
@@ -1153,7 +1226,7 @@
"metadata": {},
"outputs": [],
"source": [
- "trend_dict"
+ "trend_dict[periods_dict[symbol][0]]"
]
},
{
@@ -1191,6 +1264,7 @@
"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",
"\n",
"#scheduler.add_job(export_marketview, 'cron', year=\"*\", month='*', day_of_week='mon, tue, wed; thu, fri', hour='8-22', minute=00)\n",
@@ -1284,29 +1358,29 @@
" df = pd.DataFrame(sma)\n",
" df['time']=pd.to_datetime(df['time'], unit='s')\n",
" df['ma5'] = df['close'].rolling(3).mean()\n",
- " df['ma10'] = df['close'].rolling(15).mean()\n",
+ " df['ma10'] = df['close'].rolling(5).mean()\n",
" df['diffclose'] = df['close'].diff()\n",
" df['diff5'] = df['ma5'].diff()\n",
" df['diff10'] = df['ma10'].diff()\n",
- " df['ema'] = df['close'].ewm(span=14, adjust=False).mean()\n",
+ " df['ema'] = df['close'].ewm(span=5, adjust=False).mean()\n",
"\n",
"\n",
- " support = df[df.low == df.low.rolling(5, center=True).min()].low\n",
- " resistance = df[df.high == df.high.rolling(5, center=True).max()].high\n",
+ " support = df[df.low == df.low.rolling(3, center=True).min()].low\n",
+ " resistance = df[df.high == df.high.rolling(3, center=True).max()].high\n",
" df['resistance'] = resistance\n",
" df['support'] = support\n",
" df.support.fillna(0, inplace=True)\n",
" df.resistance.fillna(0, inplace=True)\n",
" df.dropna()\n",
- " df = df[['time','open', 'close', 'low', 'ma5', 'ma10', 'diffclose','diff5', 'diff10', 'ema', 'resistance', 'support']]\n",
+ " #df = df[['time','open', 'close', 'low', 'ma5', 'ma10', 'diffclose','diff5', 'diff10', 'ema', 'resistance', 'support', 'atr']]\n",
"\n",
" buy = []\n",
" sell = []\n",
"\n",
" for i in range (len(df)):\n",
- " if df.ma5.iloc[i] > df.ema.iloc[i]: #and df.ma5[i-1] < df.ma10.iloc[i-1]:\n",
+ " if df.close.iloc[i] > df.ma5.iloc[i]: #> df.ma10.iloc[i]: #and df.ma5[i-1] < df.ma10.iloc[i-1]:\n",
" buy.append(i)\n",
- " elif df.ma5.iloc[i] < df.ema.iloc[i]: #and df.ma5[i-1] > df.ma10.iloc[i-1]:\n",
+ " elif df.close.iloc[i] < df.ma5.iloc[i]: #< df.ma10.iloc[i]: #and df.ma5[i-1] > df.ma10.iloc[i-1]:\n",
" sell.append(i)\n",
"\n",
" buy, sell\n",
@@ -1332,7 +1406,7 @@
"outputs": [],
"source": [
"sma = get_sma_dev('m15')\n",
- "sma.tail(50)\n"
+ "sma.tail(10)\n"
]
},
{
@@ -1341,8 +1415,20 @@
"metadata": {},
"outputs": [],
"source": [
- "periods_dict['XAUUSD']\n",
- "sma.close.tail(10)"
+ "df = sma\n",
+ "plt.figure(figsize=(12,5))\n",
+ "plt.plot(df['close'], label='Close Price', c='blue', alpha=0.5)\n",
+ "plt.plot(df['ma5'], label='MA5', c='r', alpha=0.9)\n",
+ "#plt.plot(df['ma10'], label='MA10', c='y', alpha=0.9)\n",
+ "plt.plot(df['ema'], label='EMA', c='green', alpha=0.9)\n",
+ "plt.scatter(df[df.buy == 1].index, df[df.buy == 1]['close'], marker='^', color='g', s=100)\n",
+ "plt.scatter(df[df.sell == 1].index, df[df.sell == 1]['close'], marker='v', color='r', s=100)\n",
+ "plt.scatter(df[df.support != 0].index, df[df.support != 0]['close'], marker='o', color='orange', s=100)\n",
+ "plt.scatter(df[df.resistance != 0].index, df[df.resistance != 0]['close'], marker='x', color='black', s=100)\n",
+ "\n",
+ "\n",
+ "plt.legend()\n",
+ "plt.show()"
]
},
{
@@ -1351,17 +1437,34 @@
"metadata": {},
"outputs": [],
"source": [
- "tsignals = ['m30', 'm15', 'm5', 'm1']\n",
+ "tsignals = ['m15']\n",
"signals = []\n",
"\n",
"for ts in tsignals:\n",
- " sma_signals = get_sma(ts)\n",
- " if sma_signals.diff5.tail(2).sum() > 0: # and sma_signals.buy.iloc[-1] == 1:\n",
- " print(ts, 'buy', sma_signals.diff5.tail(2).sum(), sma_signals.diff10.tail(2).sum())\n",
+ " sma_signals = get_sma_dev(ts)\n",
+ "\n",
+ " if sma_signals.buy.iloc[-1] == 1 and sma_signals.sell.iloc[-1] != 1:\n",
+ " print(sma_signals.buy.iloc[-1] )\n",
" signals.append('buy')\n",
- " else:\n",
- " print(ts, 'sell', sma_signals.diff5.tail(2).sum(), sma_signals.diff10.tail(2).sum())\n",
+ " elif sma_signals.sell.iloc[-1] == 1 and sma_signals.buy.iloc[-1] != 1:\n",
+ " print(sma_signals.sell.iloc[-1])\n",
" signals.append('sell')\n",
+ " else:\n",
+ " signals.append('sell')\n",
+ " \n",
+ " # if sma_signals.ma10.iloc[-1] < sma_signals.close.iloc[-1]:# or sma_signals.buy.iloc[-1] == 1: #sma_signals.diff5.tail(2).sum() > 0: # and sma_signals.buy.iloc[-1] == 1:\n",
+ " # print(ts, 'buy', sma_signals.ma10.iloc[-1], sma_signals.close.iloc[-1])\n",
+ " # signals.append('buy')\n",
+ " # elif sma_signals.ma10.iloc[-1] > sma_signals.close.iloc[-1]: # or sma_signals.sell.iloc[-1] == 1:\n",
+ " # print(ts, 'sell', sma_signals.ma10.iloc[-1], sma_signals.close.iloc[-1])\n",
+ " # signals.append('sell')\n",
+ "\n",
+ " # if sma_signals.ma10.iloc[-1] < sma_signals.ma5.iloc[-1]:# or sma_signals.buy.iloc[-1] == 1: #sma_signals.diff5.tail(2).sum() > 0: # and sma_signals.buy.iloc[-1] == 1:\n",
+ " # print(ts, 'buy', sma_signals.ma10.iloc[-1], sma_signals.ma5.iloc[-1])\n",
+ " # signals.append('buy')\n",
+ " # elif sma_signals.ma10.iloc[-1] > sma_signals.ma5.iloc[-1]: # or sma_signals.sell.iloc[-1] == 1:\n",
+ " # print(ts, 'sell', sma_signals.ma10.iloc[-1], sma_signals.ma5.iloc[-1])\n",
+ " # signals.append('sell')\n",
"\n",
"cbuy = signals.count('buy')\n",
"csell = signals.count('sell')\n",
@@ -1375,11 +1478,21 @@
" print(csell)\n",
"\n",
"\n",
- "signal\n",
+ "signal, signals\n",
"# sma_signals = get_sma('m15')\n",
"# df = sma_signals"
]
},
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "periods_dict['XAUUSD']\n",
+ "sma.close.tail(10)"
+ ]
+ },
{
"cell_type": "code",
"execution_count": null,
@@ -1406,24 +1519,6 @@
"\n"
]
},
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "df = sma\n",
- "plt.figure(figsize=(12,5))\n",
- "plt.plot(df['close'], label='Asset Price', c='blue', alpha=0.5)\n",
- "plt.plot(df['ma5'], label='MA5', c='r', alpha=0.9)\n",
- "plt.plot(df['ma10'], label='MA10', c='y', alpha=0.9)\n",
- "plt.plot(df['ema'], label='EMA', c='green', alpha=0.9)\n",
- "plt.scatter(df[df.buy == 1].index, df[df.buy == 1]['close'], marker='^', color='g', s=100)\n",
- "plt.scatter(df[df.sell == 1].index, df[df.sell == 1]['close'], marker='v', color='r', s=100)\n",
- "plt.legend()\n",
- "plt.show()"
- ]
- },
{
"cell_type": "code",
"execution_count": null,
@@ -1482,8 +1577,8 @@
"df['support'] = support\n",
"df.support.fillna(0, inplace=True)\n",
"df.resistance.fillna(0, inplace=True)\n",
- "df = df[(df.support != 0) | (df.resistance != 0)]\n",
- "df\n"
+ "#df = df[(df.support != 0) | (df.resistance != 0)]\n",
+ "df.tail(50)\n"
]
},
{
@@ -1492,14 +1587,16 @@
"metadata": {},
"outputs": [],
"source": [
- "if df.resistance.iloc[-1] != 0:\n",
+ "if df.resistance.iloc[-1] != 0 or df.ma3.iloc[-1] > df.close.iloc[-1]:\n",
" signal = 'sell'\n",
" print(f'sell at: {df.resistance.iloc[-1]}')\n",
- "elif df.support.iloc[-1] !=0:\n",
+ "elif df.support.iloc[-1] !=0 or df.ma3.iloc[-1] < df.close.iloc[-1]:\n",
" signal = 'buy'\n",
" print(f'buy at: {df.support.iloc[-1]}')\n",
"else:\n",
- " signal = 'none'\n"
+ " signal = 'none'\n",
+ "\n",
+ "print(signal)"
]
},
{