feat: Trading Bot V1.8 - Aggressive Mode + Infrastructure

## Major Features
- Session Filter: NY-only trading (13:00-21:00 UTC)
- SQLite Database: Structured trade logging
- Telegram Bot: Real-time notifications (@Xausd_digger_bot)
- Streamlit Dashboard: Visual monitoring & analytics
- JSON Import: Historical data migration

## Infrastructure
- trading_database.py: SQLite trade storage
- telegram_notifier.py: Telegram integration
- infrastructure_patch.py: Combined DB + Telegram
- trading_dashboard.py: Real-time web dashboard
- import_json_to_db.py: JSON to SQLite migration

## Session Filter (V1.8 Aggressive Mode)
- session_filter_patch.py: Whitelist-based filter
- Blocks: Asian, London, Overlap sessions
- Active: NY session only (best performance: 47.6% WR)
- Base confidence: 60%

## Documentation
- V1.8_AGGRESSIVE_MODE_AKTIVIERT.md
- FIX_DUPLICATE_SCHEDULER.md
- DASHBOARD_WINDOWS_SERVER.md
- SQLITE_TELEGRAM_SETUP.md
- PROJECT_CLEANUP.md

## Cleanup
- Archived old V1.1-V1.7 versions
- Removed obsolete analysis scripts (replaced by dashboard)
- Added .gitignore for secrets and temp files

## Breaking Changes
- Requires telegram_config.json (use template)
- Requires Python packages: streamlit, plotly

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
cbazzaandClaude committed 2025-11-26 21:14:01 +01:00
1 parent b61cb9b8f9
commit 596718e30b
64 files changed
+9944 -78909

No files matched your search

Vendored
BIN
View File
Binary file not shown.
+61
View File
@@ -0,0 +1,61 @@
# Secrets & Credentials
telegram_config.json
*.env
*.key
*.secret
# Database
*.db
*.sqlite
*.sqlite3
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
*.egg-info/
dist/
build/
# OS Files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
# IDE
.vscode/
.idea/
*.swp
*.swo
*~
# Logs
*.log
dashboard.log
dashboard_*.log
nohup.out
# Jupyter
.ipynb_checkpoints/
*.ipynb:Zone.Identifier
# Archive/Temp folders
archive/
archiv/
misc/
.goose/
temp/
tmp/
# Performance data (optional - keep template)
# Uncomment if you don't want to track trade data
# trade_performance_*.json
# Streamlit cache
.streamlit/
-771
View File
@@ -1,771 +0,0 @@
{
"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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>time</th>\n",
" <th>open</th>\n",
" <th>high</th>\n",
" <th>low</th>\n",
" <th>close</th>\n",
" <th>tick_volume</th>\n",
" <th>spread</th>\n",
" <th>real_volume</th>\n",
" <th>ema10</th>\n",
" <th>ema30</th>\n",
" <th>rsi</th>\n",
" <th>trend</th>\n",
" <th>signal</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>2025-07-17 04:30:00</td>\n",
" <td>3340.74</td>\n",
" <td>3341.46</td>\n",
" <td>3337.21</td>\n",
" <td>3338.04</td>\n",
" <td>1293</td>\n",
" <td>18</td>\n",
" <td>0</td>\n",
" <td>3338.040000</td>\n",
" <td>3338.040000</td>\n",
" <td>NaN</td>\n",
" <td>3338.208386</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2025-07-17 04:35:00</td>\n",
" <td>3338.03</td>\n",
" <td>3341.03</td>\n",
" <td>3337.72</td>\n",
" <td>3341.03</td>\n",
" <td>964</td>\n",
" <td>18</td>\n",
" <td>0</td>\n",
" <td>3339.684500</td>\n",
" <td>3339.584833</td>\n",
" <td>NaN</td>\n",
" <td>3340.377874</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>2025-07-17 04:40:00</td>\n",
" <td>3341.03</td>\n",
" <td>3341.48</td>\n",
" <td>3339.96</td>\n",
" <td>3341.26</td>\n",
" <td>944</td>\n",
" <td>18</td>\n",
" <td>0</td>\n",
" <td>3340.317841</td>\n",
" <td>3340.180848</td>\n",
" <td>NaN</td>\n",
" <td>3341.873882</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>2025-07-17 04:45:00</td>\n",
" <td>3341.27</td>\n",
" <td>3343.45</td>\n",
" <td>3341.27</td>\n",
" <td>3342.47</td>\n",
" <td>1099</td>\n",
" <td>18</td>\n",
" <td>0</td>\n",
" <td>3341.026881</td>\n",
" <td>3340.811593</td>\n",
" <td>NaN</td>\n",
" <td>3342.785860</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>2025-07-17 04:50:00</td>\n",
" <td>3342.47</td>\n",
" <td>3343.61</td>\n",
" <td>3342.20</td>\n",
" <td>3342.84</td>\n",
" <td>1070</td>\n",
" <td>18</td>\n",
" <td>0</td>\n",
" <td>3341.547378</td>\n",
" <td>3341.273104</td>\n",
" <td>NaN</td>\n",
" <td>3343.203260</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>495</th>\n",
" <td>2025-07-18 22:45:00</td>\n",
" <td>3349.29</td>\n",
" <td>3349.71</td>\n",
" <td>3348.47</td>\n",
" <td>3348.78</td>\n",
" <td>928</td>\n",
" <td>19</td>\n",
" <td>0</td>\n",
" <td>3350.024962</td>\n",
" <td>3351.232735</td>\n",
" <td>34.935115</td>\n",
" <td>3348.405247</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>496</th>\n",
" <td>2025-07-18 22:50:00</td>\n",
" <td>3348.79</td>\n",
" <td>3348.80</td>\n",
" <td>3347.62</td>\n",
" <td>3348.15</td>\n",
" <td>859</td>\n",
" <td>19</td>\n",
" <td>0</td>\n",
" <td>3349.684060</td>\n",
" <td>3351.033849</td>\n",
" <td>32.290909</td>\n",
" <td>3348.186635</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>497</th>\n",
" <td>2025-07-18 22:55:00</td>\n",
" <td>3348.16</td>\n",
" <td>3348.53</td>\n",
" <td>3347.65</td>\n",
" <td>3348.25</td>\n",
" <td>1028</td>\n",
" <td>19</td>\n",
" <td>0</td>\n",
" <td>3349.423322</td>\n",
" <td>3350.854245</td>\n",
" <td>33.155760</td>\n",
" <td>3348.153324</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>498</th>\n",
" <td>2025-07-18 23:00:00</td>\n",
" <td>3348.24</td>\n",
" <td>3348.88</td>\n",
" <td>3347.72</td>\n",
" <td>3348.06</td>\n",
" <td>599</td>\n",
" <td>19</td>\n",
" <td>0</td>\n",
" <td>3349.175445</td>\n",
" <td>3350.673972</td>\n",
" <td>32.311285</td>\n",
" <td>3348.346744</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>499</th>\n",
" <td>2025-07-18 23:05:00</td>\n",
" <td>3348.06</td>\n",
" <td>3349.25</td>\n",
" <td>3347.92</td>\n",
" <td>3348.88</td>\n",
" <td>450</td>\n",
" <td>19</td>\n",
" <td>0</td>\n",
" <td>3349.121728</td>\n",
" <td>3350.558231</td>\n",
" <td>39.476021</td>\n",
" <td>3348.808327</td>\n",
" <td>0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>500 rows × 13 columns</p>\n",
"</div>"
],
"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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>timestamp</th>\n",
" <th>symbol</th>\n",
" <th>order_type</th>\n",
" <th>price</th>\n",
" <th>sl</th>\n",
" <th>tp</th>\n",
" <th>volume</th>\n",
" <th>signal</th>\n",
" <th>comment</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>2025-07-18 16:06:32.701648</td>\n",
" <td>XAUUSD</td>\n",
" <td>BUY</td>\n",
" <td>3358.95</td>\n",
" <td>3358.75</td>\n",
" <td>3359.35</td>\n",
" <td>0.1</td>\n",
" <td>b'\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00'</td>\n",
" <td>AutoSignalBot</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2025-07-18 15:51:32.545794</td>\n",
" <td>XAUUSD</td>\n",
" <td>SELL</td>\n",
" <td>3354.56</td>\n",
" <td>3354.76</td>\n",
" <td>3354.16</td>\n",
" <td>0.1</td>\n",
" <td>b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff'</td>\n",
" <td>AutoSignalBot</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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
}
@@ -1,2 +0,0 @@
[ZoneTransfer]
ZoneId=3
-841
View File
@@ -1,841 +0,0 @@
{
"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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>time</th>\n",
" <th>open</th>\n",
" <th>high</th>\n",
" <th>low</th>\n",
" <th>close</th>\n",
" <th>tick_volume</th>\n",
" <th>spread</th>\n",
" <th>real_volume</th>\n",
" <th>ema10</th>\n",
" <th>ema30</th>\n",
" <th>rsi</th>\n",
" <th>trend</th>\n",
" <th>signal</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>2025-07-17 04:30:00</td>\n",
" <td>3340.74</td>\n",
" <td>3341.46</td>\n",
" <td>3337.21</td>\n",
" <td>3338.04</td>\n",
" <td>1293</td>\n",
" <td>18</td>\n",
" <td>0</td>\n",
" <td>3338.040000</td>\n",
" <td>3338.040000</td>\n",
" <td>NaN</td>\n",
" <td>3338.208386</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2025-07-17 04:35:00</td>\n",
" <td>3338.03</td>\n",
" <td>3341.03</td>\n",
" <td>3337.72</td>\n",
" <td>3341.03</td>\n",
" <td>964</td>\n",
" <td>18</td>\n",
" <td>0</td>\n",
" <td>3339.684500</td>\n",
" <td>3339.584833</td>\n",
" <td>NaN</td>\n",
" <td>3340.377874</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>2025-07-17 04:40:00</td>\n",
" <td>3341.03</td>\n",
" <td>3341.48</td>\n",
" <td>3339.96</td>\n",
" <td>3341.26</td>\n",
" <td>944</td>\n",
" <td>18</td>\n",
" <td>0</td>\n",
" <td>3340.317841</td>\n",
" <td>3340.180848</td>\n",
" <td>NaN</td>\n",
" <td>3341.873882</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>2025-07-17 04:45:00</td>\n",
" <td>3341.27</td>\n",
" <td>3343.45</td>\n",
" <td>3341.27</td>\n",
" <td>3342.47</td>\n",
" <td>1099</td>\n",
" <td>18</td>\n",
" <td>0</td>\n",
" <td>3341.026881</td>\n",
" <td>3340.811593</td>\n",
" <td>NaN</td>\n",
" <td>3342.785860</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>2025-07-17 04:50:00</td>\n",
" <td>3342.47</td>\n",
" <td>3343.61</td>\n",
" <td>3342.20</td>\n",
" <td>3342.84</td>\n",
" <td>1070</td>\n",
" <td>18</td>\n",
" <td>0</td>\n",
" <td>3341.547378</td>\n",
" <td>3341.273104</td>\n",
" <td>NaN</td>\n",
" <td>3343.203260</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>495</th>\n",
" <td>2025-07-18 22:45:00</td>\n",
" <td>3349.29</td>\n",
" <td>3349.71</td>\n",
" <td>3348.47</td>\n",
" <td>3348.78</td>\n",
" <td>928</td>\n",
" <td>19</td>\n",
" <td>0</td>\n",
" <td>3350.024962</td>\n",
" <td>3351.232735</td>\n",
" <td>34.935115</td>\n",
" <td>3348.405247</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>496</th>\n",
" <td>2025-07-18 22:50:00</td>\n",
" <td>3348.79</td>\n",
" <td>3348.80</td>\n",
" <td>3347.62</td>\n",
" <td>3348.15</td>\n",
" <td>859</td>\n",
" <td>19</td>\n",
" <td>0</td>\n",
" <td>3349.684060</td>\n",
" <td>3351.033849</td>\n",
" <td>32.290909</td>\n",
" <td>3348.186635</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>497</th>\n",
" <td>2025-07-18 22:55:00</td>\n",
" <td>3348.16</td>\n",
" <td>3348.53</td>\n",
" <td>3347.65</td>\n",
" <td>3348.25</td>\n",
" <td>1028</td>\n",
" <td>19</td>\n",
" <td>0</td>\n",
" <td>3349.423322</td>\n",
" <td>3350.854245</td>\n",
" <td>33.155760</td>\n",
" <td>3348.153324</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>498</th>\n",
" <td>2025-07-18 23:00:00</td>\n",
" <td>3348.24</td>\n",
" <td>3348.88</td>\n",
" <td>3347.72</td>\n",
" <td>3348.06</td>\n",
" <td>599</td>\n",
" <td>19</td>\n",
" <td>0</td>\n",
" <td>3349.175445</td>\n",
" <td>3350.673972</td>\n",
" <td>32.311285</td>\n",
" <td>3348.346744</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>499</th>\n",
" <td>2025-07-18 23:05:00</td>\n",
" <td>3348.06</td>\n",
" <td>3349.25</td>\n",
" <td>3347.92</td>\n",
" <td>3348.88</td>\n",
" <td>450</td>\n",
" <td>19</td>\n",
" <td>0</td>\n",
" <td>3349.121728</td>\n",
" <td>3350.558231</td>\n",
" <td>39.476021</td>\n",
" <td>3348.808327</td>\n",
" <td>0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>500 rows × 13 columns</p>\n",
"</div>"
],
"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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>timestamp</th>\n",
" <th>symbol</th>\n",
" <th>order_type</th>\n",
" <th>price</th>\n",
" <th>sl</th>\n",
" <th>tp</th>\n",
" <th>volume</th>\n",
" <th>signal</th>\n",
" <th>comment</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>2025-07-18 16:06:32.701648</td>\n",
" <td>XAUUSD</td>\n",
" <td>BUY</td>\n",
" <td>3358.95</td>\n",
" <td>3358.75</td>\n",
" <td>3359.35</td>\n",
" <td>0.1</td>\n",
" <td>b'\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00'</td>\n",
" <td>AutoSignalBot</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2025-07-18 15:51:32.545794</td>\n",
" <td>XAUUSD</td>\n",
" <td>SELL</td>\n",
" <td>3354.56</td>\n",
" <td>3354.76</td>\n",
" <td>3354.16</td>\n",
" <td>0.1</td>\n",
" <td>b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff'</td>\n",
" <td>AutoSignalBot</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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
}
@@ -1,885 +0,0 @@
{
"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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>time</th>\n",
" <th>open</th>\n",
" <th>high</th>\n",
" <th>low</th>\n",
" <th>close</th>\n",
" <th>tick_volume</th>\n",
" <th>spread</th>\n",
" <th>real_volume</th>\n",
" <th>ema10</th>\n",
" <th>ema30</th>\n",
" <th>rsi</th>\n",
" <th>trend</th>\n",
" <th>signal</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>2025-07-17 04:30:00</td>\n",
" <td>3340.74</td>\n",
" <td>3341.46</td>\n",
" <td>3337.21</td>\n",
" <td>3338.04</td>\n",
" <td>1293</td>\n",
" <td>18</td>\n",
" <td>0</td>\n",
" <td>3338.040000</td>\n",
" <td>3338.040000</td>\n",
" <td>NaN</td>\n",
" <td>3338.208386</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2025-07-17 04:35:00</td>\n",
" <td>3338.03</td>\n",
" <td>3341.03</td>\n",
" <td>3337.72</td>\n",
" <td>3341.03</td>\n",
" <td>964</td>\n",
" <td>18</td>\n",
" <td>0</td>\n",
" <td>3339.684500</td>\n",
" <td>3339.584833</td>\n",
" <td>NaN</td>\n",
" <td>3340.377874</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>2025-07-17 04:40:00</td>\n",
" <td>3341.03</td>\n",
" <td>3341.48</td>\n",
" <td>3339.96</td>\n",
" <td>3341.26</td>\n",
" <td>944</td>\n",
" <td>18</td>\n",
" <td>0</td>\n",
" <td>3340.317841</td>\n",
" <td>3340.180848</td>\n",
" <td>NaN</td>\n",
" <td>3341.873882</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>2025-07-17 04:45:00</td>\n",
" <td>3341.27</td>\n",
" <td>3343.45</td>\n",
" <td>3341.27</td>\n",
" <td>3342.47</td>\n",
" <td>1099</td>\n",
" <td>18</td>\n",
" <td>0</td>\n",
" <td>3341.026881</td>\n",
" <td>3340.811593</td>\n",
" <td>NaN</td>\n",
" <td>3342.785860</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>2025-07-17 04:50:00</td>\n",
" <td>3342.47</td>\n",
" <td>3343.61</td>\n",
" <td>3342.20</td>\n",
" <td>3342.84</td>\n",
" <td>1070</td>\n",
" <td>18</td>\n",
" <td>0</td>\n",
" <td>3341.547378</td>\n",
" <td>3341.273104</td>\n",
" <td>NaN</td>\n",
" <td>3343.203260</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>495</th>\n",
" <td>2025-07-18 22:45:00</td>\n",
" <td>3349.29</td>\n",
" <td>3349.71</td>\n",
" <td>3348.47</td>\n",
" <td>3348.78</td>\n",
" <td>928</td>\n",
" <td>19</td>\n",
" <td>0</td>\n",
" <td>3350.024962</td>\n",
" <td>3351.232735</td>\n",
" <td>34.935115</td>\n",
" <td>3348.405247</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>496</th>\n",
" <td>2025-07-18 22:50:00</td>\n",
" <td>3348.79</td>\n",
" <td>3348.80</td>\n",
" <td>3347.62</td>\n",
" <td>3348.15</td>\n",
" <td>859</td>\n",
" <td>19</td>\n",
" <td>0</td>\n",
" <td>3349.684060</td>\n",
" <td>3351.033849</td>\n",
" <td>32.290909</td>\n",
" <td>3348.186635</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>497</th>\n",
" <td>2025-07-18 22:55:00</td>\n",
" <td>3348.16</td>\n",
" <td>3348.53</td>\n",
" <td>3347.65</td>\n",
" <td>3348.25</td>\n",
" <td>1028</td>\n",
" <td>19</td>\n",
" <td>0</td>\n",
" <td>3349.423322</td>\n",
" <td>3350.854245</td>\n",
" <td>33.155760</td>\n",
" <td>3348.153324</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>498</th>\n",
" <td>2025-07-18 23:00:00</td>\n",
" <td>3348.24</td>\n",
" <td>3348.88</td>\n",
" <td>3347.72</td>\n",
" <td>3348.06</td>\n",
" <td>599</td>\n",
" <td>19</td>\n",
" <td>0</td>\n",
" <td>3349.175445</td>\n",
" <td>3350.673972</td>\n",
" <td>32.311285</td>\n",
" <td>3348.346744</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>499</th>\n",
" <td>2025-07-18 23:05:00</td>\n",
" <td>3348.06</td>\n",
" <td>3349.25</td>\n",
" <td>3347.92</td>\n",
" <td>3348.88</td>\n",
" <td>450</td>\n",
" <td>19</td>\n",
" <td>0</td>\n",
" <td>3349.121728</td>\n",
" <td>3350.558231</td>\n",
" <td>39.476021</td>\n",
" <td>3348.808327</td>\n",
" <td>0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>500 rows × 13 columns</p>\n",
"</div>"
],
"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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>timestamp</th>\n",
" <th>symbol</th>\n",
" <th>order_type</th>\n",
" <th>price</th>\n",
" <th>sl</th>\n",
" <th>tp</th>\n",
" <th>volume</th>\n",
" <th>signal</th>\n",
" <th>comment</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>2025-07-18 16:06:32.701648</td>\n",
" <td>XAUUSD</td>\n",
" <td>BUY</td>\n",
" <td>3358.95</td>\n",
" <td>3358.75</td>\n",
" <td>3359.35</td>\n",
" <td>0.1</td>\n",
" <td>b'\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00'</td>\n",
" <td>AutoSignalBot</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2025-07-18 15:51:32.545794</td>\n",
" <td>XAUUSD</td>\n",
" <td>SELL</td>\n",
" <td>3354.56</td>\n",
" <td>3354.76</td>\n",
" <td>3354.16</td>\n",
" <td>0.1</td>\n",
" <td>b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff'</td>\n",
" <td>AutoSignalBot</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"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
}
-66
View File
@@ -1,66 +0,0 @@
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()
+508
View File
@@ -0,0 +1,508 @@
# 📊 Streamlit Dashboard - Windows Server Deployment
## Übersicht
Diese Anleitung zeigt dir wie du das Trading Dashboard auf einem **Windows Server** (oder Windows VPS) zum Laufen bringst.
## 🚀 Installation auf Windows Server
### SCHRITT 1: Python & Dependencies prüfen
**1. Öffne PowerShell als Administrator**
```powershell
# Prüfe Python Version
python --version
# Sollte Python 3.8+ zeigen
# Falls Python nicht gefunden wird:
# Installiere von: https://www.python.org/downloads/
```
**2. Navigiere zum Trading Bot Ordner**
```powershell
# Beispiel (passe Pfad an):
cd C:\TradingBot\placeorder
```
**3. Installiere Streamlit & Dependencies**
```powershell
pip install streamlit plotly pandas
```
Falls `pip` nicht funktioniert:
```powershell
python -m pip install streamlit plotly pandas
```
### SCHRITT 2: Dashboard-Datei kopieren
**Option A: Via RDP (Remote Desktop)**
1. Verbinde per RDP zu deinem Windows Server
2. Öffne Browser auf dem Server
3. Lade `trading_dashboard.py` herunter (z.B. via GitHub, Email, Cloud)
4. Kopiere nach: `C:\TradingBot\placeorder\`
**Option B: Via SCP (von Mac aus)**
```bash
# Auf deinem Mac (Terminal)
scp "/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/FinancialTrading/PlaceOrder/placeorder/trading_dashboard.py" user@windows-server-ip:C:/TradingBot/placeorder/
```
**Hinweis:** Benötigt OpenSSH Server auf Windows. Siehe unten für Aktivierung.
**Option C: Manuell erstellen**
1. Auf Windows Server: Öffne Notepad++, VSCode oder Editor
2. Erstelle neue Datei: `trading_dashboard.py`
3. Copy-Paste den Code aus der Datei
4. Speichere in: `C:\TradingBot\placeorder\`
### SCHRITT 3: Dashboard starten
**Option A: PowerShell (zum Testen)**
```powershell
cd C:\TradingBot\placeorder
streamlit run trading_dashboard.py --server.port 8501 --server.address 0.0.0.0
```
Das Dashboard startet und sollte automatisch den Browser öffnen!
**Option B: CMD (Command Prompt)**
```cmd
cd C:\TradingBot\placeorder
streamlit run trading_dashboard.py --server.port 8501 --server.address 0.0.0.0
```
### SCHRITT 4: Firewall-Regel erstellen
**Windows Firewall für Port 8501 öffnen:**
**Via GUI:**
1. Windows-Taste → "Windows Defender Firewall"
2. "Erweiterte Einstellungen"
3. "Eingehende Regeln" → "Neue Regel..."
4. "Port" auswählen → Weiter
5. "TCP" → "Bestimmte lokale Ports": **8501** → Weiter
6. "Verbindung zulassen" → Weiter
7. Alle Profile aktivieren → Weiter
8. Name: "Streamlit Dashboard" → Fertig
**Via PowerShell (als Administrator):**
```powershell
New-NetFirewallRule -DisplayName "Streamlit Dashboard" -Direction Inbound -LocalPort 8501 -Protocol TCP -Action Allow
```
### SCHRITT 5: Dashboard im Browser öffnen
**Lokal auf dem Server:**
```
http://localhost:8501
```
**Von anderem Computer:**
```
http://WINDOWS-SERVER-IP:8501
```
Beispiel:
```
http://192.168.1.100:8501
```
## 🔄 Dashboard permanent laufen lassen
### Option 1: Als Windows Service (EMPFOHLEN)
**Mit NSSM (Non-Sucking Service Manager):**
**1. NSSM herunterladen:**
```
https://nssm.cc/download
```
**2. NSSM installieren:**
```powershell
# NSSM entpacken nach C:\nssm
# PowerShell als Administrator öffnen
cd C:\nssm\win64
# Service erstellen
.\nssm.exe install TradingDashboard
```
**3. Im NSSM GUI konfigurieren:**
- **Application Tab:**
- Path: `C:\Python310\Scripts\streamlit.exe` (passe Python-Pfad an)
- Startup directory: `C:\TradingBot\placeorder`
- Arguments: `run trading_dashboard.py --server.port 8501 --server.address 0.0.0.0`
- **Details Tab:**
- Display name: `Trading Dashboard`
- Description: `Streamlit Dashboard for Trading Bot V1.8`
- **Log on Tab:**
- Wähle Account (z.B. dein User-Account)
- **I/O Tab:**
- Output (stdout): `C:\TradingBot\placeorder\dashboard_stdout.log`
- Error (stderr): `C:\TradingBot\placeorder\dashboard_stderr.log`
**4. Service starten:**
```powershell
# Service starten
.\nssm.exe start TradingDashboard
# Service Status prüfen
.\nssm.exe status TradingDashboard
# Service stoppen
.\nssm.exe stop TradingDashboard
# Service entfernen (falls nötig)
.\nssm.exe remove TradingDashboard
```
**Oder via Windows Services:**
1. Windows-Taste → "services.msc"
2. Finde "Trading Dashboard"
3. Rechtsklick → "Starten"
### Option 2: Batch-Datei + Task Scheduler
**1. Erstelle Batch-Datei:**
Erstelle `start_dashboard.bat`:
```batch
@echo off
echo Starting Trading Dashboard...
cd /d C:\TradingBot\placeorder
streamlit run trading_dashboard.py --server.port 8501 --server.address 0.0.0.0
pause
```
**2. Task Scheduler konfigurieren:**
1. Windows-Taste → "Task Scheduler"
2. "Create Basic Task..."
3. Name: "Trading Dashboard"
4. Trigger: "When the computer starts"
5. Action: "Start a program"
6. Program: `C:\TradingBot\placeorder\start_dashboard.bat`
7. Finish
**Task manuell starten:**
- Task Scheduler → Rechtsklick auf Task → "Run"
### Option 3: PowerShell Background Job (temporär)
```powershell
# Starte als Background Job
Start-Process powershell -ArgumentList "-NoExit", "-Command", "cd C:\TradingBot\placeorder; streamlit run trading_dashboard.py --server.port 8501 --server.address 0.0.0.0"
# Prüfe laufende Prozesse
Get-Process | Where-Object {$_.ProcessName -like "*streamlit*"}
# Stoppe Dashboard
Stop-Process -Name streamlit -Force
```
## 🔒 Sicherheit & Zugriff
### Option 1: SSH Tunnel (von Mac aus)
**Falls OpenSSH Server auf Windows aktiviert:**
```bash
# Auf Mac
ssh -L 8501:localhost:8501 user@windows-server-ip
# Dann Browser öffnen
http://localhost:8501
```
**OpenSSH Server auf Windows aktivieren:**
```powershell
# PowerShell als Administrator
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
# SSH Service starten
Start-Service sshd
Set-Service -Name sshd -StartupType 'Automatic'
# Firewall-Regel (falls nötig)
New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
```
### Option 2: IIS Reverse Proxy (für HTTPS)
Falls du IIS verwendest, kannst du einen Reverse Proxy einrichten:
1. Installiere "Application Request Routing" (ARR)
2. Installiere "URL Rewrite"
3. Konfiguriere Reverse Proxy von Port 80/443 → 8501
### Option 3: VPN-Only Access
Öffne Port 8501 nur im VPN-Netzwerk, nicht öffentlich.
## 📱 Zugriff von außen (Internet)
### Router Port Forwarding (falls Home Server)
1. Router-Verwaltung öffnen
2. Port Forwarding Regel erstellen:
- External Port: 8501
- Internal IP: Windows Server IP (z.B. 192.168.1.100)
- Internal Port: 8501
- Protocol: TCP
3. Zugriff via:
```
http://DEINE-ÖFFENTLICHE-IP:8501
```
### Cloud VPS (z.B. Azure, AWS)
**Firewall/Security Group konfigurieren:**
- Erlaube eingehenden Traffic auf Port 8501 (TCP)
- Von deiner IP oder 0.0.0.0/0 (öffentlich, vorsichtig!)
## 🛠️ Troubleshooting
### Dashboard startet nicht
**1. Prüfe Python/Streamlit Installation:**
```powershell
python --version
streamlit --version
```
**2. Prüfe ob Port belegt:**
```powershell
netstat -ano | findstr :8501
```
Falls Port belegt, finde Prozess:
```powershell
# Nutze die PID aus netstat output
tasklist | findstr <PID>
# Prozess killen
taskkill /PID <PID> /F
```
**3. Prüfe Logs:**
Falls als Service läuft, schaue in:
```
C:\TradingBot\placeorder\dashboard_stdout.log
C:\TradingBot\placeorder\dashboard_stderr.log
```
### Dashboard nicht erreichbar von außen
**1. Firewall prüfen:**
```powershell
Get-NetFirewallRule | Where-Object {$_.LocalPort -eq 8501}
```
**2. Prüfe ob Streamlit auf richtiger IP hört:**
```powershell
netstat -ano | findstr :8501
```
Sollte zeigen: `0.0.0.0:8501` (nicht `127.0.0.1:8501`)
Falls falsch, starte mit `--server.address 0.0.0.0`:
```powershell
streamlit run trading_dashboard.py --server.port 8501 --server.address 0.0.0.0
```
### Database Error
```powershell
# Prüfe ob trading_bot.db existiert
dir trading_bot.db
# Falls nicht:
# 1. Starte zuerst den Trading Bot (Jupyter Notebook)
# 2. Der erstellt automatisch die Datenbank
```
## 📊 PowerShell Helper Scripts
### start_dashboard.ps1
```powershell
# Trading Dashboard Starter Script
Write-Host "Starting Trading Dashboard..." -ForegroundColor Green
$path = "C:\TradingBot\placeorder"
Set-Location $path
# Check if database exists
if (!(Test-Path "trading_bot.db")) {
Write-Host "WARNING: trading_bot.db not found!" -ForegroundColor Yellow
Write-Host "Make sure the Trading Bot is running first." -ForegroundColor Yellow
}
# Start Streamlit
Write-Host "Dashboard starting on http://localhost:8501" -ForegroundColor Cyan
streamlit run trading_dashboard.py --server.port 8501 --server.address 0.0.0.0
```
### stop_dashboard.ps1
```powershell
# Stop Trading Dashboard
Write-Host "Stopping Trading Dashboard..." -ForegroundColor Yellow
Get-Process | Where-Object {$_.ProcessName -like "*streamlit*"} | Stop-Process -Force
Write-Host "Dashboard stopped!" -ForegroundColor Green
```
### check_dashboard.ps1
```powershell
# Check Dashboard Status
Write-Host "Checking Trading Dashboard Status..." -ForegroundColor Cyan
$process = Get-Process | Where-Object {$_.ProcessName -like "*streamlit*"}
if ($process) {
Write-Host "Dashboard is RUNNING" -ForegroundColor Green
Write-Host "Process ID: $($process.Id)" -ForegroundColor White
Write-Host "URL: http://localhost:8501" -ForegroundColor Cyan
} else {
Write-Host "Dashboard is NOT running" -ForegroundColor Red
}
# Check if port is listening
$port = Get-NetTCPConnection -LocalPort 8501 -ErrorAction SilentlyContinue
if ($port) {
Write-Host "Port 8501 is LISTENING" -ForegroundColor Green
} else {
Write-Host "Port 8501 is NOT listening" -ForegroundColor Yellow
}
```
## ✅ Installation Checklist
- [ ] Python 3.8+ installiert
- [ ] Streamlit installiert (`pip install streamlit plotly pandas`)
- [ ] trading_dashboard.py im richtigen Ordner
- [ ] Windows Firewall Port 8501 geöffnet
- [ ] Dashboard gestartet (manuell oder als Service)
- [ ] Im Browser erreichbar (`http://localhost:8501`)
- [ ] Von außen erreichbar (`http://SERVER-IP:8501`)
- [ ] Als Windows Service konfiguriert (optional, empfohlen)
- [ ] Auto-Start beim Boot konfiguriert (optional)
## 🎯 Empfohlenes Setup für Windows Server
**Beste Praxis:**
1. **Dashboard als Windows Service** (mit NSSM)
- Auto-Start beim Boot
- Läuft auch ohne User-Login
2. **Firewall konfiguriert**
- Port 8501 nur von vertrauenswürdigen IPs
3. **Logs aktiviert**
- stdout/stderr Logs für Debugging
4. **Auto-Refresh im Dashboard** (30s)
## 🎉 Quick Start Commands
```powershell
# Dashboard starten (manuell)
cd C:\TradingBot\placeorder
streamlit run trading_dashboard.py --server.port 8501 --server.address 0.0.0.0
# Dashboard Status prüfen
Get-Process | Where-Object {$_.ProcessName -like "*streamlit*"}
# Dashboard stoppen
Stop-Process -Name streamlit -Force
# Service starten (falls als Service installiert)
Start-Service TradingDashboard
# Service stoppen
Stop-Service TradingDashboard
```
## 📝 Zugriff URLs
**Lokal auf Server:**
```
http://localhost:8501
```
**Vom Netzwerk:**
```
http://WINDOWS-SERVER-IP:8501
```
**Von außen (Internet):**
```
http://ÖFFENTLICHE-IP:8501
```
**Via SSH Tunnel:**
```bash
# Auf Mac
ssh -L 8501:localhost:8501 user@windows-server-ip
# Browser öffnen
http://localhost:8501
```
## 🔗 Nützliche Links
- **NSSM Download:** https://nssm.cc/download
- **Python Windows:** https://www.python.org/downloads/windows/
- **Streamlit Docs:** https://docs.streamlit.io/
## 💡 Pro-Tipps
1. **Dedicated User Account:** Erstelle einen separaten Windows User nur für den Trading Bot
2. **Scheduled Restart:** Task Scheduler für täglichen Neustart (z.B. 3:00 nachts)
3. **Backup:** Sichere `trading_bot.db` regelmäßig
4. **Monitoring:** Nutze Windows Performance Monitor für Ressourcen-Überwachung
5. **Updates:** Halte Streamlit aktuell: `pip install --upgrade streamlit`
## 🚨 Wichtige Sicherheitshinweise
⚠️ **NIEMALS Port 8501 öffentlich ohne Authentifizierung öffnen!**
Empfohlene Absicherung:
- VPN-Only Access
- SSH Tunnel
- IIS Reverse Proxy mit Basic Auth
- IP Whitelist in Firewall
---
Du bist jetzt bereit das Dashboard auf Windows Server zu deployen! 🎉
+306
View File
@@ -0,0 +1,306 @@
# 🔧 FIX: Duplicate Scheduler Problem
## ❌ Problem Identifiziert
**Symptom:** Bot tradet während London Session trotz SESSION_WHITELIST_CONFIG mit nur NY aktiviert
**Root Cause:** **DUPLICATE Scheduler Jobs!**
Beweis aus deinen Logs:
```
2025-11-26 11:37:00 - INFO - Running job "create_session_filtered_check..." (scheduled at 11:37:00)
2025-11-26 11:37:00 - INFO - ⏸️ Trading SKIP: Session blocked: London
2025-11-26 11:37:00 - INFO - Running job "create_session_filtered_check..." (scheduled at 11:37:00)
2025-11-26 11:37:00 - INFO - ⏸️ Trading SKIP: Session blocked: London
```
**Was passiert:**
1. ✅ **NEUER** Scheduler mit Session Filter → blockiert London korrekt
2. ❌ **ALTER** Scheduler OHNE Session Filter → tradet weiter!
## 🔍 Wie ist das passiert?
**Szenario:**
1. Du hast Cell 33 (Scheduler Start) mehrmals ausgeführt
2. Jedes Mal wurde ein NEUER Scheduler erstellt
3. ALTE Scheduler laufen weiter im Hintergrund
4. Result: 2+ Jobs zur gleichen Zeit!
## ✅ Lösung: Scheduler Cleanup + Neustart
### SCHRITT 1: Alle laufenden Scheduler stoppen
**In einer NEUEN Notebook Cell ausführen:**
```python
# ==========================================
# SCHRITT 1: ALLE SCHEDULER STOPPEN
# ==========================================
print("🔄 Stopping all schedulers...")
# Stop current scheduler
try:
scheduler.shutdown(wait=False)
print("✅ Main scheduler stopped")
except:
print("⚠️ No main scheduler found")
# Check for orphaned schedulers
import gc
from apscheduler.schedulers.background import BackgroundScheduler
orphaned_count = 0
for obj in gc.get_objects():
try:
if isinstance(obj, BackgroundScheduler):
if obj.running:
obj.shutdown(wait=False)
orphaned_count += 1
print(f"✅ Stopped orphaned scheduler {orphaned_count}")
except:
pass
print(f"\n✅ Cleanup complete! Stopped {orphaned_count + 1} scheduler(s)")
print("⏸️ Bot is now PAUSED - no trading happening")
```
**Erwartete Ausgabe:**
```
🔄 Stopping all schedulers...
✅ Main scheduler stopped
✅ Stopped orphaned scheduler 1
✅ Stopped orphaned scheduler 2
✅ Cleanup complete! Stopped 3 scheduler(s)
```
### SCHRITT 2: Session Filter Configuration bestätigen
**Prüfe nochmal die Config:**
```python
# ==========================================
# SCHRITT 2: VERIFY SESSION FILTER CONFIG
# ==========================================
from session_filter_patch import SESSION_WHITELIST_CONFIG, is_session_allowed
print("📊 CURRENT SESSION FILTER CONFIGURATION:")
print("=" * 60)
for session in ['asian', 'london', 'overlap', 'ny']:
allowed, reason = is_session_allowed(session)
emoji = "✅ AKTIV" if allowed else "❌ BLOCKED"
print(f"{emoji:12s} {session.upper():8s}: {reason}")
print("\n📋 Full Config:")
print(f"Enabled Sessions: {SESSION_WHITELIST_CONFIG['enabled_sessions']}")
print(f"Base Confidence: {SESSION_WHITELIST_CONFIG['base_confidence']}%")
print(f"Aggressive Mode: {SESSION_WHITELIST_CONFIG.get('aggressive_mode', False)}")
```
**Erwartete Ausgabe:**
```
❌ BLOCKED ASIAN : Session blocked: Asian has -$199 loss...
❌ BLOCKED LONDON : Session blocked: London is break-even...
❌ BLOCKED OVERLAP : Session blocked: Not in whitelist
✅ AKTIV NY : NY allowed: +$372 profit, 50.0% win-rate
```
### SCHRITT 3: Neuen Scheduler mit Session Filter starten
**Erstelle einen FRISCHEN Scheduler:**
```python
# ==========================================
# SCHRITT 3: CREATE FRESH SCHEDULER
# ==========================================
from apscheduler.schedulers.background import BackgroundScheduler
from session_filter_patch import create_session_filtered_check, SESSION_WHITELIST_CONFIG
from infrastructure_patch import create_scheduled_reports
print("🚀 Creating FRESH scheduler with session filter...")
# Create NEW scheduler instance
scheduler = BackgroundScheduler()
# Create session-filtered trading check
adaptive_trading_check = create_session_filtered_check(
rhythm_manager=rhythm_manager,
execute_func=execute_trade_v2_adaptive,
symbol=symbol,
strategy_name=strategy_name,
max_positions=max_positions,
logger=logger,
datetime=datetime,
config=SESSION_WHITELIST_CONFIG # ✅ EXPLICITLY pass config
)
# Add FILTERED trading job
scheduler.add_job(
func=adaptive_trading_check,
trigger='cron',
minute='*',
id='adaptive_trading_check_v18', # NEW ID to avoid conflicts
replace_existing=True
)
# Add status report
scheduler.add_job(
func=print_status_report,
trigger='cron',
minute='0,30',
id='status_report_v18',
replace_existing=True
)
# Add infrastructure reports
create_scheduled_reports(infra, scheduler)
# Start scheduler
scheduler.start()
print("\n✅ FRESH SCHEDULER STARTED!")
print(f" Active Jobs: {len(scheduler.get_jobs())}")
print("\n📋 Scheduled Jobs:")
for job in scheduler.get_jobs():
print(f" • {job.id} - {job.trigger}")
print("\n⚠️ SESSION FILTER ACTIVE:")
for session, enabled in SESSION_WHITELIST_CONFIG['enabled_sessions'].items():
status = "✅ TRADING" if enabled else "❌ BLOCKED"
print(f" {session.upper():8s}: {status}")
print("\n🎯 Bot will ONLY trade during NY session (13:00-21:00 UTC)")
print("🔒 All other sessions are BLOCKED")
```
**Erwartete Ausgabe:**
```
✅ FRESH SCHEDULER STARTED!
Active Jobs: 4
📋 Scheduled Jobs:
• adaptive_trading_check_v18 - cron[minute='*']
• status_report_v18 - cron[minute='0,30']
• daily_report - cron[hour='22', minute='0']
• weekly_report - cron[day_of_week='sun', hour='23', minute='0']
⚠️ SESSION FILTER ACTIVE:
ASIAN : ❌ BLOCKED
LONDON : ❌ BLOCKED
OVERLAP : ❌ BLOCKED
NY : ✅ TRADING
```
### SCHRITT 4: Verification Test
**Warte 1-2 Minuten und prüfe die Logs:**
```python
# ==========================================
# SCHRITT 4: VERIFY LOGS
# ==========================================
import time
print("⏰ Waiting 90 seconds to collect logs...")
time.sleep(90)
print("\n📊 Last few log entries should show:")
print(" ⏸️ Trading SKIP: Session blocked: London")
print("\n✅ If you see this → Session filter is working!")
```
## 📊 Expected Behavior nach Fix
### Während London Session (08:00-13:00 UTC / 09:00-14:00 CET):
```
2025-11-26 11:37:00 - INFO - ⏸️ Trading SKIP: Session blocked: London
2025-11-26 11:38:00 - INFO - ⏸️ Trading SKIP: Session blocked: London
2025-11-26 11:39:00 - INFO - ⏸️ Trading SKIP: Session blocked: London
```
**WICHTIG:** Nur EINE Log-Zeile pro Minute! (Nicht 2 wie vorher)
### Während NY Session (13:00-21:00 UTC / 14:00-22:00 CET):
```
2025-11-26 14:00:00 - INFO - ✅ Session: NY - NY allowed: +$372 profit
2025-11-26 14:00:00 - INFO - 📊 Confidence Threshold: 60%
[Normal trading analysis...]
```
### Andere Sessions:
- **Asian (00:00-08:00 UTC):** ⏸️ Trading SKIP
- **Overlap (13:00-16:00 UTC):** ⏸️ Trading SKIP (auch wenn in NY Zeit!)
## 🔍 How to Monitor
### Quick Check jede Stunde:
```python
# Check current session & status
from datetime import datetime
import pytz
now_utc = datetime.now(pytz.UTC)
current_session = rhythm_manager.get_current_session()
allowed, reason = is_session_allowed(current_session)
print(f"Time: {now_utc.strftime('%H:%M UTC')}")
print(f"Session: {current_session.upper()}")
print(f"Trading: {'✅ ACTIVE' if allowed else '❌ BLOCKED'}")
print(f"Reason: {reason}")
```
### Full Status:
```python
check_adaptive_bot_status()
```
## ⚠️ WICHTIG: Prevent Future Duplicates
**NIEMALS nochmal Cell 33 ausführen!**
Wenn du den Scheduler neu starten musst:
1. **ERST:** `scheduler.shutdown()` ausführen
2. **DANN:** Neue Scheduler Cell ausführen
**ODER:** Kernel → Restart & Run All (safest!)
## 🎯 Summary
**Problem:**
- Duplicate schedulers (mit/ohne Session Filter)
**Lösung:**
1. ✅ Alle Scheduler stoppen
2. ✅ Config verifizieren
3. ✅ Frischen Scheduler mit Session Filter starten
4. ✅ Logs monitoren
**Result:**
- Nur 1 Scheduler läuft
- Session Filter aktiv
- Nur NY Session tradet
- London/Asian/Overlap blockiert
**Expected Log:**
```
⏸️ Trading SKIP: Session blocked: London ← RICHTIG!
(nur EINE Zeile pro Minute während London)
```
## 📱 Next Steps
Nach dem Fix:
1. **Monitor 24h:** Prüfe dass KEIN Trade außerhalb NY passiert
2. **Check Telegram:** Du solltest jetzt NUR NY-Trades sehen
3. **Database Check:** Alle neuen Trades sollten `session='ny'` haben
**Falls weiterhin London Trades:**
→ Kernel Restart erforderlich
→ Alle Cells neu ausführen (Kernel → Restart & Run All)
+279
View File
@@ -0,0 +1,279 @@
# 🧹 Project Cleanup Guide
## Aktuelle Projekt-Struktur
### ✅ KEEP - Production Files (Aktiv genutzt)
**Core Trading Bot:**
- `TradingBot_V1.6_Adaptive_Complete_CORRECTED.ipynb` ⭐ Main notebook
- `session_filter_patch.py` ⭐ Session filter (V1.8)
- `infrastructure_patch.py` ⭐ Database + Telegram integration
- `trading_database.py` ⭐ SQLite database
- `telegram_notifier.py` ⭐ Telegram bot
- `telegram_config.json` ⭐ Your credentials (KEEP PRIVATE!)
- `trading_bot.db` ⭐ Your trade data
**Dashboard & Tools:**
- `trading_dashboard.py` ⭐ Streamlit dashboard
- `import_json_to_db.py` ⭐ JSON import tool
**Data:**
- `trade_performance_v16_XAUUSD_202510.json` 📊 Historical data (October)
- `trade_performance_v16_XAUUSD_202511.json` 📊 Historical data (November)
**Documentation (Active):**
- `V1.8_AGGRESSIVE_MODE_AKTIVIERT.md` 📖 Current version docs
- `FIX_DUPLICATE_SCHEDULER.md` 📖 Critical fix guide
- `DASHBOARD_WINDOWS_SERVER.md` 📖 Dashboard deployment
- `SQLITE_TELEGRAM_SETUP.md` 📖 Infrastructure setup
---
### 📦 ARCHIVE - Old/Reference Files
**Old Documentation (Superseded by V1.8):**
- `V1.6_CORRECTED_Dokumentation.md` → Archive
- `V1.7_SESSION_FILTER_AKTIVIERT.md` → Archive (now V1.8)
- `SESSION_FILTER_INSTALLATION.md` → Archive (covered in V1.8 docs)
- `CONFIDENCE_THRESHOLD_GUIDE.md` → Archive (info in session_filter_patch.py)
- `TradingBot_V1.6_Verbesserungsvorschlaege.md` → Archive
- `Implementierungsplan_V1.6_to_V2.0.md` → Archive
**Development/Deployment Docs (Still useful but can be archived):**
- `VPS_DEPLOYMENT_V1.8.md` → Keep or Archive (covered in DASHBOARD_WINDOWS_SERVER.md)
- `DASHBOARD_VPS_DEPLOYMENT.md` → Archive (Windows version is newer)
- `QUICK_START_INFRASTRUCTURE.md` → Archive (covered in SQLITE_TELEGRAM_SETUP.md)
- `NOTEBOOK_FIX_TRADE_LOGGING.md` → Archive (fix already applied)
**Analysis Scripts (Optional - can archive if not used):**
- `analyze_mt5_profitability.py` → Archive (Dashboard does this now)
- `analyze_performance.py` → Archive (Dashboard does this now)
- `analyze_performance_simple.py` → Archive (Dashboard does this now)
- `check_database_logs.py` → Archive (Dashboard replaced this)
**Template:**
- `telegram_config_template.json` → Keep (useful for setup on new systems)
---
## 🗂️ Recommended Folder Structure
```
placeorder/
├── 📁 production/ # Active files
│ ├── TradingBot_V1.6_Adaptive_Complete_CORRECTED.ipynb
│ ├── session_filter_patch.py
│ ├── infrastructure_patch.py
│ ├── trading_database.py
│ ├── telegram_notifier.py
│ ├── trading_dashboard.py
│ ├── import_json_to_db.py
│ ├── telegram_config.json
│ └── trading_bot.db
│
├── 📁 docs/ # Current documentation
│ ├── V1.8_AGGRESSIVE_MODE_AKTIVIERT.md
│ ├── FIX_DUPLICATE_SCHEDULER.md
│ ├── DASHBOARD_WINDOWS_SERVER.md
│ ├── SQLITE_TELEGRAM_SETUP.md
│ └── telegram_config_template.json
│
├── 📁 data/ # Trade data
│ ├── trade_performance_v16_XAUUSD_202510.json
│ └── trade_performance_v16_XAUUSD_202511.json
│
└── 📁 archive/ # Old files
├── docs/
│ ├── V1.6_CORRECTED_Dokumentation.md
│ ├── V1.7_SESSION_FILTER_AKTIVIERT.md
│ ├── SESSION_FILTER_INSTALLATION.md
│ ├── CONFIDENCE_THRESHOLD_GUIDE.md
│ ├── TradingBot_V1.6_Verbesserungsvorschlaege.md
│ ├── Implementierungsplan_V1.6_to_V2.0.md
│ ├── VPS_DEPLOYMENT_V1.8.md
│ ├── DASHBOARD_VPS_DEPLOYMENT.md
│ ├── QUICK_START_INFRASTRUCTURE.md
│ └── NOTEBOOK_FIX_TRADE_LOGGING.md
│
└── scripts/
├── analyze_mt5_profitability.py
├── analyze_performance.py
├── analyze_performance_simple.py
└── check_database_logs.py
```
---
## 🚀 Quick Cleanup Actions
### Option 1: Manual Cleanup (Safest)
```bash
# Create folders
mkdir -p production docs data archive/docs archive/scripts
# Move production files
mv TradingBot_V1.6_Adaptive_Complete_CORRECTED.ipynb production/
mv session_filter_patch.py infrastructure_patch.py production/
mv trading_database.py telegram_notifier.py production/
mv trading_dashboard.py import_json_to_db.py production/
mv telegram_config.json trading_bot.db production/
# Move current docs
mv V1.8_AGGRESSIVE_MODE_AKTIVIERT.md docs/
mv FIX_DUPLICATE_SCHEDULER.md docs/
mv DASHBOARD_WINDOWS_SERVER.md docs/
mv SQLITE_TELEGRAM_SETUP.md docs/
mv telegram_config_template.json docs/
# Move data
mv trade_performance_v16_XAUUSD_*.json data/
# Archive old docs
mv V1.6_CORRECTED_Dokumentation.md archive/docs/
mv V1.7_SESSION_FILTER_AKTIVIERT.md archive/docs/
mv SESSION_FILTER_INSTALLATION.md archive/docs/
mv CONFIDENCE_THRESHOLD_GUIDE.md archive/docs/
mv TradingBot_V1.6_Verbesserungsvorschlaege.md archive/docs/
mv Implementierungsplan_V1.6_to_V2.0.md archive/docs/
mv VPS_DEPLOYMENT_V1.8.md archive/docs/
mv DASHBOARD_VPS_DEPLOYMENT.md archive/docs/
mv QUICK_START_INFRASTRUCTURE.md archive/docs/
mv NOTEBOOK_FIX_TRADE_LOGGING.md archive/docs/
# Archive old scripts
mv analyze_*.py archive/scripts/
mv check_database_logs.py archive/scripts/
```
### Option 2: Simple Cleanup (Just Archive)
```bash
# Create archive folder
mkdir -p archive
# Move old files
mv V1.6_CORRECTED_Dokumentation.md archive/
mv V1.7_SESSION_FILTER_AKTIVIERT.md archive/
mv SESSION_FILTER_INSTALLATION.md archive/
mv CONFIDENCE_THRESHOLD_GUIDE.md archive/
mv TradingBot_V1.6_Verbesserungsvorschlaege.md archive/
mv Implementierungsplan_V1.6_to_V2.0.md archive/
mv VPS_DEPLOYMENT_V1.8.md archive/
mv DASHBOARD_VPS_DEPLOYMENT.md archive/
mv QUICK_START_INFRASTRUCTURE.md archive/
mv NOTEBOOK_FIX_TRADE_LOGGING.md archive/
mv analyze_*.py archive/
mv check_database_logs.py archive/
```
### Option 3: Aggressive Cleanup (Delete Archive)
**⚠️ ONLY if you're sure you don't need old docs!**
```bash
# Delete old docs
rm V1.6_CORRECTED_Dokumentation.md
rm V1.7_SESSION_FILTER_AKTIVIERT.md
rm SESSION_FILTER_INSTALLATION.md
rm CONFIDENCE_THRESHOLD_GUIDE.md
rm TradingBot_V1.6_Verbesserungsvorschlaege.md
rm Implementierungsplan_V1.6_to_V2.0.md
rm VPS_DEPLOYMENT_V1.8.md
rm DASHBOARD_VPS_DEPLOYMENT.md
rm QUICK_START_INFRASTRUCTURE.md
rm NOTEBOOK_FIX_TRADE_LOGGING.md
# Delete old scripts (replaced by dashboard)
rm analyze_mt5_profitability.py
rm analyze_performance.py
rm analyze_performance_simple.py
rm check_database_logs.py
```
---
## 📋 Minimal Production Setup (What you NEED)
For clean Windows Server deployment, you only need these files:
**Essential Files (13 files):**
```
1. TradingBot_V1.6_Adaptive_Complete_CORRECTED.ipynb
2. session_filter_patch.py
3. infrastructure_patch.py
4. trading_database.py
5. telegram_notifier.py
6. telegram_config.json
7. trading_dashboard.py
8. import_json_to_db.py (optional, for historical data)
Documentation:
9. V1.8_AGGRESSIVE_MODE_AKTIVIERT.md
10. FIX_DUPLICATE_SCHEDULER.md
11. DASHBOARD_WINDOWS_SERVER.md
12. SQLITE_TELEGRAM_SETUP.md
13. telegram_config_template.json
```
**Generated at Runtime:**
- `trading_bot.db` (created by bot)
- Performance JSON files (created by bot)
---
## 🎯 Recommendation
**My Suggestion: Option 2 (Simple Archive)**
1. Create `archive/` folder
2. Move old docs/scripts there
3. Keep everything accessible but organized
4. Easy to reference if needed
**Benefits:**
- ✅ Clean main directory
- ✅ Easy to find current files
- ✅ Old docs still accessible
- ✅ Safe (nothing deleted)
**Execute with:**
```bash
cd "/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/FinancialTrading/PlaceOrder/placeorder"
# Run Option 2 commands above
```
---
## 📦 What to Deploy to Windows Server
**Copy only these to Windows Server:**
```
Essential Production Files:
1. TradingBot_V1.6_Adaptive_Complete_CORRECTED.ipynb
2. session_filter_patch.py
3. infrastructure_patch.py
4. trading_database.py
5. telegram_notifier.py
6. telegram_config.json
7. trading_dashboard.py
8. import_json_to_db.py (if you want to import JSON data)
Optional:
9. trade_performance_v16_XAUUSD_*.json (historical data)
```
**Don't copy:**
- Documentation (read on Mac)
- Analysis scripts (replaced by dashboard)
- Archive folder (not needed)
---
Would you like me to execute the cleanup for you? Choose:
- **A)** Option 1 - Full folder structure
- **B)** Option 2 - Simple archive ⭐ Recommended
- **C)** Option 3 - Delete old files
- **D)** Do it manually
-106
View File
@@ -1,106 +0,0 @@
"""
QUICK FIX: Position Control Patch
Füge diese Funktionen zu deinem bestehenden TradingBot_V1.4_Complete.ipynb hinzu
"""
def check_existing_positions_simple(symbol="XAUUSD", strategy_name="TradingBot_V1.4_Complete"):
"""
Einfache Position-Überprüfung für bestehende Notebooks
"""
try:
positions = mt.positions_get(symbol=symbol)
if positions is None:
return False, 0
# Zähle Positionen mit unserem Strategy-Namen
strategy_positions = 0
for pos in positions:
if strategy_name in pos.comment:
strategy_positions += 1
return strategy_positions > 0, strategy_positions
except:
return False, 0
def execute_trade_v2_with_simple_position_control(
symbol="XAUUSD",
atr_mult=1.5,
base_confidence=70,
max_risk_per_trade=0.01,
risk_filter=True,
min_atr=0.0010,
use_pullback_entry=True,
debug=True
):
"""
QUICK FIX: Füge diese Funktion zu deinem bestehenden Notebook hinzu
Ersetzt deine bestehende execute_trade_v2() Funktion
"""
# WICHTIG: Position-Check ZUERST!
has_position, position_count = check_existing_positions_simple(symbol, strategy_name)
if has_position:
if debug:
print(f"🛑 TRADE BLOCKIERT: {position_count} Position(en) bereits aktiv für {symbol}")
# Zeige bestehende Positionen
positions = mt.positions_get(symbol=symbol)
if positions:
for pos in positions:
if strategy_name in pos.comment:
profit_emoji = "🟢" if pos.profit >= 0 else "🔴"
print(f" Aktive Position: {'BUY' if pos.type == 0 else 'SELL'} {pos.volume} @ {pos.price_open} | Profit: {profit_emoji} {pos.profit:.2f}")
return None
print(f"✅ Position-Check OK: Keine aktiven Positionen für {symbol}")
# AB HIER: Deine bestehende execute_trade_v2 Logik
# (Kopiere deine bestehende Funktion hier hin, aber mit Position-Check am Anfang)
# Vereinfachte Version für Demonstration:
signal_info = extended_top_down_v2(symbol)
if signal_info is None:
print("❌ Signal-Analyse fehlgeschlagen")
return None
entry_signal = signal_info["entry_signal"]
confidence = signal_info["confidence"]
adaptive_threshold = signal_info["adaptive_threshold"]
if entry_signal == 0:
print(f"⏸️ No entry signal (Confidence: {confidence}%, Threshold: {adaptive_threshold}%)")
return None
if confidence < adaptive_threshold:
print(f"⏸️ Confidence too low: {confidence}% < {adaptive_threshold}%")
return None
# FINAL POSITION CHECK vor Order (Sicherheit)
final_check, _ = check_existing_positions_simple(symbol, strategy_name)
if final_check:
print(f"🛑 LAST-MINUTE BLOCK: Position wurde zwischen Checks eröffnet!")
return None
# Hier würde deine normale Trading-Logik kommen
print(f"🚀 WOULD EXECUTE TRADE: {'LONG' if entry_signal == 1 else 'SHORT'}")
print(f"Confidence: {confidence}% | Quality: {signal_info['signal_quality']}")
# Für echte Ausführung: Uncomment die nächste Zeile und füge deine market_order Logik hinzu
# return market_order(symbol, volume, order_type, stoploss, take_profit)
return "DEMO_ORDER_RESULT" # Placeholder für Demo
print("✅ Simple Position Control Patch ready")
# ANLEITUNG FÜR DEIN BESTEHENDES NOTEBOOK:
print("\\n📋 ANLEITUNG für dein bestehendes Notebook:")
print("1. Kopiere check_existing_positions_simple() in eine neue Zelle")
print("2. Ersetze deine execute_trade_v2() durch execute_trade_v2_with_simple_position_control()")
print("3. Oder füge am Anfang deiner bestehenden execute_trade_v2() den Position-Check hinzu:")
print("\\n # Position-Check am Anfang der Funktion:")
print(" has_position, position_count = check_existing_positions_simple(symbol, strategy_name)")
print(" if has_position:")
print(" print(f'🛑 TRADE BLOCKIERT: {position_count} Position(en) aktiv')")
print(" return None")
print("\\n4. Fertig! Dein Bot handelt jetzt maximal 1x gleichzeitig.")
-244
View File
@@ -1,244 +0,0 @@
# TradingBot V1.4 - Optimized Version
## 🚀 Überblick
TradingBot V1.4 ist eine erheblich verbesserte Version deines ursprünglichen Trading Bots mit intelligenten Anpassungen an verschiedene Marktbedingungen.
## 📁 Dateien
- `TradingBot_V1.4_Optimized.py` - Hauptfunktionen der optimierten Logik
- `TradingBot_V1.4_Integration.ipynb` - Jupyter Notebook mit vollständiger Integration
- `config_v1.4.json` - Konfigurationsdatei für alle Parameter
- `TradingBot_V1.3_backup_*` - Backup deiner ursprünglichen Datei
## 🎯 Hauptverbesserungen
### 1. **Adaptive Confidence Threshold**
```python
# Statt fixer 80% wird automatisch angepasst:
Trending Markets: 60-75%
Ranging Markets: 85%
Volatile Markets: 90%
```
### 2. **Market Regime Detection**
- **Trending**: ADX > 25, klare Richtung
- **Ranging**: ADX < 20, seitwärts bewegung
- **Volatile**: Hohe Volatilitäts-Cluster
### 3. **Entry Timing Optimization**
- Wartet auf Pullbacks zu EMA21
- Bessere Risk/Reward durch optimiertes Timing
- Regime-abhängige Entry-Kriterien
### 4. **Risk-Adjusted Signal Strength**
```python
signal_strength = confidence × trend_strength × rrr
# Mindestens 100 für Entry, 150+ für "excellent" Signals
```
### 5. **Performance Monitoring**
- Automatisches Logging aller Signale
- JSON-Export für Analyse
- Regime-basierte Performance-Statistiken
## 📊 Vergleich V1.3 vs V1.4
| Feature | V1.3 | V1.4 |
|---------|------|------|
| Confidence Threshold | Fixed 80% | Adaptive 60-90% |
| Market Regime | Ignoriert | Aktive Erkennung |
| Entry Timing | Sofort | Pullback-optimiert |
| Performance Tracking | Manuell | Automatisch |
| Parameter | Statisch | Dynamisch |
## 🛠️ Installation & Setup
### 1. Dateien kopieren
```bash
# Alle V1.4 Dateien sind bereits in deinem Verzeichnis:
/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/FinancialTrading/PlaceOrder/placeorder/
```
### 2. Jupyter Notebook öffnen
```bash
# Öffne: TradingBot_V1.4_Integration.ipynb
# Führe alle Zellen aus
```
### 3. Konfiguration anpassen (optional)
```json
// Editiere config_v1.4.json für deine Bedürfnisse
{
"trading_config": {
"symbol": "XAUUSD",
"base_confidence": 70,
"max_risk_per_trade": 0.01
}
}
```
## 🔄 Migration von V1.3 zu V1.4
### Option 1: Komplette Migration (empfohlen)
1. Verwende `TradingBot_V1.4_Integration.ipynb` als neues Hauptnotebook
2. Deine bestehenden Funktionen werden automatisch integriert
3. Alle Verbesserungen sind sofort aktiv
### Option 2: Schrittweise Integration
1. Kopiere einzelne Funktionen aus `TradingBot_V1.4_Optimized.py`
2. Ersetze in deinem V1.3 Notebook:
- `extended_top_down()` → `extended_top_down_v2()`
- `execute_trade()` → `execute_trade_v2()`
## 📈 Verwendung
### Schnellstart
```python
from TradingBot_V1.4_Optimized import extended_top_down_v2, execute_trade_v2
# Analysiere aktuelles Signal
signal_info = extended_top_down_v2("XAUUSD")
print(f"Signal: {signal_info['entry_signal']}")
print(f"Quality: {signal_info['signal_quality']}")
print(f"Regime: {signal_info['market_regime']['regime']}")
# Führe optimierten Trade aus
result = execute_trade_v2(
symbol="XAUUSD",
base_confidence=70,
use_pullback_entry=True
)
```
### Automatisierung
```python
# Setup für automatisierten Handel
from apscheduler.schedulers.background import BackgroundScheduler
scheduler = BackgroundScheduler()
scheduler.add_job(
execute_trade_v2,
'cron',
minute='*/5', # Alle 5 Minuten
kwargs={'symbol': 'XAUUSD', 'debug': True}
)
scheduler.start()
```
## 📊 Performance Monitoring
### Logs prüfen
```python
from TradingBot_V1.4_Optimized import analyze_performance
# Analysiere letzte 7 Tage
analyze_performance("XAUUSD", days_back=7)
```
### Output:
```
📊 PERFORMANCE ANALYSIS - Last 7 days
Total Trades: 12
By Market Regime:
TRENDING: 8 (66.7%)
RANGING: 3 (25.0%)
VOLATILE: 1 (8.3%)
By Signal Quality:
EXCELLENT: 4 (33.3%)
GOOD: 6 (50.0%)
FAIR: 2 (16.7%)
```
## ⚙️ Konfiguration
### Wichtige Parameter
```python
# In config_v1.4.json oder direkt im Code:
ADAPTIVE_THRESHOLDS = {
'trending': -10, # 10% niedrigere Confidence in Trends
'ranging': +15, # 15% höhere Confidence in Ranges
'volatile': +20 # 20% höhere Confidence bei Volatilität
}
RISK_SETTINGS = {
'max_risk_per_trade': 0.01, # 1% pro Trade
'max_daily_loss': 0.05, # 5% maximaler Tagesverlust
'use_pullback_entry': True # Warte auf besseres Timing
}
```
## 🧪 Testing & Validation
### 1. Demo-Modus Test
```python
# Führe 1-2 Wochen im Demo-Modus aus
# Überwache Performance-Logs
# Validiere Verbesserungen gegenüber V1.3
```
### 2. Parameter-Optimierung
```python
# Basierend auf Demo-Ergebnissen:
# - Anpassung der Confidence-Schwellen
# - Feintuning der Regime-Erkennung
# - Optimierung der Entry-Timing-Parameter
```
## ⚠️ Wichtige Hinweise
### Risiken
- **Neue Logik**: Teste ausführlich im Demo-Modus
- **Parameter**: Beginne mit konservativen Einstellungen
- **Monitoring**: Überwache Performance täglich in der ersten Woche
### Backup
```bash
# Dein Original V1.3 ist gesichert als:
TradingBot_V1.3_backup_YYYYMMDD_HHMMSS.ipynb
```
### Support
Bei Fragen oder Problemen:
1. Prüfe die Debug-Ausgaben
2. Analysiere Performance-Logs
3. Validiere MT5-Verbindung
## 📝 Changelog V1.3 → V1.4
### ✅ Neue Features
- Market Regime Detection
- Adaptive Confidence Thresholds
- Pullback Entry Timing
- Risk-Adjusted Signal Strength
- Automatic Performance Logging
- Enhanced Debug Output
### 🔧 Verbesserungen
- Weighted Timeframe Analysis
- Dynamic Parameter Adjustment
- Better Risk Management
- Signal Quality Grading
- Configuration Management
### 🐛 Fixes
- Over-filtering durch zu hohe Confidence-Schwellen
- Fehlende Markt-Adaptation
- Späte Entry-Signale durch zu viele Filter
## 🎯 Nächste Schritte
1. **Sofort**: Teste V1.4 im Demo-Modus
2. **1 Woche**: Analysiere erste Performance-Daten
3. **2 Wochen**: Optimiere Parameter basierend auf Ergebnissen
4. **1 Monat**: Bei positiven Ergebnissen → Live-Trading
---
**Version**: 1.4.0
**Datum**: 2025-01-17
**Status**: Ready for Demo Testing
**Kompatibilität**: MT5, Python 3.7+
+692
View File
@@ -0,0 +1,692 @@
# 🗄️📱 SQLite + Telegram Integration Guide
**Version:** V1.8+
**Datum:** 26. November 2025
**Features:** Database Logging + Mobile Notifications
---
## 🎯 Was wird implementiert?
### 1. **SQLite Database** 🗄️
- Strukturiertes Trade Logging (statt JSON)
- Schnelle Performance-Queries
- Session/Confidence-basierte Analysen
- Historische Datenbank
### 2. **Telegram Notifications** 📱
- Live Trade Entry/Exit Benachrichtigungen
- Tägliche Performance Reports (22:00 UTC)
- Wöchentliche Summaries (Sonntag 23:00 UTC)
- Error Alerts
- Bot Status Updates
---
## 📦 Neue Dateien
| Datei | Beschreibung |
|-------|--------------|
| `trading_database.py` | SQLite Database Core |
| `telegram_notifier.py` | Telegram Integration |
| `infrastructure_patch.py` | Integration mit TradingBot |
| `telegram_config.json` | Telegram Konfiguration (erstellen!) |
| `trading_bot.db` | SQLite Database (automatisch erstellt) |
---
## 🚀 Setup Guide - Schritt für Schritt
### **PHASE 1: Telegram Bot erstellen (5 Minuten)**
#### Schritt 1.1: Bot erstellen bei @BotFather
1. Öffne Telegram
2. Suche nach `@BotFather`
3. Sende `/newbot`
4. Folge den Anweisungen:
- Bot Name: z.B. "My Trading Bot"
- Bot Username: z.B. "mytrading_bot" (muss auf "_bot" enden)
5. **Kopiere den Bot Token** (z.B. `1234567890:ABCdefGHIjklMNOpqrsTUVwxyz`)
#### Schritt 1.2: Chat ID herausfinden
1. Suche nach `@userinfobot` in Telegram
2. Sende `/start`
3. **Kopiere deine User ID** (z.B. `987654321`)
#### Schritt 1.3: Telegram Config erstellen
Erstelle eine neue Datei `telegram_config.json`:
```json
{
"bot_token": "1234567890:ABCdefGHIjklMNOpqrsTUVwxyz",
"chat_id": "987654321",
"notifications": {
"trade_entry": true,
"trade_exit": true,
"daily_report": true,
"weekly_report": true,
"error_alerts": true
},
"daily_report_time": "22:00",
"weekly_report_day": "Sunday"
}
```
**Wichtig:** Ersetze `bot_token` und `chat_id` mit deinen echten Werten!
#### Schritt 1.4: Bot testen
```bash
python telegram_notifier.py
```
**Erwartete Ausgabe:**
```
✅ Telegram Bot connected: @mytrading_bot
✅ Created telegram_config_template.json
```
Wenn erfolgreich, sende eine Test-Nachricht:
```python
from telegram_notifier import TelegramNotifier
notifier = TelegramNotifier(
bot_token='YOUR_BOT_TOKEN',
chat_id='YOUR_CHAT_ID'
)
notifier.send_message("🎉 Telegram Bot Test erfolgreich!")
```
Du solltest die Nachricht auf deinem Handy bekommen! 📱
---
### **PHASE 2: SQLite Database einrichten (2 Minuten)**
#### Schritt 2.1: Database erstellen
```bash
python trading_database.py
```
**Erwartete Ausgabe:**
```
🗄️ TRADING DATABASE - System Check
======================================================================
📊 Tables created: 3
✅ trades
✅ performance_summary
✅ bot_status
📈 Overall Statistics:
Total Trades: 0
Win Rate: 0%
Net Profit: $0
======================================================================
✅ Database ready!
```
#### Schritt 2.2: Existierende JSON Daten migrieren (optional)
Wenn du bereits JSON Performance-Dateien hast:
```python
from trading_database import TradingDatabase
db = TradingDatabase("trading_bot.db")
# Migriere alle JSON Files
import glob
json_files = glob.glob("trade_performance_*.json")
for json_file in json_files:
print(f"Migrating {json_file}...")
db.migrate_from_json(json_file)
db.close()
```
#### Schritt 2.3: Database prüfen
```python
from trading_database import TradingDatabase
db = TradingDatabase("trading_bot.db")
# Zeige alle Trades
trades = db.get_recent_trades(limit=10)
print(f"Total trades in DB: {len(trades)}")
# Session Performance
session_perf = db.get_session_performance(days=30)
for session, stats in session_perf.items():
print(f"{session}: {stats['total_profit']} profit, {stats['win_rate']}% WR")
db.close()
```
---
### **PHASE 3: Integration mit TradingBot (10 Minuten)**
#### Schritt 3.1: Imports hinzufügen
**Am Anfang deines Notebooks** (nach den MT5 Imports):
```python
# ==========================================
# INFRASTRUCTURE IMPORTS (NEU!)
# ==========================================
from infrastructure_patch import (
TradingInfrastructure,
create_scheduled_reports
)
from trading_database import TradingDatabase
from telegram_notifier import TelegramNotifier
```
#### Schritt 3.2: Infrastructure initialisieren
**Nach der MT5 Verbindung und VOR dem Scheduler**:
```python
# ==========================================
# INITIALIZE INFRASTRUCTURE
# ==========================================
print("🔧 Initializing Infrastructure...")
infra = TradingInfrastructure(
db_path="trading_bot.db",
enable_telegram=True, # Telegram aktivieren
enable_database=True # SQLite aktivieren
)
# Send Bot Started Notification
from session_filter_patch import SESSION_WHITELIST_CONFIG
bot_config = {
'version': 'V1.8',
'enabled_sessions': SESSION_WHITELIST_CONFIG['enabled_sessions'],
'base_confidence': SESSION_WHITELIST_CONFIG['base_confidence'],
'max_risk_per_trade': SESSION_WHITELIST_CONFIG['max_risk_per_trade']
}
infra.send_bot_started(bot_config)
print("✅ Infrastructure ready!")
```
**Du solltest jetzt auf Telegram eine "Bot Started" Nachricht bekommen!** 📱🚀
#### Schritt 3.3: Trade Logging hinzufügen
**Modifiziere deine `execute_trade_v2_adaptive` Funktion:**
**VORHER** (ca. Zeile wo Position geöffnet wird):
```python
result = mt.order_send(request)
if result.retcode == mt.TRADE_RETCODE_DONE:
logger.info(f"✅ {trade_type} position opened")
# ... existing code ...
```
**NACHHER** (mit Infrastructure Logging):
```python
result = mt.order_send(request)
if result.retcode == mt.TRADE_RETCODE_DONE:
logger.info(f"✅ {trade_type} position opened")
# ==========================================
# LOG TRADE ENTRY (NEU!)
# ==========================================
try:
# Hole Position Info
positions = mt.positions_get(symbol=symbol)
if positions:
position = positions[0]
# Erstelle Trade Data
trade_data = {
'ticket': position.ticket,
'position_id': position.identifier,
'symbol': symbol,
'strategy_name': strategy_name,
'type': 'BUY' if trade_type == 'BUY' else 'SELL',
'volume': volume,
'entry_price': position.price_open,
'sl_price': position.sl,
'tp_price': position.tp,
'entry_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
'session': rhythm_manager.get_current_session(),
'regime': regime,
'quality': quality,
'confidence': confidence,
'timeframe_alignment': timeframe_alignment,
'risk_amount': risk_amount,
'risk_pct': max_risk_per_trade
}
# Log to Database + Telegram
infra.log_trade_entry(trade_data)
except Exception as e:
logger.error(f"⚠️ Infrastructure logging failed: {e}")
# ==========================================
# ... existing code continues ...
```
#### Schritt 3.4: Exit Logging hinzufügen
**Wenn Trade geschlossen wird** (z.B. durch SL/TP):
Dies hängt davon ab, wie dein Bot Exits erkennt. Falls du einen Position Monitor hast:
```python
# Wenn Position geschlossen wurde
if position_closed:
exit_data = {
'exit_price': close_price,
'exit_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
'duration_hours': (close_time - open_time).total_seconds() / 3600,
'profit': profit,
'commission': commission,
'swap': swap,
'net_profit': net_profit,
'profit_pct': (net_profit / risk_amount) * 100 if risk_amount else 0,
'rr_ratio': abs(net_profit / risk_amount) if risk_amount else 0,
'exit_reason': 'tp' if hit_tp else 'sl' if hit_sl else 'manual'
}
# Log Exit
infra.log_trade_exit(ticket, exit_data)
```
#### Schritt 3.5: Scheduled Reports hinzufügen
**Nach dem Scheduler Setup**:
```python
# ==========================================
# SCHEDULER SETUP (existing)
# ==========================================
scheduler = BackgroundScheduler()
# ... existing jobs ...
# ==========================================
# ADD SCHEDULED REPORTS (NEU!)
# ==========================================
create_scheduled_reports(infra, scheduler)
# Start Scheduler
scheduler.start()
```
---
### **PHASE 4: Testing (5 Minuten)**
#### Test 1: Infrastructure Status
```python
# Prüfe ob alles läuft
print("\n🔍 Infrastructure Status:")
print(f" Database: {'✅' if infra.enable_database else '❌'}")
print(f" Telegram: {'✅' if infra.enable_telegram else '❌'}")
# Prüfe DB Stats
if infra.db:
stats = infra.db.get_overall_statistics(days=7)
print(f"\n📊 Last 7 Days:")
print(f" Trades: {stats.get('total_trades', 0)}")
print(f" Win Rate: {stats.get('win_rate', 0)}%")
print(f" Net Profit: ${stats.get('net_profit', 0):.2f}")
```
#### Test 2: Manual Telegram Test
```python
# Sende Test Notification
if infra.telegram:
infra.telegram.send_message("🧪 Test: Infrastructure is working!")
```
#### Test 3: Database Query
```python
# Query recent trades
if infra.db:
trades = infra.db.get_recent_trades(limit=5)
print(f"\n📝 Recent Trades: {len(trades)}")
for trade in trades:
print(f" {trade['symbol']} {trade['type']} @ {trade['entry_price']}")
```
---
## 📱 Was du auf Telegram sehen wirst
### Bot Started (sofort)
```
🚀 TradingBot Started
Version: V1.8
Time: 2025-11-26 14:30:00 UTC
⚙️ Configuration:
Active Sessions: NY
Confidence Threshold: 60%
Max Risk/Trade: 1.0%
✅ Bot is now monitoring the market
```
### Trade Entry (bei jedem Trade)
```
🟢 Trade Opened
Symbol: XAUUSD
Type: BUY
Entry: 2650.50
SL: 2645.50 | TP: 2660.50
Risk: $50.00 (1.0%)
Volume: 0.1 lots
🇺🇸 Session: NY
📊 Confidence: 72.5%
🎯 Quality: EXCELLENT
⏰ 2025-11-26 17:15:00 UTC
```
### Trade Exit (bei jedem Close)
```
✅ Trade Closed 🟢
Symbol: XAUUSD
Type: BUY
Entry: 2650.50
Exit: 2660.50
Profit: +$100.00
Duration: 2.5h
Exit Reason: TP
R:R Ratio: 2.00
⏰ 2025-11-26 19:45:00 UTC
```
### Daily Report (täglich 22:00 UTC)
```
📊 Daily Trading Report
📅 2025-11-26
━━━━━━━━━━━━━━━━━━━━
Trades: 3
Wins: 2 | Losses: 1
🎯 Win Rate: 66.7%
💰 Net Profit: $150.00
Gross Profit: $200.00
Gross Loss: $-50.00
Avg Trade: $50.00
━━━━━━━━━━━━━━━━━━━━
✅ Bot Status: Running
```
### Weekly Report (Sonntag 23:00 UTC)
```
📈 Weekly Trading Report
📅 2025-11-20 to 2025-11-26
━━━━━━━━━━━━━━━━━━━━
📊 Overall Performance
Total Trades: 21
Wins: 10 | Losses: 11
Win Rate: 47.6%
💰 Net Profit: $660.00
🟢 Profit Factor: 1.85
Avg Trade: $31.43
━━━━━━━━━━━━━━━━━━━━
📍 Session Performance
🇺🇸 NY: +$660.00 (47.6% WR) ✅
━━━━━━━━━━━━━━━━━━━━
✅ Bot Status: Running
```
---
## 🔍 Nützliche Database Queries
### Query 1: Session Performance (letzte 30 Tage)
```python
from trading_database import TradingDatabase
db = TradingDatabase("trading_bot.db")
session_perf = db.get_session_performance(days=30)
for session, stats in session_perf.items():
print(f"{session.upper()}:")
print(f" Trades: {stats['count']}")
print(f" Win Rate: {stats['win_rate']}%")
print(f" Profit: ${stats['total_profit']:.2f}")
print()
```
### Query 2: Confidence Analysis
```python
conf_analysis = db.get_confidence_analysis(days=30)
for conf_range, stats in conf_analysis.items():
print(f"Confidence {conf_range}:")
print(f" Trades: {stats['count']}")
print(f" Win Rate: {stats['win_rate']}%")
print(f" Profit: ${stats['total_profit']:.2f}")
print()
```
### Query 3: Best/Worst Trades
```python
# Best Trades
db.cursor.execute("""
SELECT symbol, type, entry_price, exit_price, net_profit, session
FROM trades
WHERE status = 'closed'
ORDER BY net_profit DESC
LIMIT 5
""")
print("🏆 Top 5 Trades:")
for row in db.cursor.fetchall():
print(f" {row['symbol']} {row['type']}: ${row['net_profit']:.2f} ({row['session']})")
# Worst Trades
db.cursor.execute("""
SELECT symbol, type, entry_price, exit_price, net_profit, session
FROM trades
WHERE status = 'closed'
ORDER BY net_profit ASC
LIMIT 5
""")
print("\n💔 Bottom 5 Trades:")
for row in db.cursor.fetchall():
print(f" {row['symbol']} {row['type']}: ${row['net_profit']:.2f} ({row['session']})")
db.close()
```
### Query 4: Daily Breakdown
```python
db.cursor.execute("""
SELECT
DATE(entry_time) as date,
COUNT(*) as trades,
SUM(CASE WHEN net_profit > 0 THEN 1 ELSE 0 END) as wins,
ROUND(SUM(net_profit), 2) as daily_profit
FROM trades
WHERE status = 'closed'
AND entry_time >= datetime('now', '-30 days')
GROUP BY DATE(entry_time)
ORDER BY date DESC
""")
print("📅 Daily Performance (Last 30 Days):")
for row in db.cursor.fetchall():
print(f" {row['date']}: {row['trades']} trades, {row['wins']} wins, ${row['daily_profit']}")
```
---
## 🛠️ Troubleshooting
### Problem 1: Telegram nicht verbunden
**Symptom:** `❌ Telegram connection failed`
**Lösung:**
1. Prüfe `telegram_config.json` existiert
2. Prüfe Bot Token ist korrekt
3. Prüfe Chat ID ist korrekt
4. Teste mit: `python telegram_notifier.py`
### Problem 2: Database locked
**Symptom:** `database is locked`
**Lösung:**
```python
# Stelle sicher nur eine Connection offen ist
db.close()
# ODER: Benutze Context Manager
with TradingDatabase("trading_bot.db") as db:
# queries...
pass # automatisch geschlossen
```
### Problem 3: Keine Notifications
**Symptom:** Bot läuft, aber keine Telegram Nachrichten
**Lösung:**
1. Prüfe `infra.enable_telegram` ist `True`
2. Sende Test-Nachricht manuell
3. Prüfe Bot ist nicht von @BotFather blockiert
4. Starte eine Konversation mit deinem Bot (sende `/start`)
### Problem 4: Alte Trades nicht in DB
**Symptom:** Database zeigt 0 Trades
**Lösung:**
```python
# Migriere JSON Daten
from infrastructure_patch import TradingInfrastructure
infra = TradingInfrastructure()
infra.migrate_json_files(".") # Migriert alle JSON Files
```
---
## 📊 Performance Vorteile
### Vorher (nur JSON):
- ❌ Schwer zu analysieren
- ❌ Manuelle Performance-Berechnung
- ❌ Keine Live Updates
- ❌ Keine Session-Analyse
### Nachher (SQLite + Telegram):
- ✅ Instant Queries
- ✅ Automatische Reports
- ✅ Mobile Benachrichtigungen
- ✅ Session/Confidence Analytics
- ✅ Historische Datenbank
---
## 🎯 Nächste Schritte
### Nach erfolgreicher Integration:
1. **1 Woche monitoren:**
- Prüfe tägliche Telegram Reports
- Verifiziere Database logging
- Teste Queries
2. **Performance analysieren:**
```python
# Nach 1 Woche
stats = infra.get_performance_summary(days=7)
print(stats)
```
3. **Optional - Custom Queries:**
- Erstelle eigene Performance-Metriken
- Exportiere Daten für Excel/Charts
- Backtesting mit historischen Daten
4. **Phase 2 Features** (später):
- Position Scaling basierend auf Confidence
- ML Signal Filter
- Multi-Symbol Support
---
## ✅ Checklist - Ist alles fertig?
- [ ] Telegram Bot erstellt (@BotFather)
- [ ] Chat ID erhalten (@userinfobot)
- [ ] `telegram_config.json` erstellt mit echten Werten
- [ ] `python telegram_notifier.py` läuft ohne Fehler
- [ ] `python trading_database.py` erstellt DB
- [ ] Alte JSON Daten migriert (optional)
- [ ] Infrastructure im Notebook initialisiert
- [ ] Trade Entry Logging hinzugefügt
- [ ] Trade Exit Logging hinzugefügt (wenn möglich)
- [ ] Scheduled Reports aktiviert
- [ ] Test-Trade durchgeführt → Telegram Notification erhalten
- [ ] Database Query funktioniert
- [ ] Bot auf VPS deployed
---
## 🎉 Zusammenfassung
Mit **SQLite + Telegram** hast du jetzt:
🗄️ **Strukturierte Datenbank** für alle Trades
📱 **Live Mobile Notifications** für jeden Trade
📊 **Automatische Performance Reports** täglich & wöchentlich
🔍 **Schnelle Analytics** mit SQL Queries
📈 **Historische Daten** für Backtesting
⚠️ **Error Alerts** wenn etwas schief geht
**V1.8 ist jetzt eine professionelle Trading-Platform!** 🚀
Bei Fragen oder Problemen: Check Troubleshooting oder frag nach! 💪
-354
View File
@@ -1,354 +0,0 @@
"""
TradingBot Diagnosis Tool
Hilft bei der Identifikation, warum der Bot nicht handelt
"""
import pandas as pd
import numpy as np
import MetaTrader5 as mt
import pandas_ta as ta
from tabulate import tabulate
def diagnose_trading_issue(symbol="XAUUSD"):
"""
Umfassende Diagnose warum der Bot nicht handelt
"""
print("🔍 TRADING BOT DIAGNOSIS")
print("=" * 50)
issues_found = []
# 1. MT5 Connection Check
print("\n1️⃣ MT5 Connection Check:")
terminal_info = mt.terminal_info()
if terminal_info:
print(" ✅ MT5 connected")
print(f" Company: {terminal_info.company}")
print(f" Connected: {terminal_info.connected}")
print(f" Trade allowed: {terminal_info.trade_allowed}")
if not terminal_info.trade_allowed:
issues_found.append("Trading not allowed in terminal")
else:
print(" ❌ MT5 not connected")
issues_found.append("MT5 connection failed")
return issues_found
# 2. Account Info Check
print("\n2️⃣ Account Info Check:")
account_info = mt.account_info()
if account_info:
print(f" ✅ Account: {account_info.login}")
print(f" Balance: {account_info.balance}")
print(f" Equity: {account_info.equity}")
print(f" Trade allowed: {account_info.trade_allowed}")
print(f" Trade mode: {account_info.trade_mode}")
if not account_info.trade_allowed:
issues_found.append("Trading not allowed on account")
else:
print(" ❌ Cannot get account info")
issues_found.append("Account info unavailable")
# 3. Symbol Info Check
print(f"\n3️⃣ Symbol Info Check ({symbol}):")
symbol_info = mt.symbol_info(symbol)
if symbol_info:
print(f" ✅ Symbol exists: {symbol_info.name}")
print(f" Trade mode: {symbol_info.trade_mode}")
print(f" Min volume: {symbol_info.volume_min}")
print(f" Max volume: {symbol_info.volume_max}")
print(f" Volume step: {symbol_info.volume_step}")
if symbol_info.trade_mode == 0:
issues_found.append(f"Trading disabled for {symbol}")
else:
print(f" ❌ Symbol {symbol} not found")
issues_found.append(f"Symbol {symbol} not available")
# 4. Market Hours Check
print("\n4️⃣ Market Hours Check:")
tick = mt.symbol_info_tick(symbol)
if tick:
print(f" ✅ Current price: Bid={tick.bid}, Ask={tick.ask}")
print(f" Last tick time: {pd.to_datetime(tick.time, unit='s')}")
spread = tick.ask - tick.bid
print(f" Spread: {spread:.5f}")
if spread > 0.01: # Sehr hoher Spread
issues_found.append(f"High spread: {spread:.5f}")
else:
print(" ❌ No current price data")
issues_found.append("No price data available")
# 5. Data Availability Check
print("\n5️⃣ Data Availability Check:")
timeframes_to_check = ["M5", "M15", "M30", "H1", "H4", "D1"]
tf_map = {"M5": mt.TIMEFRAME_M5, "M15": mt.TIMEFRAME_M15, "M30": mt.TIMEFRAME_M30,
"H1": mt.TIMEFRAME_H1, "H4": mt.TIMEFRAME_H4, "D1": mt.TIMEFRAME_D1}
data_status = []
for tf in timeframes_to_check:
rates = mt.copy_rates_from_pos(symbol, tf_map[tf], 0, 50)
if rates is not None and len(rates) > 0:
data_status.append([tf, "✅", len(rates), pd.to_datetime(rates[-1]['time'], unit='s')])
else:
data_status.append([tf, "❌", 0, "No data"])
issues_found.append(f"No data for {tf}")
print(tabulate(data_status, headers=["Timeframe", "Status", "Bars", "Last Update"], tablefmt="psql"))
return issues_found
def compare_v13_vs_v14_logic(symbol="XAUUSD"):
"""
Vergleicht warum V1.3 gehandelt hat aber V1.4 nicht
"""
print("\n🔄 COMPARING V1.3 vs V1.4 LOGIC")
print("=" * 50)
try:
# Simuliere V1.3 Logik (vereinfacht)
from TradingBot_V1.4_Fixed import extended_top_down_v2, get_rates
# Hole aktuelle Daten
signal_info = extended_top_down_v2(symbol, lookback=100)
if signal_info is None:
print("❌ Cannot get signal info")
return
confidence = signal_info['confidence']
trend = signal_info['top_down_trend']
signal_quality = signal_info['signal_quality']
regime = signal_info['market_regime']['regime']
adaptive_threshold = signal_info['adaptive_threshold']
# V1.3 Logic (fixed 80% threshold)
v13_threshold = 80
v13_would_trade = (trend != "sideways" and confidence >= v13_threshold)
# V1.4 Logic (adaptive threshold + quality filter)
v14_would_trade = (signal_info['entry_signal'] != 0)
print(f"\n📊 SIGNAL COMPARISON:")
comparison_data = [
["Metric", "V1.3 (Old)", "V1.4 (New)", "Impact"],
["Confidence", f"{confidence:.1f}%", f"{confidence:.1f}%", "Same"],
["Threshold", f"{v13_threshold}%", f"{adaptive_threshold}%", f"{adaptive_threshold-v13_threshold:+d}%"],
["Trend", trend, trend, "Same"],
["Would Trade", "✅" if v13_would_trade else "❌", "✅" if v14_would_trade else "❌", ""],
["Market Regime", "Not considered", regime, "New Filter"],
["Signal Quality", "Not checked", signal_quality, "New Filter"],
]
print(tabulate(comparison_data, headers="firstrow", tablefmt="psql"))
# Analyse warum nicht gehandelt wird
print(f"\n🔍 WHY NOT TRADING:")
if not v13_would_trade and not v14_would_trade:
print(" • Both versions agree: Confidence too low")
print(f" • Need: {v13_threshold}% (V1.3) or {adaptive_threshold}% (V1.4)")
print(f" • Have: {confidence:.1f}%")
elif v13_would_trade and not v14_would_trade:
print(" 🛡️ V1.4 is MORE SELECTIVE (this is good!)")
print(f" • V1.3 would trade with {confidence:.1f}% confidence")
print(f" • V1.4 requires {adaptive_threshold}% in {regime} market")
print(f" • Signal quality: {signal_quality}")
if regime == 'ranging':
print(" • RANGING market detected - higher threshold prevents false breakouts")
elif regime == 'volatile':
print(" • VOLATILE market detected - avoiding choppy conditions")
elif not v13_would_trade and v14_would_trade:
print(" 🚀 V1.4 FOUND OPPORTUNITY that V1.3 missed!")
print(f" • Adaptive threshold {adaptive_threshold}% < fixed 80%")
print(f" • Trading in {regime} market with {signal_quality} quality")
else:
print(" 🤝 Both versions would trade - check other filters")
return {
'v13_would_trade': v13_would_trade,
'v14_would_trade': v14_would_trade,
'confidence': confidence,
'adaptive_threshold': adaptive_threshold,
'regime': regime,
'signal_quality': signal_quality
}
except Exception as e:
print(f"❌ Error in comparison: {e}")
return None
def check_position_limits(symbol="XAUUSD"):
"""
Prüft ob Position-Limits das Trading verhindern
"""
print("\n📊 POSITION LIMITS CHECK")
print("=" * 30)
# Aktuelle Positionen
positions = mt.positions_get(symbol=symbol)
total_positions = mt.positions_total()
print(f"Current positions for {symbol}: {len(positions) if positions else 0}")
print(f"Total positions: {total_positions}")
if positions:
print("\nExisting positions:")
for pos in positions:
print(f" • {pos.type_str} {pos.volume} lots @ {pos.price_open}")
print(f" Comment: {pos.comment}")
print(f" Profit: {pos.profit}")
# Position Limits prüfen
# (Hier würdest du deine spezifischen Limits einbauen)
max_positions = 3 # Beispiel
if total_positions >= max_positions:
return f"Position limit reached: {total_positions}/{max_positions}"
return None
def suggest_quick_fixes():
"""
Schlägt schnelle Lösungen vor
"""
print("\n🔧 QUICK FIXES TO TRY")
print("=" * 30)
fixes = [
"1️⃣ Lower adaptive threshold temporarily:",
" adaptive_threshold = max(60, adaptive_threshold - 10)",
"",
"2️⃣ Bypass pullback entry timing:",
" use_pullback_entry = False",
"",
"3️⃣ Reduce minimum signal quality:",
" Allow 'fair' quality signals temporarily",
"",
"4️⃣ Check if V1.3 logic still works:",
" Run your original extended_top_down() function",
"",
"5️⃣ Force a test trade:",
" market_order(symbol, 0.01, 'buy') # Small test",
]
for fix in fixes:
print(fix)
def emergency_v13_mode(symbol="XAUUSD"):
"""
Notfall-Modus: Nutze V1.3 Logik mit V1.4 Verbesserungen
"""
print("\n🚨 EMERGENCY V1.3 MODE")
print("=" * 30)
emergency_code = '''
def emergency_trading_signal(symbol="XAUUSD"):
"""
Vereinfachte V1.3-ähnliche Logik als Fallback
"""
from TradingBot_V1.4_Fixed import get_rates
import pandas_ta as ta
from scipy.signal import savgol_filter
from sklearn.linear_model import LinearRegression
import numpy as np
# Hole H4 und M5 Daten
h4_df = get_rates("h4", 150, symbol)
m5_df = get_rates("m5", 100, symbol)
if h4_df is None or m5_df is None:
return 0, "No data"
# Einfache Trend-Analyse H4
h4_df['close_smooth'] = savgol_filter(h4_df['close'], 15, 3)
X = np.arange(len(h4_df)).reshape(-1, 1)
y = h4_df['close_smooth'].values
model = LinearRegression().fit(X, y)
slope = model.coef_[0]
atr = h4_df['atr'].iloc[-1]
slope_threshold = atr * 0.0001
if slope > slope_threshold:
h4_trend = "uptrend"
elif slope < -slope_threshold:
h4_trend = "downtrend"
else:
h4_trend = "sideways"
# Einfache Confidence (Prozent der letzten 6 Timeframes die aligned sind)
# Vereinfacht: nur prüfen ob H4 und M5 aligned sind
m5_df['close_smooth'] = savgol_filter(m5_df['close'], 15, 3)
X_m5 = np.arange(len(m5_df)).reshape(-1, 1)
y_m5 = m5_df['close_smooth'].values
model_m5 = LinearRegression().fit(X_m5, y_m5)
slope_m5 = model_m5.coef_[0]
atr_m5 = m5_df['atr'].iloc[-1]
slope_threshold_m5 = atr_m5 * 0.0001
if slope_m5 > slope_threshold_m5:
m5_trend = "uptrend"
elif slope_m5 < -slope_threshold_m5:
m5_trend = "downtrend"
else:
m5_trend = "sideways"
# Confidence basierend auf Alignment
if h4_trend == m5_trend and h4_trend != "sideways":
confidence = 85 # Hoch wenn aligned
signal = 1 if h4_trend == "uptrend" else -1
else:
confidence = 45 # Niedrig wenn nicht aligned
signal = 0
# V1.3-ähnliche Schwelle (niedriger als adaptive)
threshold = 70 # Niedrigere Schwelle als V1.4
if confidence >= threshold and signal != 0:
return signal, f"Emergency signal: {h4_trend}, confidence: {confidence}%"
else:
return 0, f"No signal: confidence {confidence}% < {threshold}%"
# Test:
signal, reason = emergency_trading_signal("XAUUSD")
print(f"Emergency Signal: {signal}")
print(f"Reason: {reason}")
'''
print("Copy this code to test emergency V1.3-like logic:")
print(emergency_code)
if __name__ == "__main__":
# Hauptdiagnose
symbol = "XAUUSD"
print("🚨 TRADING BOT NOT WORKING - DIAGNOSIS")
print("=" * 60)
# 1. Grundlegende Checks
issues = diagnose_trading_issue(symbol)
# 2. Logic Comparison
comparison = compare_v13_vs_v14_logic(symbol)
# 3. Position Limits
position_issue = check_position_limits(symbol)
if position_issue:
issues.append(position_issue)
# 4. Zusammenfassung
print(f"\n📋 ISSUES SUMMARY:")
if issues:
for i, issue in enumerate(issues, 1):
print(f" {i}. {issue}")
else:
print(" ✅ No technical issues found")
# 5. Lösungsvorschläge
suggest_quick_fixes()
# 6. Emergency Mode
emergency_v13_mode(symbol)
-367
View File
@@ -1,367 +0,0 @@
"""
Position Control für TradingBot V1.4
Verhindert mehrfache gleichzeitige Trades
"""
import MetaTrader5 as mt
import pandas as pd
from datetime import datetime
def check_existing_positions(symbol="XAUUSD", strategy_name="TradingBot_V1.4_Complete"):
"""
Überprüft ob bereits Positionen für das Symbol und die Strategie existieren
Returns:
- has_position: bool - True wenn bereits Position existiert
- position_info: dict - Info über bestehende Position(en)
"""
try:
# Alle Positionen für das Symbol abrufen
positions = mt.positions_get(symbol=symbol)
if positions is None:
return False, {"count": 0, "details": []}
# Filter nach Strategie-Namen im Kommentar
strategy_positions = []
for pos in positions:
if strategy_name in pos.comment:
strategy_positions.append({
"ticket": pos.ticket,
"type": "BUY" if pos.type == 0 else "SELL",
"volume": pos.volume,
"price_open": pos.price_open,
"profit": pos.profit,
"comment": pos.comment,
"time_open": pd.to_datetime(pos.time, unit='s')
})
has_position = len(strategy_positions) > 0
position_info = {
"count": len(strategy_positions),
"details": strategy_positions
}
return has_position, position_info
except Exception as e:
print(f"Error checking positions: {e}")
return False, {"count": 0, "details": []}
def get_position_summary(symbol="XAUUSD", strategy_name="TradingBot_V1.4_Complete"):
"""
Gibt eine übersichtliche Zusammenfassung der aktuellen Positionen
"""
has_position, position_info = check_existing_positions(symbol, strategy_name)
print(f"\n📊 POSITION SUMMARY für {symbol}")
print("=" * 50)
if not has_position:
print("✅ Keine aktiven Positionen - bereit für neuen Trade")
return False
print(f"⚠️ {position_info['count']} aktive Position(en) gefunden:")
for i, pos in enumerate(position_info['details'], 1):
profit_emoji = "🟢" if pos['profit'] >= 0 else "🔴"
print(f"\n Position {i}:")
print(f" Ticket: {pos['ticket']}")
print(f" Typ: {pos['type']}")
print(f" Volumen: {pos['volume']}")
print(f" Eröffnungspreis: {pos['price_open']}")
print(f" Profit: {profit_emoji} {pos['profit']:.2f}")
print(f" Eröffnungszeit: {pos['time_open']}")
print(f" Kommentar: {pos['comment']}")
print(f"\n🛑 TRADING BLOCKIERT - Maximal 1 Position erlaubt")
return True
def close_existing_positions(symbol="XAUUSD", strategy_name="TradingBot_V1.4_Complete", force_close=False):
"""
Schließt bestehende Positionen (optional)
Args:
force_close: bool - Wenn True, schließt alle Positionen sofort
"""
has_position, position_info = check_existing_positions(symbol, strategy_name)
if not has_position:
print("✅ Keine Positionen zum Schließen")
return True
if not force_close:
print(f"⚠️ {position_info['count']} Position(en) gefunden. Verwende force_close=True zum Schließen.")
return False
print(f"🔄 Schließe {position_info['count']} Position(en)...")
success_count = 0
for pos in position_info['details']:
try:
# Position schließen
close_request = {
"action": mt.TRADE_ACTION_DEAL,
"symbol": symbol,
"volume": pos['volume'],
"type": mt.ORDER_TYPE_SELL if pos['type'] == "BUY" else mt.ORDER_TYPE_BUY,
"position": pos['ticket'],
"price": mt.symbol_info_tick(symbol).bid if pos['type'] == "BUY" else mt.symbol_info_tick(symbol).ask,
"deviation": 20,
"magic": 234000,
"comment": f"Close {strategy_name}",
"type_time": mt.ORDER_TIME_GTC,
"type_filling": mt.ORDER_FILLING_IOC,
}
result = mt.order_send(close_request)
if result.retcode == mt.TRADE_RETCODE_DONE:
print(f"✅ Position {pos['ticket']} erfolgreich geschlossen")
success_count += 1
else:
print(f"❌ Fehler beim Schließen von Position {pos['ticket']}: {result.comment}")
except Exception as e:
print(f"❌ Exception beim Schließen von Position {pos['ticket']}: {e}")
print(f"📊 {success_count}/{len(position_info['details'])} Positionen erfolgreich geschlossen")
return success_count == len(position_info['details'])
def enhanced_execute_trade_v2_with_position_control(
symbol="XAUUSD",
atr_mult=1.5,
base_confidence=70,
max_risk_per_trade=0.01,
risk_filter=True,
min_atr=0.0010,
use_pullback_entry=True,
max_positions=1, # NEU: Maximale Anzahl Positionen
strategy_name="TradingBot_V1.4_Complete",
debug=True
):
"""
Enhanced Execute Trade mit Position-Kontrolle
"""
# WICHTIG: Zuerst Position-Check
print(f"\n🔍 POSITION CHECK für {symbol}")
has_position, position_info = check_existing_positions(symbol, strategy_name)
if has_position and position_info['count'] >= max_positions:
if debug:
print(f"🛑 TRADE BLOCKIERT: {position_info['count']}/{max_positions} Positionen bereits aktiv")
for pos in position_info['details']:
profit_emoji = "🟢" if pos['profit'] >= 0 else "🔴"
print(f" Position: {pos['type']} {pos['volume']} @ {pos['price_open']} | Profit: {profit_emoji} {pos['profit']:.2f}")
return None
print(f"✅ Position-Check OK: {position_info['count']}/{max_positions} Positionen")
# Hier würde deine bestehende execute_trade_v2 Logik kommen
# Ich importiere sie von deinem bestehenden Code
try:
# Import der bestehenden Funktionen (angepasst an deine Struktur)
from TradingBot_V1_4_Complete import extended_top_down_v2, check_risk_limits, market_order, check_pullback_entry
# Signal-Analyse
signal_info = extended_top_down_v2(symbol)
if signal_info is None:
print("❌ Signal-Analyse fehlgeschlagen")
return None
entry_signal = signal_info["entry_signal"]
confidence = signal_info["confidence"]
adaptive_threshold = signal_info["adaptive_threshold"]
signal_quality = signal_info["signal_quality"]
market_regime = signal_info["market_regime"]
# Get Price/ATR from M5
m5_info = signal_info["trend_info"]["M5"]
price = m5_info["price"]
atr = m5_info["atr"]
# Enhanced Pre-checks
reason = ""
if confidence < adaptive_threshold:
reason = f"Confidence {confidence}% < adaptive threshold {adaptive_threshold}%"
elif entry_signal == 0:
reason = f"No entry signal (Trend: {signal_info['top_down_trend']}, Regime: {market_regime['regime']})"
elif price is None or atr is None:
reason = "Price/ATR not available"
elif risk_filter and atr < min_atr:
reason = f"ATR {atr:.5f} < min_atr {min_atr}"
elif signal_quality == "none":
reason = "Signal quality insufficient"
else:
# Entry Timing Check
if use_pullback_entry:
pullback_ok, pullback_reason = check_pullback_entry(symbol, signal_info)
if not pullback_ok:
reason = f"Entry timing: {pullback_reason}"
if not reason:
# Risk Checks
risk_ok = check_risk_limits(symbol, max_risk_per_trade=max_risk_per_trade)
if not risk_ok:
reason = "Risk limits exceeded"
# Execute Trade if all checks pass
if not reason:
# Enhanced SL/TP calculation based on regime
regime_mult = 1.0
if market_regime['regime'] == 'volatile':
regime_mult = 1.3 # Wider stops in volatile markets
elif market_regime['regime'] == 'ranging':
regime_mult = 0.8 # Tighter stops in ranging markets
adjusted_atr_mult = atr_mult * regime_mult
if entry_signal == 1: # Long
stop_loss = price - adjusted_atr_mult * atr
take_profit = price + adjusted_atr_mult * atr * 2.5
else: # Short
stop_loss = price + adjusted_atr_mult * atr
take_profit = price - adjusted_atr_mult * atr * 2.5
# Dynamic Position Sizing
stop_distance = adjusted_atr_mult * atr
account_info = mt.account_info()
if account_info:
balance = account_info.balance
risk_amount = balance * max_risk_per_trade
if symbol == "XAUUSD":
volume = min(0.1, max(0.01, risk_amount / (stop_distance * 100)))
else:
volume = 0.01
else:
volume = 0.01
# FINAL POSITION CHECK vor Order
final_check, _ = check_existing_positions(symbol, strategy_name)
if final_check:
print(f"🛑 LAST-MINUTE BLOCK: Position wurde zwischen Checks eröffnet!")
return None
# Log Enhanced Trade Info
print(f"\n🚀 ENHANCED TRADE EXECUTION (mit Position Control)")
print(f"Symbol: {symbol}")
print(f"Direction: {'LONG' if entry_signal == 1 else 'SHORT'}")
print(f"Price: {price:.5f}")
print(f"Volume: {volume:.2f}")
print(f"Stop Loss: {stop_loss:.5f}")
print(f"Take Profit: {take_profit:.5f}")
print(f"Confidence: {confidence}% (Threshold: {adaptive_threshold}%)")
print(f"Signal Quality: {signal_quality.upper()}")
print(f"Market Regime: {market_regime['regime'].upper()}")
print(f"Position Limit: {position_info['count']}/{max_positions}")
# Execute the actual trade
try:
order_result = market_order(
symbol=symbol,
volume=volume,
order_type="buy" if entry_signal == 1 else "sell",
stoploss=stop_loss,
take_profit=take_profit,
comment=strategy_name # Wichtig für Position-Tracking
)
if order_result and order_result.retcode == mt.TRADE_RETCODE_DONE:
print(f"✅ Trade erfolgreich eröffnet! Ticket: {order_result.order}")
# Verify position was created
new_check, new_info = check_existing_positions(symbol, strategy_name)
print(f"📊 Neue Position-Anzahl: {new_info['count']}")
return order_result
except Exception as e:
print(f"❌ Trade execution failed: {e}")
return None
else:
if debug:
print(f"\n⏸️ TRADE SKIPPED: {reason}")
print(f"Confidence: {confidence}% | Threshold: {adaptive_threshold}%")
print(f"Signal Quality: {signal_quality} | Regime: {market_regime['regime']}")
print(f"Positions: {position_info['count']}/{max_positions}")
return None
except ImportError:
print("❌ Konnte bestehende Funktionen nicht importieren. Verwende vereinfachte Version.")
return None
except Exception as e:
print(f"❌ Fehler in enhanced_execute_trade_v2_with_position_control: {e}")
return None
def position_management_menu():
"""
Interaktives Menü für Position-Management
"""
symbol = "XAUUSD"
strategy_name = "TradingBot_V1.4_Complete"
while True:
print(f"\n🔧 POSITION MANAGEMENT MENU")
print("=" * 40)
print("1. Position Status anzeigen")
print("2. Alle Positionen schließen")
print("3. Position-Check für neuen Trade")
print("4. Trading mit Position-Control testen")
print("5. Exit")
choice = input("\nWähle Option (1-5): ").strip()
if choice == "1":
get_position_summary(symbol, strategy_name)
elif choice == "2":
confirm = input("❗ Alle Positionen schließen? (yes/no): ").strip().lower()
if confirm in ['yes', 'y', 'ja', 'j']:
close_existing_positions(symbol, strategy_name, force_close=True)
else:
print("❌ Abgebrochen")
elif choice == "3":
has_pos, pos_info = check_existing_positions(symbol, strategy_name)
if has_pos:
print(f"🛑 {pos_info['count']} Position(en) aktiv - KEIN neuer Trade möglich")
else:
print("✅ Keine Positionen - neuer Trade möglich")
elif choice == "4":
print("🧪 Testing Trading mit Position Control...")
result = enhanced_execute_trade_v2_with_position_control(
symbol=symbol,
strategy_name=strategy_name,
debug=True
)
if result:
print(f"✅ Test-Trade ausgeführt: {result}")
else:
print("⏸️ Kein Test-Trade ausgeführt")
elif choice == "5":
print("👋 Exit Position Management")
break
else:
print("❌ Ungültige Option")
if __name__ == "__main__":
# Teste Position Control
symbol = "XAUUSD"
strategy_name = "TradingBot_V1.4_Complete"
print("🔍 TESTING POSITION CONTROL")
print("=" * 40)
# Check current positions
get_position_summary(symbol, strategy_name)
# Start interactive menu
position_management_menu()
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
-11068
View File
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
-2
View File
@@ -1,2 +0,0 @@
[ZoneTransfer]
ZoneId=3
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
-680
View File
@@ -1,680 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# TradingBot V1.4 - Complete Version\n",
"\n",
"## 🚀 Optimierte Entry Signal Logik\n",
"\n",
"### Hauptverbesserungen:\n",
"1. **Adaptive Confidence Threshold** - Automatische Anpassung an Marktbedingungen\n",
"2. **Market Regime Detection** - Erkennung von Trending/Ranging/Volatile Märkten\n",
"3. **Entry Timing Optimization** - Pullback-basierte Entries\n",
"4. **Risk-Adjusted Signal Strength** - Kombiniert Confidence mit Trend-Stärke\n",
"5. **Performance Monitoring** - Automatisches Tracking"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Imports\n",
"import pandas as pd\n",
"import numpy as np\n",
"import MetaTrader5 as mt\n",
"import pandas_ta as ta\n",
"from scipy.signal import savgol_filter, find_peaks\n",
"from sklearn.linear_model import LinearRegression\n",
"from tabulate import tabulate\n",
"from datetime import datetime, timedelta\n",
"import json\n",
"import keyring as kr\n",
"\n",
"print(\"✅ All imports successful\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# MT5 Login\n",
"mt.initialize()\n",
"login = 10800246\n",
"server = 'VantageInternational-Demo'\n",
"password = kr.get_password(server, str(login))\n",
"login_result = mt.login(login, password, server)\n",
"print(f\"Login successful: {login_result}\")\n",
"\n",
"# Trading Parameter\n",
"symbol = \"XAUUSD\"\n",
"strategy_name = \"TradingBot_V1.4_Complete\"\n",
"print(f\"Symbol: {symbol}\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Helper Functions\n",
"def get_rates(timeframe=\"h4\", count=200, symbol=\"XAUUSD\"):\n",
" timeframes_dict = {\n",
" \"m1\": mt.TIMEFRAME_M1, \"m5\": mt.TIMEFRAME_M5, \"m15\": mt.TIMEFRAME_M15,\n",
" \"m30\": mt.TIMEFRAME_M30, \"h1\": mt.TIMEFRAME_H1, \"h4\": mt.TIMEFRAME_H4, \"d1\": mt.TIMEFRAME_D1\n",
" }\n",
" try:\n",
" rates = mt.copy_rates_from_pos(symbol, timeframes_dict[timeframe], 0, count)\n",
" if rates is None: return None\n",
" df = pd.DataFrame(rates)\n",
" df['time'] = pd.to_datetime(df['time'], unit='s')\n",
" df.set_index('time', inplace=True)\n",
" df['atr'] = ta.atr(df['high'], df['low'], df['close'], length=14)\n",
" return df\n",
" except Exception as e:\n",
" print(f\"Error getting rates: {e}\")\n",
" return None\n",
"\n",
"def check_risk_limits(symbol, volume=None, order_type=\"buy\", max_risk_per_trade=0.01):\n",
" try:\n",
" account_info = mt.account_info()\n",
" if not account_info: return False\n",
" balance, equity = account_info.balance, account_info.equity\n",
" if equity < balance * 0.8: return False\n",
" return True\n",
" except: return False\n",
"\n",
"def market_order(symbol, volume, order_type, stoploss=None, take_profit=None, deviation=20):\n",
" try:\n",
" price_dict = {'buy': mt.symbol_info_tick(symbol).ask, 'sell': mt.symbol_info_tick(symbol).bid}\n",
" order_type_dict = {'buy': mt.ORDER_TYPE_BUY, 'sell': mt.ORDER_TYPE_SELL}\n",
" request = {\n",
" \"action\": mt.TRADE_ACTION_DEAL, \"symbol\": symbol, \"volume\": volume,\n",
" \"type\": order_type_dict[order_type], \"price\": price_dict[order_type],\n",
" \"sl\": stoploss, \"tp\": take_profit, \"deviation\": deviation,\n",
" \"magic\": 234000, \"comment\": strategy_name, \"type_time\": mt.ORDER_TIME_GTC,\n",
" \"type_filling\": mt.ORDER_FILLING_IOC\n",
" }\n",
" return mt.order_send(request)\n",
" except Exception as e:\n",
" print(f\"Error in market order: {e}\")\n",
" return None\n",
"\n",
"print(\"✅ Helper functions defined\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Market Regime Detection\n",
"def detect_market_regime(df, lookback=50):\n",
" try:\n",
" adx_data = ta.adx(df['high'], df['low'], df['close'], length=14)\n",
" adx = adx_data['ADX_14'].iloc[-1] if adx_data is not None and 'ADX_14' in adx_data.columns else 25.0\n",
" \n",
" try:\n",
" bb = ta.bbands(df['close'], length=20)\n",
" if bb is not None and len(bb.columns) >= 3:\n",
" bb_cols = bb.columns.tolist()\n",
" bb_width = ((bb[bb_cols[0]] - bb[bb_cols[2]]) / bb[bb_cols[1]] * 100).iloc[-lookback:].mean()\n",
" else: bb_width = 4.0\n",
" except: bb_width = 4.0\n",
" \n",
" price_range = df['high'].iloc[-lookback:].max() - df['low'].iloc[-lookback:].min()\n",
" atr_avg = df['atr'].iloc[-lookback:].mean()\n",
" range_ratio = price_range / (atr_avg * lookback) if atr_avg > 0 else 1.0\n",
" vol_cluster = df['atr'].iloc[-10:].std() / df['atr'].iloc[-50:].mean() if len(df) >= 50 else 1.0\n",
" \n",
" if adx > 25 and range_ratio > 1.5:\n",
" regime, strength = 'trending', min(100, adx * 2)\n",
" elif vol_cluster > 1.5:\n",
" regime, strength = 'volatile', min(100, vol_cluster * 50)\n",
" else:\n",
" regime, strength = 'ranging', max(0, 100 - adx * 2)\n",
" \n",
" return {'regime': regime, 'strength': strength, 'adx': adx, 'bb_width': bb_width, 'range_ratio': range_ratio, 'vol_cluster': vol_cluster}\n",
" except Exception as e:\n",
" return {'regime': 'ranging', 'strength': 50, 'adx': 20, 'bb_width': 4.0, 'range_ratio': 1.0, 'vol_cluster': 1.0}\n",
"\n",
"print(\"✅ Market Regime Detection defined\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Adaptive Confidence System\n",
"def calculate_adaptive_confidence_threshold(regime_info, base_confidence=70):\n",
" regime = regime_info['regime']\n",
" adx = regime_info['adx']\n",
" \n",
" if regime == 'trending':\n",
" return max(60, base_confidence - 15) if adx > 30 else base_confidence - 10\n",
" elif regime == 'ranging':\n",
" return base_confidence + 15\n",
" elif regime == 'volatile':\n",
" return base_confidence + 20\n",
" return base_confidence\n",
"\n",
"print(\"✅ Adaptive Confidence System defined\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Enhanced Trend Analysis\n",
"def get_enhanced_trend(timeframe=\"H4\", lookback=150, symbol=\"XAUUSD\"):\n",
" tf_map = {\"D1\": \"d1\", \"H4\": \"h4\", \"H1\": \"h1\", \"M30\": \"m30\", \"M15\": \"m15\", \"M5\": \"m5\"}\n",
" tf = tf_map.get(timeframe, timeframe.lower())\n",
" \n",
" try:\n",
" df = get_rates(tf, lookback, symbol)\n",
" if df is None or len(df) < 50: return None\n",
" \n",
" df['close_smooth'] = savgol_filter(df['close'], min(15, len(df)//10), 3)\n",
" X = np.arange(len(df)).reshape(-1, 1)\n",
" y = df['close_smooth'].values\n",
" model = LinearRegression().fit(X, y)\n",
" slope = model.coef_[0]\n",
" \n",
" regime_info = detect_market_regime(df.iloc[-50:])\n",
" base_threshold = df['atr'].iloc[-1] * 0.0001\n",
" \n",
" if regime_info['regime'] == 'trending':\n",
" slope_threshold = base_threshold * 0.7\n",
" elif regime_info['regime'] == 'ranging':\n",
" slope_threshold = base_threshold * 1.5\n",
" else:\n",
" slope_threshold = base_threshold * 1.2\n",
" \n",
" trend = \"uptrend\" if slope > slope_threshold else \"downtrend\" if slope < -slope_threshold else \"sideways\"\n",
" trend_strength = abs(slope) / slope_threshold if slope_threshold > 0 else 0\n",
" \n",
" return {\n",
" \"trend\": trend, \"slope\": slope, \"slope_threshold\": slope_threshold,\n",
" \"trend_strength\": trend_strength, \"atr\": df['atr'].iloc[-1],\n",
" \"price\": df['close'].iloc[-1], \"regime_info\": regime_info\n",
" }\n",
" except Exception as e:\n",
" print(f\"Error in get_enhanced_trend: {e}\")\n",
" return None\n",
"\n",
"print(\"✅ Enhanced Trend Analysis defined\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Extended Top-Down Analysis V2\n",
"def extended_top_down_v2(symbol=\"XAUUSD\", lookback=150):\n",
" timeframes = [\"D1\", \"H4\", \"H1\", \"M30\", \"M15\", \"M5\"]\n",
" trend_info = {}\n",
" \n",
" for tf in timeframes:\n",
" trend_info[tf] = get_enhanced_trend(tf, lookback, symbol)\n",
" if trend_info[tf] is None:\n",
" print(f\"⚠️ Keine Daten für {tf}\")\n",
" return None\n",
" \n",
" main_regime = trend_info[\"H4\"][\"regime_info\"]\n",
" adaptive_confidence_threshold = calculate_adaptive_confidence_threshold(main_regime)\n",
" \n",
" # Standard-Trend (D1 + H4)\n",
" d1_trend = trend_info[\"D1\"][\"trend\"]\n",
" h4_trend = trend_info[\"H4\"][\"trend\"]\n",
" d1_strength = trend_info[\"D1\"][\"trend_strength\"]\n",
" h4_strength = trend_info[\"H4\"][\"trend_strength\"]\n",
" \n",
" if d1_trend == h4_trend and d1_trend != \"sideways\":\n",
" standard_trend = d1_trend\n",
" standard_strength = (d1_strength * 0.6 + h4_strength * 0.4)\n",
" elif d1_strength > h4_strength * 1.5:\n",
" standard_trend = d1_trend\n",
" standard_strength = d1_strength * 0.8\n",
" elif h4_strength > d1_strength * 1.5:\n",
" standard_trend = h4_trend\n",
" standard_strength = h4_strength * 0.8\n",
" else:\n",
" standard_trend = \"sideways\"\n",
" standard_strength = 0\n",
" \n",
" # Fast-Trend\n",
" fast_timeframes = [\"H1\", \"M30\", \"M15\", \"M5\"]\n",
" fast_trends = [trend_info[tf][\"trend\"] for tf in fast_timeframes]\n",
" fast_strengths = [trend_info[tf][\"trend_strength\"] for tf in fast_timeframes]\n",
" \n",
" required_alignment = 2 if main_regime['regime'] == 'trending' else 3\n",
" \n",
" trend_counts = {'uptrend': 0, 'downtrend': 0, 'sideways': 0}\n",
" weighted_strengths = {'uptrend': 0, 'downtrend': 0}\n",
" weights = [1.0, 0.8, 0.6, 0.4]\n",
" \n",
" for i, (trend, strength) in enumerate(zip(fast_trends, fast_strengths)):\n",
" trend_counts[trend] += 1\n",
" if trend != 'sideways':\n",
" weighted_strengths[trend] += strength * weights[i]\n",
" \n",
" max_count = max(trend_counts['uptrend'], trend_counts['downtrend'])\n",
" if max_count >= required_alignment:\n",
" if trend_counts['uptrend'] > trend_counts['downtrend']:\n",
" fast_trend = \"uptrend\"\n",
" elif trend_counts['downtrend'] > trend_counts['uptrend']:\n",
" fast_trend = \"downtrend\"\n",
" else:\n",
" fast_trend = \"uptrend\" if weighted_strengths['uptrend'] > weighted_strengths['downtrend'] else \"downtrend\"\n",
" else:\n",
" fast_trend = \"sideways\"\n",
" \n",
" # Top-Down-Trend\n",
" if standard_trend == fast_trend and standard_trend != \"sideways\":\n",
" top_down_trend = standard_trend\n",
" combined_strength = (standard_strength + weighted_strengths.get(fast_trend, 0)) / 2\n",
" else:\n",
" top_down_trend = \"sideways\"\n",
" combined_strength = 0\n",
" \n",
" # Confidence Calculation\n",
" weights = {\"D1\": 2.5, \"H4\": 2.0, \"H1\": 1.5, \"M30\": 1.0, \"M15\": 0.8, \"M5\": 0.6}\n",
" \n",
" weighted_matching = sum(\n",
" weights[tf] * trend_info[tf][\"trend_strength\"] \n",
" for tf in timeframes\n",
" if trend_info[tf][\"trend\"] == top_down_trend and trend_info[tf][\"trend\"] != \"sideways\"\n",
" )\n",
" \n",
" weighted_total = sum(\n",
" weights[tf] * trend_info[tf][\"trend_strength\"]\n",
" for tf in timeframes\n",
" if trend_info[tf][\"trend\"] != \"sideways\"\n",
" )\n",
" \n",
" confidence = round((weighted_matching / weighted_total) * 100, 2) if weighted_total > 0 else 0.0\n",
" \n",
" # Risk-Adjusted Signal Strength\n",
" atr = trend_info[\"M5\"][\"atr\"]\n",
" rrr = 2.5\n",
" risk_adjusted_strength = confidence * combined_strength * min(2.0, rrr)\n",
" \n",
" # Entry Signal\n",
" entry_signal = 0\n",
" signal_quality = \"none\"\n",
" \n",
" if (top_down_trend != \"sideways\" and \n",
" confidence >= adaptive_confidence_threshold and\n",
" risk_adjusted_strength >= 100):\n",
" \n",
" entry_signal = 1 if top_down_trend == \"uptrend\" else -1\n",
" \n",
" if confidence >= 85 and risk_adjusted_strength >= 150:\n",
" signal_quality = \"excellent\"\n",
" elif confidence >= 75 and risk_adjusted_strength >= 120:\n",
" signal_quality = \"good\"\n",
" else:\n",
" signal_quality = \"fair\"\n",
" \n",
" # Debug Output\n",
" debug_data = []\n",
" for tf in timeframes:\n",
" info = trend_info[tf]\n",
" debug_data.append([tf, info[\"trend\"], f\"{info['trend_strength']:.2f}\", \n",
" f\"{info['atr']:.4f}\", f\"{info['slope']:.6f}\", f\"{info['price']:.2f}\"])\n",
" \n",
" print(f\"📊 Enhanced Trend-Analyse für {symbol}\")\n",
" print(f\"🎯 Market Regime: {main_regime['regime'].upper()} (Strength: {main_regime['strength']:.0f}%)\")\n",
" print(f\"🎚️ Adaptive Confidence Threshold: {adaptive_confidence_threshold}%\")\n",
" print(tabulate(debug_data, headers=[\"TF\", \"Trend\", \"Strength\", \"ATR\", \"Slope\", \"Price\"], tablefmt=\"psql\"))\n",
" print(f\"➡️ Standard-Trend: {standard_trend} (Strength: {standard_strength:.2f})\")\n",
" print(f\"➡️ Fast-Trend: {fast_trend}\")\n",
" print(f\"➡️ Top-Down-Trend: {top_down_trend}\")\n",
" print(f\"➡️ Confidence: {confidence}% (Threshold: {adaptive_confidence_threshold}%)\")\n",
" print(f\"➡️ Risk-Adjusted Strength: {risk_adjusted_strength:.1f}\")\n",
" print(f\"➡️ Signal Quality: {signal_quality.upper()}\")\n",
" \n",
" return {\n",
" \"symbol\": symbol, \"trend_info\": trend_info, \"market_regime\": main_regime,\n",
" \"standard_trend\": standard_trend, \"fast_trend\": fast_trend, \"top_down_trend\": top_down_trend,\n",
" \"confidence\": confidence, \"adaptive_threshold\": adaptive_confidence_threshold,\n",
" \"risk_adjusted_strength\": risk_adjusted_strength, \"entry_signal\": entry_signal,\n",
" \"signal_quality\": signal_quality, \"combined_strength\": combined_strength\n",
" }\n",
"\n",
"print(\"✅ Extended Top-Down V2 defined\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Entry Timing Optimization\n",
"def check_pullback_entry(symbol, signal_info, timeframe=\"M5\"):\n",
" if signal_info[\"entry_signal\"] == 0:\n",
" return False, \"No base signal\"\n",
" \n",
" try:\n",
" df = get_rates(timeframe.lower(), 50, symbol)\n",
" if df is None or len(df) < 20:\n",
" return False, \"Insufficient data\"\n",
" \n",
" df['ema21'] = df['close'].ewm(span=21).mean()\n",
" df['ema50'] = df['close'].ewm(span=50).mean()\n",
" \n",
" current_price = df['close'].iloc[-1]\n",
" ema21 = df['ema21'].iloc[-1]\n",
" ema50 = df['ema50'].iloc[-1]\n",
" signal_direction = signal_info[\"entry_signal\"]\n",
" \n",
" if signal_direction == 1: # Long\n",
" if current_price <= ema21 * 1.002 and ema21 > ema50:\n",
" return True, \"Pullback to EMA21 for Long\"\n",
" elif current_price <= ema21 * 0.998:\n",
" return True, \"Below EMA21 - Good Long Entry\"\n",
" elif signal_direction == -1: # Short\n",
" if current_price >= ema21 * 0.998 and ema21 < ema50:\n",
" return True, \"Pullback to EMA21 for Short\"\n",
" elif current_price >= ema21 * 1.002:\n",
" return True, \"Above EMA21 - Good Short Entry\"\n",
" \n",
" return False, \"Waiting for better entry timing\"\n",
" except Exception as e:\n",
" return True, \"Using immediate entry (fallback)\"\n",
"\n",
"print(\"✅ Entry Timing Optimization defined\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Enhanced Execute Trade Function\n",
"def execute_trade_v2(\n",
" symbol=\"XAUUSD\",\n",
" atr_mult=1.5,\n",
" base_confidence=70,\n",
" max_risk_per_trade=0.01,\n",
" risk_filter=True,\n",
" min_atr=0.0010,\n",
" use_pullback_entry=True,\n",
" debug=True\n",
"):\n",
" signal_info = extended_top_down_v2(symbol)\n",
" if signal_info is None:\n",
" print(\"❌ Signal-Analyse fehlgeschlagen\")\n",
" return None\n",
" \n",
" entry_signal = signal_info[\"entry_signal\"]\n",
" confidence = signal_info[\"confidence\"]\n",
" adaptive_threshold = signal_info[\"adaptive_threshold\"]\n",
" signal_quality = signal_info[\"signal_quality\"]\n",
" market_regime = signal_info[\"market_regime\"]\n",
" \n",
" m5_info = signal_info[\"trend_info\"][\"M5\"]\n",
" price = m5_info[\"price\"]\n",
" atr = m5_info[\"atr\"]\n",
" \n",
" reason = \"\"\n",
" \n",
" if confidence < adaptive_threshold:\n",
" reason = f\"Confidence {confidence}% < threshold {adaptive_threshold}%\"\n",
" elif entry_signal == 0:\n",
" reason = f\"No entry signal (Trend: {signal_info['top_down_trend']})\"\n",
" elif price is None or atr is None:\n",
" reason = \"Price/ATR not available\"\n",
" elif risk_filter and atr < min_atr:\n",
" reason = f\"ATR {atr:.5f} < min_atr {min_atr}\"\n",
" elif signal_quality == \"none\":\n",
" reason = \"Signal quality insufficient\"\n",
" else:\n",
" if use_pullback_entry:\n",
" pullback_ok, pullback_reason = check_pullback_entry(symbol, signal_info)\n",
" if not pullback_ok:\n",
" reason = f\"Entry timing: {pullback_reason}\"\n",
" \n",
" if not reason:\n",
" risk_ok = check_risk_limits(symbol, max_risk_per_trade=max_risk_per_trade)\n",
" if not risk_ok:\n",
" reason = \"Risk limits exceeded\"\n",
" \n",
" if not reason:\n",
" regime_mult = 1.0\n",
" if market_regime['regime'] == 'volatile':\n",
" regime_mult = 1.3\n",
" elif market_regime['regime'] == 'ranging':\n",
" regime_mult = 0.8\n",
" \n",
" adjusted_atr_mult = atr_mult * regime_mult\n",
" \n",
" if entry_signal == 1:\n",
" stop_loss = price - adjusted_atr_mult * atr\n",
" take_profit = price + adjusted_atr_mult * atr * 2.5\n",
" else:\n",
" stop_loss = price + adjusted_atr_mult * atr\n",
" take_profit = price - adjusted_atr_mult * atr * 2.5\n",
" \n",
" account_info = mt.account_info()\n",
" if account_info:\n",
" balance = account_info.balance\n",
" risk_amount = balance * max_risk_per_trade\n",
" if symbol == \"XAUUSD\":\n",
" volume = min(0.1, max(0.01, risk_amount / (adjusted_atr_mult * atr * 100)))\n",
" else:\n",
" volume = 0.01\n",
" else:\n",
" volume = 0.01\n",
" \n",
" print(f\"🚀 ENHANCED TRADE EXECUTION\")\n",
" print(f\"Symbol: {symbol}\")\n",
" print(f\"Direction: {'LONG' if entry_signal == 1 else 'SHORT'}\")\n",
" print(f\"Price: {price:.5f}\")\n",
" print(f\"Volume: {volume:.2f}\")\n",
" print(f\"Stop Loss: {stop_loss:.5f}\")\n",
" print(f\"Take Profit: {take_profit:.5f}\")\n",
" print(f\"Confidence: {confidence}% (Threshold: {adaptive_threshold}%)\")\n",
" print(f\"Signal Quality: {signal_quality.upper()}\")\n",
" print(f\"Market Regime: {market_regime['regime'].upper()}\")\n",
" \n",
" try:\n",
" order_result = market_order(\n",
" symbol=symbol,\n",
" volume=volume,\n",
" order_type=\"buy\" if entry_signal == 1 else \"sell\",\n",
" stoploss=stop_loss,\n",
" take_profit=take_profit\n",
" )\n",
" return order_result\n",
" except Exception as e:\n",
" print(f\"❌ Trade execution failed: {e}\")\n",
" return None\n",
" else:\n",
" if debug:\n",
" print(f\"⏸️ TRADE SKIPPED: {reason}\")\n",
" print(f\"Confidence: {confidence}% | Threshold: {adaptive_threshold}%\")\n",
" print(f\"Signal Quality: {signal_quality} | Regime: {market_regime['regime']}\")\n",
" return None\n",
"\n",
"print(\"✅ Enhanced Execute Trade defined\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Test der optimierten Funktionen\n",
"print(\"🔍 Testing Market Regime Detection...\")\n",
"df_test = get_rates(\"h4\", 100, symbol)\n",
"if df_test is not None:\n",
" regime = detect_market_regime(df_test)\n",
" print(f\"Regime: {regime['regime'].upper()}\")\n",
" print(f\"Strength: {regime['strength']:.1f}%\")\n",
" print(f\"ADX: {regime['adx']:.1f}\")\n",
" \n",
" adaptive_threshold = calculate_adaptive_confidence_threshold(regime)\n",
" print(f\"Adaptive Threshold: {adaptive_threshold}% (vs 80% fixed)\")\n",
"else:\n",
" print(\"❌ Could not get test data\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Test Enhanced Top-Down Analysis\n",
"print(\"🔍 Testing Enhanced Top-Down Analysis...\")\n",
"signal_result = extended_top_down_v2(symbol)\n",
"\n",
"if signal_result:\n",
" print(f\"🎯 SIGNAL SUMMARY:\")\n",
" print(f\"Entry Signal: {signal_result['entry_signal']}\")\n",
" print(f\"Confidence: {signal_result['confidence']}%\")\n",
" print(f\"Adaptive Threshold: {signal_result['adaptive_threshold']}%\")\n",
" print(f\"Signal Quality: {signal_result['signal_quality'].upper()}\")\n",
" print(f\"Market Regime: {signal_result['market_regime']['regime'].upper()}\")\n",
" print(f\"Risk-Adjusted Strength: {signal_result['risk_adjusted_strength']:.1f}\")\n",
" \n",
" if signal_result['entry_signal'] != 0:\n",
" direction = \"LONG\" if signal_result['entry_signal'] == 1 else \"SHORT\"\n",
" print(f\"🚀 TRADING SIGNAL: {direction}\")\n",
" else:\n",
" print(f\"⏸️ NO TRADING SIGNAL\")\n",
"else:\n",
" print(\"❌ Signal analysis failed\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Trading Configuration\n",
"TRADING_CONFIG = {\n",
" 'symbol': symbol,\n",
" 'atr_mult': 1.5,\n",
" 'base_confidence': 70,\n",
" 'max_risk_per_trade': 0.01,\n",
" 'risk_filter': True,\n",
" 'min_atr': 0.0010,\n",
" 'use_pullback_entry': True,\n",
" 'debug': True\n",
"}\n",
"\n",
"print(\"⚙️ Trading Configuration:\")\n",
"for key, value in TRADING_CONFIG.items():\n",
" print(f\" {key}: {value}\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Test Trading Execution\n",
"def test_trading():\n",
" print(\"🚀 Testing Trade Execution...\")\n",
" try:\n",
" result = execute_trade_v2(**TRADING_CONFIG)\n",
" if result:\n",
" print(\"✅ Trade executed successfully!\")\n",
" return result\n",
" else:\n",
" print(\"⏸️ No trade executed\")\n",
" return None\n",
" except Exception as e:\n",
" print(f\"❌ Error: {e}\")\n",
" return None\n",
"\n",
"test_result = test_trading()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Status Check\n",
"def check_bot_status():\n",
" print(\"🔍 Trading Bot Status:\")\n",
" print(f\" MT5 Connection: {'✅' if mt.terminal_info() else '❌'}\")\n",
" \n",
" try:\n",
" signal_info = extended_top_down_v2(symbol)\n",
" if signal_info:\n",
" print(f\" Current Signal: {signal_info['entry_signal']}\")\n",
" print(f\" Confidence: {signal_info['confidence']}%\")\n",
" print(f\" Market Regime: {signal_info['market_regime']['regime'].upper()}\")\n",
" print(f\" Signal Quality: {signal_info['signal_quality'].upper()}\")\n",
" except Exception as e:\n",
" print(f\" Signal Check: ❌ Error: {e}\")\n",
"\n",
"check_bot_status()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 📝 Zusammenfassung\n",
"\n",
"### ✅ **TradingBot V1.4 Complete ist bereit!**\n",
"\n",
"**Hauptfunktionen:**\n",
"- `extended_top_down_v2()` - Optimierte Signal-Analyse\n",
"- `execute_trade_v2()` - Verbesserte Trade-Ausführung\n",
"- `detect_market_regime()` - Marktregime-Erkennung\n",
"\n",
"**Nächste Schritte:**\n",
"1. Teste die Funktionen im Demo-Modus\n",
"2. Überwache Performance für 1-2 Wochen\n",
"3. Optimiere Parameter basierend auf Ergebnissen\n",
"4. Bei Erfolg: Live-Trading aktivieren"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"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
}
File diff suppressed because it is too large. Load diff
@@ -1,2 +0,0 @@
[ZoneTransfer]
ZoneId=3
File diff suppressed because it is too large. Load diff
@@ -1,2 +0,0 @@
[ZoneTransfer]
ZoneId=3
File diff suppressed because it is too large. Load diff
-753
View File
@@ -1,753 +0,0 @@
"""
TradingBot V1.4 - Fixed Version
Korrigierte Entry Signal Logik ohne externe Abhängigkeiten
Alle notwendigen Funktionen sind integriert.
"""
import pandas as pd
import numpy as np
import MetaTrader5 as mt
import pandas_ta as ta
from scipy.signal import savgol_filter, find_peaks
from sklearn.linear_model import LinearRegression
from tabulate import tabulate
from datetime import datetime, timedelta
import json
# =============================================================================
# HILFSFUNKTIONEN (aus deiner bestehenden V1.3)
# =============================================================================
def get_rates(timeframe="h4", count=200, symbol="XAUUSD"):
"""
Holt Kursdaten von MT5
"""
timeframes_dict = {
"m1": mt.TIMEFRAME_M1,
"m5": mt.TIMEFRAME_M5,
"m15": mt.TIMEFRAME_M15,
"m30": mt.TIMEFRAME_M30,
"h1": mt.TIMEFRAME_H1,
"h4": mt.TIMEFRAME_H4,
"d1": mt.TIMEFRAME_D1
}
try:
rates = mt.copy_rates_from_pos(symbol, timeframes_dict[timeframe], 0, count)
if rates is None:
return None
df = pd.DataFrame(rates)
df['time'] = pd.to_datetime(df['time'], unit='s')
df.set_index('time', inplace=True)
# ATR hinzufügen
df['atr'] = ta.atr(df['high'], df['low'], df['close'], length=14)
return df
except Exception as e:
print(f"Error getting rates: {e}")
return None
def check_risk_limits(symbol, volume=None, order_type="buy", max_risk_per_trade=0.01):
"""
Prüft alle Risikolimits (vereinfachte Version)
"""
try:
account_info = mt.account_info()
if not account_info:
print("⚠️ Kontodaten nicht verfügbar.")
return False
# Einfache Checks - erweitere nach Bedarf
balance = account_info.balance
equity = account_info.equity
# Basis-Risiko-Check
if equity < balance * 0.8: # Mehr als 20% Verlust
print("⚠️ Drawdown-Limit erreicht")
return False
return True
except Exception as e:
print(f"Error in risk check: {e}")
return False
def market_order(symbol, volume, order_type, stoploss=None, take_profit=None, deviation=20):
"""
Führt Market Order aus (vereinfachte Version)
"""
try:
price_dict = {
'buy': mt.symbol_info_tick(symbol).ask,
'sell': mt.symbol_info_tick(symbol).bid
}
order_type_dict = {
'buy': mt.ORDER_TYPE_BUY,
'sell': mt.ORDER_TYPE_SELL
}
request = {
"action": mt.TRADE_ACTION_DEAL,
"symbol": symbol,
"volume": volume,
"type": order_type_dict[order_type],
"price": price_dict[order_type],
"sl": stoploss,
"tp": take_profit,
"deviation": deviation,
"magic": 234000,
"comment": "TradingBot_V1.4_Optimized",
"type_time": mt.ORDER_TIME_GTC,
"type_filling": mt.ORDER_FILLING_IOC,
}
result = mt.order_send(request)
return result
except Exception as e:
print(f"Error in market order: {e}")
return None
# =============================================================================
# 1. MARKET REGIME DETECTION
# =============================================================================
def detect_market_regime(df, lookback=50):
"""
Erkennt das aktuelle Marktregime (Trending vs. Ranging)
"""
try:
# ADX für Trendstärke
adx_data = ta.adx(df['high'], df['low'], df['close'], length=14)
if adx_data is None or 'ADX_14' not in adx_data.columns:
# Fallback: einfache ADX-Berechnung
adx = 25.0 # Standardwert
else:
adx = adx_data['ADX_14'].iloc[-1] if not pd.isna(adx_data['ADX_14'].iloc[-1]) else 25.0
# Bollinger Band Squeeze für Ranging Markets
try:
bb = ta.bbands(df['close'], length=20)
if bb is not None and len(bb.columns) >= 3:
bb_cols = bb.columns.tolist()
bb_upper = bb[bb_cols[0]] # Oberes Band
bb_middle = bb[bb_cols[1]] # Mittleres Band
bb_lower = bb[bb_cols[2]] # Unteres Band
bb_width = ((bb_upper - bb_lower) / bb_middle * 100).iloc[-lookback:].mean()
else:
bb_width = 4.0 # Standardwert
except:
bb_width = 4.0
# Price Action Analysis
price_range = (df['high'].iloc[-lookback:].max() - df['low'].iloc[-lookback:].min())
atr_avg = df['atr'].iloc[-lookback:].mean()
range_ratio = price_range / (atr_avg * lookback) if atr_avg > 0 else 1.0
# Volatility Cluster Detection
vol_cluster = df['atr'].iloc[-10:].std() / df['atr'].iloc[-50:].mean() if len(df) >= 50 else 1.0
# Regime-Bestimmung
if adx > 25 and range_ratio > 1.5:
regime = 'trending'
strength = min(100, adx * 2)
elif vol_cluster > 1.5:
regime = 'volatile'
strength = min(100, vol_cluster * 50)
else:
regime = 'ranging'
strength = max(0, 100 - adx * 2)
return {
'regime': regime,
'strength': strength,
'adx': adx,
'bb_width': bb_width,
'range_ratio': range_ratio,
'vol_cluster': vol_cluster
}
except Exception as e:
print(f"Error in regime detection: {e}")
# Fallback
return {
'regime': 'ranging',
'strength': 50,
'adx': 20,
'bb_width': 4.0,
'range_ratio': 1.0,
'vol_cluster': 1.0
}
# =============================================================================
# 2. ADAPTIVE CONFIDENCE SYSTEM
# =============================================================================
def calculate_adaptive_confidence_threshold(regime_info, base_confidence=70):
"""
Berechnet adaptive Confidence-Schwelle basierend auf Marktregime
"""
regime = regime_info['regime']
strength = regime_info['strength']
adx = regime_info['adx']
if regime == 'trending':
# In Trending Markets: niedrigere Schwelle bei starken Trends
if adx > 30:
return max(60, base_confidence - 15)
else:
return base_confidence - 10
elif regime == 'ranging':
# In Ranging Markets: höhere Schwelle für mehr Selektivität
return base_confidence + 15
elif regime == 'volatile':
# In Volatile Markets: deutlich höhere Schwelle
return base_confidence + 20
return base_confidence
# =============================================================================
# 3. ENHANCED TREND ANALYSIS
# =============================================================================
def get_enhanced_trend(timeframe="H4", lookback=150, symbol="XAUUSD"):
"""
Verbesserte Trend-Analyse mit Regime-Awareness
"""
# Timeframe mapping
tf_map = {"D1": "d1", "H4": "h4", "H1": "h1", "M30": "m30", "M15": "m15", "M5": "m5"}
tf = tf_map.get(timeframe, timeframe.lower())
try:
df = get_rates(tf, lookback, symbol)
if df is None or len(df) < 50:
return None
# Bestehende Trend-Logik
df['close_smooth'] = savgol_filter(df['close'], min(15, len(df)//10), 3)
# Linear Regression
X = np.arange(len(df)).reshape(-1, 1)
y = df['close_smooth'].values
model = LinearRegression().fit(X, y)
slope = model.coef_[0]
# Market Regime Detection
regime_info = detect_market_regime(df.iloc[-50:])
# Adaptive Slope Threshold basierend auf Regime
base_threshold = df['atr'].iloc[-1] * 0.0001
if regime_info['regime'] == 'trending':
slope_threshold = base_threshold * 0.7 # Niedrigere Schwelle in Trends
elif regime_info['regime'] == 'ranging':
slope_threshold = base_threshold * 1.5 # Höhere Schwelle in Ranges
else: # volatile
slope_threshold = base_threshold * 1.2
# Trend bestimmen
if slope > slope_threshold:
trend = "uptrend"
elif slope < -slope_threshold:
trend = "downtrend"
else:
trend = "sideways"
# Enhanced Trend Strength
trend_strength = abs(slope) / slope_threshold if slope_threshold > 0 else 0
return {
"trend": trend,
"slope": slope,
"slope_threshold": slope_threshold,
"trend_strength": trend_strength,
"atr": df['atr'].iloc[-1],
"price": df['close'].iloc[-1],
"regime_info": regime_info
}
except Exception as e:
print(f"Error in get_enhanced_trend: {e}")
return None
# =============================================================================
# 4. OPTIMIZED TOP-DOWN ANALYSIS
# =============================================================================
def extended_top_down_v2(symbol="XAUUSD", lookback=150):
"""
Optimierte Top-Down-Analyse mit adaptiven Parametern
"""
timeframes = ["D1", "H4", "H1", "M30", "M15", "M5"]
trend_info = {}
# 1. Alle Timeframes analysieren
for tf in timeframes:
trend_info[tf] = get_enhanced_trend(tf, lookback, symbol)
if trend_info[tf] is None:
print(f"⚠️ Keine Daten für {tf}")
return None
# 2. Market Regime aus H4 bestimmen (repräsentativ)
main_regime = trend_info["H4"]["regime_info"]
# 3. Adaptive Confidence Threshold
adaptive_confidence_threshold = calculate_adaptive_confidence_threshold(main_regime)
# 4. Enhanced Standard-Trend (D1 + H4 mit Gewichtung)
d1_trend = trend_info["D1"]["trend"]
h4_trend = trend_info["H4"]["trend"]
d1_strength = trend_info["D1"]["trend_strength"]
h4_strength = trend_info["H4"]["trend_strength"]
# Gewichteter Standard-Trend
if d1_trend == h4_trend and d1_trend != "sideways":
standard_trend = d1_trend
standard_strength = (d1_strength * 0.6 + h4_strength * 0.4)
elif d1_strength > h4_strength * 1.5: # D1 deutlich stärker
standard_trend = d1_trend
standard_strength = d1_strength * 0.8
elif h4_strength > d1_strength * 1.5: # H4 deutlich stärker
standard_trend = h4_trend
standard_strength = h4_strength * 0.8
else:
standard_trend = "sideways"
standard_strength = 0
# 5. Enhanced Fast-Trend mit Regime-Awareness
fast_timeframes = ["H1", "M30", "M15", "M5"]
fast_trends = [trend_info[tf]["trend"] for tf in fast_timeframes]
fast_strengths = [trend_info[tf]["trend_strength"] for tf in fast_timeframes]
# Regime-abhängige Fast-Trend Logik
if main_regime['regime'] == 'trending':
# In Trends: 2 von 4 TFs reichen
required_alignment = 2
else:
# In Ranging/Volatile: 3 von 4 TFs erforderlich
required_alignment = 3
trend_counts = {'uptrend': 0, 'downtrend': 0, 'sideways': 0}
weighted_strengths = {'uptrend': 0, 'downtrend': 0}
weights = [1.0, 0.8, 0.6, 0.4] # H1, M30, M15, M5
for i, (trend, strength) in enumerate(zip(fast_trends, fast_strengths)):
trend_counts[trend] += 1
if trend != 'sideways':
weighted_strengths[trend] += strength * weights[i]
# Fast-Trend bestimmen
max_count = max(trend_counts['uptrend'], trend_counts['downtrend'])
if max_count >= required_alignment:
if trend_counts['uptrend'] > trend_counts['downtrend']:
fast_trend = "uptrend"
elif trend_counts['downtrend'] > trend_counts['uptrend']:
fast_trend = "downtrend"
else:
# Bei Gleichstand: Stärke entscheidet
if weighted_strengths['uptrend'] > weighted_strengths['downtrend']:
fast_trend = "uptrend"
else:
fast_trend = "downtrend"
else:
fast_trend = "sideways"
# 6. Top-Down-Trend Bestimmung
if standard_trend == fast_trend and standard_trend != "sideways":
top_down_trend = standard_trend
combined_strength = (standard_strength + weighted_strengths.get(fast_trend, 0)) / 2
else:
top_down_trend = "sideways"
combined_strength = 0
# 7. Enhanced Confidence Calculation
weights = {"D1": 2.5, "H4": 2.0, "H1": 1.5, "M30": 1.0, "M15": 0.8, "M5": 0.6}
weighted_matching = sum(
weights[tf] * trend_info[tf]["trend_strength"]
for tf in timeframes
if trend_info[tf]["trend"] == top_down_trend and trend_info[tf]["trend"] != "sideways"
)
weighted_total = sum(
weights[tf] * trend_info[tf]["trend_strength"]
for tf in timeframes
if trend_info[tf]["trend"] != "sideways"
)
confidence = round((weighted_matching / weighted_total) * 100, 2) if weighted_total > 0 else 0.0
# 8. Risk-Adjusted Signal Strength
atr = trend_info["M5"]["atr"]
rrr = 2.5 # Risk-Reward Ratio
risk_adjusted_strength = confidence * combined_strength * min(2.0, rrr)
# 9. Entry Signal mit adaptiven Kriterien
entry_signal = 0
signal_quality = "none"
if (top_down_trend != "sideways" and
confidence >= adaptive_confidence_threshold and
risk_adjusted_strength >= 100):
entry_signal = 1 if top_down_trend == "uptrend" else -1
# Signal Quality Assessment
if confidence >= 85 and risk_adjusted_strength >= 150:
signal_quality = "excellent"
elif confidence >= 75 and risk_adjusted_strength >= 120:
signal_quality = "good"
else:
signal_quality = "fair"
# 10. Enhanced Debug Output
debug_data = []
for tf in timeframes:
info = trend_info[tf]
debug_data.append([
tf,
info["trend"],
f"{info['trend_strength']:.2f}",
f"{info['atr']:.4f}",
f"{info['slope']:.6f}",
f"{info['price']:.2f}"
])
print(f"\n📊 Enhanced Trend-Analyse für {symbol}")
print(f"🎯 Market Regime: {main_regime['regime'].upper()} (Strength: {main_regime['strength']:.0f}%)")
print(f"🎚️ Adaptive Confidence Threshold: {adaptive_confidence_threshold}%")
print()
print(tabulate(debug_data, headers=["TF", "Trend", "Strength", "ATR", "Slope", "Price"], tablefmt="psql"))
print(f"\n➡️ Standard-Trend: {standard_trend} (Strength: {standard_strength:.2f})")
print(f"➡️ Fast-Trend: {fast_trend}")
print(f"➡️ Top-Down-Trend: {top_down_trend}")
print(f"➡️ Confidence: {confidence}% (Threshold: {adaptive_confidence_threshold}%)")
print(f"➡️ Risk-Adjusted Strength: {risk_adjusted_strength:.1f}")
print(f"➡️ Signal Quality: {signal_quality.upper()}")
return {
"symbol": symbol,
"trend_info": trend_info,
"market_regime": main_regime,
"standard_trend": standard_trend,
"fast_trend": fast_trend,
"top_down_trend": top_down_trend,
"confidence": confidence,
"adaptive_threshold": adaptive_confidence_threshold,
"risk_adjusted_strength": risk_adjusted_strength,
"entry_signal": entry_signal,
"signal_quality": signal_quality,
"combined_strength": combined_strength
}
# =============================================================================
# 5. ENTRY TIMING OPTIMIZATION
# =============================================================================
def check_pullback_entry(symbol, signal_info, timeframe="M5"):
"""
Prüft optimale Entry-Timing durch Pullback-Analyse
"""
if signal_info["entry_signal"] == 0:
return False, "No base signal"
try:
df = get_rates(timeframe.lower(), 50, symbol)
if df is None or len(df) < 20:
return False, "Insufficient data"
# EMAs für Pullback-Erkennung
df['ema21'] = df['close'].ewm(span=21).mean()
df['ema50'] = df['close'].ewm(span=50).mean()
current_price = df['close'].iloc[-1]
ema21 = df['ema21'].iloc[-1]
ema50 = df['ema50'].iloc[-1]
signal_direction = signal_info["entry_signal"]
if signal_direction == 1: # Long Signal
# Pullback zu EMA21 oder Support
if current_price <= ema21 * 1.002 and ema21 > ema50:
return True, "Pullback to EMA21 for Long"
elif current_price <= ema21 * 0.998:
return True, "Below EMA21 - Good Long Entry"
elif signal_direction == -1: # Short Signal
# Pullback zu EMA21 oder Resistance
if current_price >= ema21 * 0.998 and ema21 < ema50:
return True, "Pullback to EMA21 for Short"
elif current_price >= ema21 * 1.002:
return True, "Above EMA21 - Good Short Entry"
return False, "Waiting for better entry timing"
except Exception as e:
print(f"Error in pullback check: {e}")
return True, "Using immediate entry (fallback)"
# =============================================================================
# 6. ENHANCED EXECUTE TRADE FUNCTION
# =============================================================================
def execute_trade_v2(
symbol="XAUUSD",
atr_mult=1.5,
base_confidence=70,
max_risk_per_trade=0.01,
risk_filter=True,
min_atr=0.0010,
use_pullback_entry=True,
debug=True
):
"""
Optimierte Trade-Ausführung mit allen Verbesserungen
"""
# 1. Enhanced Signal Analysis
signal_info = extended_top_down_v2(symbol)
if signal_info is None:
print("❌ Signal-Analyse fehlgeschlagen")
return None
entry_signal = signal_info["entry_signal"]
confidence = signal_info["confidence"]
adaptive_threshold = signal_info["adaptive_threshold"]
signal_quality = signal_info["signal_quality"]
market_regime = signal_info["market_regime"]
# 2. Get Price/ATR from M5
m5_info = signal_info["trend_info"]["M5"]
price = m5_info["price"]
atr = m5_info["atr"]
# 3. Enhanced Pre-checks
reason = ""
if confidence < adaptive_threshold:
reason = f"Confidence {confidence}% < adaptive threshold {adaptive_threshold}%"
elif entry_signal == 0:
reason = f"No entry signal (Trend: {signal_info['top_down_trend']}, Regime: {market_regime['regime']})"
elif price is None or atr is None:
reason = "Price/ATR not available"
elif risk_filter and atr < min_atr:
reason = f"ATR {atr:.5f} < min_atr {min_atr}"
elif signal_quality == "none":
reason = "Signal quality insufficient"
else:
# 4. Entry Timing Check
if use_pullback_entry:
pullback_ok, pullback_reason = check_pullback_entry(symbol, signal_info)
if not pullback_ok:
reason = f"Entry timing: {pullback_reason}"
if not reason:
# 5. Enhanced Risk Checks
risk_ok = check_risk_limits(symbol, max_risk_per_trade=max_risk_per_trade)
if not risk_ok:
reason = "Risk limits exceeded"
# 6. Execute Trade if all checks pass
if not reason:
# Enhanced SL/TP calculation based on regime
regime_mult = 1.0
if market_regime['regime'] == 'volatile':
regime_mult = 1.3 # Wider stops in volatile markets
elif market_regime['regime'] == 'ranging':
regime_mult = 0.8 # Tighter stops in ranging markets
adjusted_atr_mult = atr_mult * regime_mult
if entry_signal == 1: # Long
stop_loss = price - adjusted_atr_mult * atr
take_profit = price + adjusted_atr_mult * atr * 2.5 # Better RRR
else: # Short
stop_loss = price + adjusted_atr_mult * atr
take_profit = price - adjusted_atr_mult * atr * 2.5
# Dynamic Position Sizing (vereinfacht)
stop_distance = adjusted_atr_mult * atr
account_info = mt.account_info()
if account_info:
balance = account_info.balance
risk_amount = balance * max_risk_per_trade
# Vereinfachte Volumen-Berechnung
if symbol == "XAUUSD":
volume = min(0.1, max(0.01, risk_amount / (stop_distance * 100)))
else:
volume = 0.01 # Standard für andere Symbole
else:
volume = 0.01
# Log Enhanced Trade Info
print(f"\n🚀 ENHANCED TRADE EXECUTION")
print(f"Symbol: {symbol}")
print(f"Direction: {'LONG' if entry_signal == 1 else 'SHORT'}")
print(f"Price: {price:.5f}")
print(f"Volume: {volume:.2f}")
print(f"Stop Loss: {stop_loss:.5f}")
print(f"Take Profit: {take_profit:.5f}")
print(f"Confidence: {confidence}% (Threshold: {adaptive_threshold}%)")
print(f"Signal Quality: {signal_quality.upper()}")
print(f"Market Regime: {market_regime['regime'].upper()}")
print(f"ATR Multiplier: {adjusted_atr_mult:.2f} (Base: {atr_mult})")
print(f"Risk per Trade: {max_risk_per_trade*100:.1f}%")
# Execute the actual trade
try:
order_result = market_order(
symbol=symbol,
volume=volume,
order_type="buy" if entry_signal == 1 else "sell",
stoploss=stop_loss,
take_profit=take_profit
)
# Log Trade to Performance Monitor
log_trade_performance(signal_info, order_result)
return order_result
except Exception as e:
print(f"❌ Trade execution failed: {e}")
return None
else:
if debug:
print(f"\n⏸️ TRADE SKIPPED: {reason}")
print(f"Confidence: {confidence}% | Threshold: {adaptive_threshold}%")
print(f"Signal Quality: {signal_quality} | Regime: {market_regime['regime']}")
return None
# =============================================================================
# 7. PERFORMANCE MONITORING
# =============================================================================
def log_trade_performance(signal_info, order_result):
"""
Loggt Trade-Performance für Analyse und Optimierung
"""
trade_data = {
'timestamp': datetime.now().isoformat(),
'symbol': signal_info['symbol'],
'entry_signal': signal_info['entry_signal'],
'confidence': signal_info['confidence'],
'adaptive_threshold': signal_info['adaptive_threshold'],
'signal_quality': signal_info['signal_quality'],
'market_regime': signal_info['market_regime']['regime'],
'regime_strength': signal_info['market_regime']['strength'],
'risk_adjusted_strength': signal_info['risk_adjusted_strength'],
'order_result': str(order_result) if order_result else None
}
# Save to JSON file for analysis
try:
filename = f"trade_performance_{signal_info['symbol']}_{datetime.now().strftime('%Y%m')}.json"
try:
with open(filename, 'r') as f:
data = json.load(f)
except FileNotFoundError:
data = []
data.append(trade_data)
with open(filename, 'w') as f:
json.dump(data, f, indent=2)
except Exception as e:
print(f"Warning: Could not log performance data: {e}")
def analyze_performance(symbol="XAUUSD", days_back=30):
"""
Analysiert Performance der letzten Trades
"""
try:
filename = f"trade_performance_{symbol}_{datetime.now().strftime('%Y%m')}.json"
with open(filename, 'r') as f:
data = json.load(f)
# Filter last X days
cutoff = datetime.now() - timedelta(days=days_back)
recent_trades = [
trade for trade in data
if datetime.fromisoformat(trade['timestamp']) > cutoff
]
if not recent_trades:
print(f"No trades found in last {days_back} days")
return
# Analysis
total_trades = len(recent_trades)
by_regime = {}
by_confidence = {'high': 0, 'medium': 0, 'low': 0}
by_quality = {}
for trade in recent_trades:
# By regime
regime = trade['market_regime']
by_regime[regime] = by_regime.get(regime, 0) + 1
# By confidence
conf = trade['confidence']
if conf >= 85:
by_confidence['high'] += 1
elif conf >= 75:
by_confidence['medium'] += 1
else:
by_confidence['low'] += 1
# By quality
quality = trade['signal_quality']
by_quality[quality] = by_quality.get(quality, 0) + 1
print(f"\n📊 PERFORMANCE ANALYSIS - Last {days_back} days")
print(f"Total Trades: {total_trades}")
print(f"\nBy Market Regime:")
for regime, count in by_regime.items():
print(f" {regime.upper()}: {count} ({count/total_trades*100:.1f}%)")
print(f"\nBy Confidence Level:")
for level, count in by_confidence.items():
print(f" {level.upper()}: {count} ({count/total_trades*100:.1f}%)")
print(f"\nBy Signal Quality:")
for quality, count in by_quality.items():
print(f" {quality.upper()}: {count} ({count/total_trades*100:.1f}%)")
except Exception as e:
print(f"Could not analyze performance: {e}")
# =============================================================================
# 8. QUICK SETUP FUNCTION
# =============================================================================
def setup_optimized_trading():
"""
Quick setup für optimiertes Trading
"""
print("🚀 Setting up Optimized Trading Bot V1.4 - Fixed Version")
print("\nKey Improvements:")
print("✅ Adaptive confidence thresholds")
print("✅ Market regime detection")
print("✅ Enhanced entry timing")
print("✅ Risk-adjusted signal strength")
print("✅ Performance monitoring")
print("✅ Fixed import dependencies")
print("\nReady to trade with enhanced logic!")
if __name__ == "__main__":
setup_optimized_trading()
-849
View File
@@ -1,849 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# TradingBot V1.4 - Fixed Integration\n",
"\n",
"## ✅ **Korrigierte Version ohne externe Abhängigkeiten**\n",
"\n",
"Diese Version behebt das Import-Problem und integriert alle notwendigen Funktionen direkt."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. Standard Imports"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Standard Imports aus deiner V1.3\n",
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"import mplfinance as mpf\n",
"import keyring as kr\n",
"import MetaTrader5 as mt\n",
"import requests\n",
"import re\n",
"from time import sleep\n",
"import sqlite3 as db\n",
"import pandas_ta as ta\n",
"import numpy as np\n",
"from sklearn.linear_model import LinearRegression\n",
"from scipy.signal import savgol_filter, find_peaks\n",
"from tabulate import tabulate\n",
"from ta.trend import ADXIndicator, EMAIndicator\n",
"from ta.momentum import RSIIndicator\n",
"from talib import CDLHAMMER, CDLSHOOTINGSTAR\n",
"from datetime import datetime, timedelta\n",
"import json"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. Login & Setup (unverändert)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Login zu MT5\n",
"mt.initialize()\n",
" \n",
"login = 10800246\n",
"server = 'VantageInternational-Demo'\n",
"password = kr.get_password(server, str(login))\n",
"\n",
"login_result = mt.login(login, password, server)\n",
"print(f\"Login successful: {login_result}\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Trading Parameter\n",
"symbol = \"XAUUSD\"\n",
"pause_trading = 0\n",
"strategy_name = \"TradingBot_V1.4_Fixed\"\n",
"\n",
"print(f\"Symbol: {symbol}\")\n",
"print(f\"Strategy: {strategy_name}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. Integrierte Hilfsfunktionen"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def get_rates(timeframe=\"h4\", count=200, symbol=\"XAUUSD\"):\n",
" \"\"\"\n",
" Holt Kursdaten von MT5\n",
" \"\"\"\n",
" timeframes_dict = {\n",
" \"m1\": mt.TIMEFRAME_M1,\n",
" \"m5\": mt.TIMEFRAME_M5,\n",
" \"m15\": mt.TIMEFRAME_M15,\n",
" \"m30\": mt.TIMEFRAME_M30,\n",
" \"h1\": mt.TIMEFRAME_H1,\n",
" \"h4\": mt.TIMEFRAME_H4,\n",
" \"d1\": mt.TIMEFRAME_D1\n",
" }\n",
" \n",
" try:\n",
" rates = mt.copy_rates_from_pos(symbol, timeframes_dict[timeframe], 0, count)\n",
" if rates is None:\n",
" return None\n",
" \n",
" df = pd.DataFrame(rates)\n",
" df['time'] = pd.to_datetime(df['time'], unit='s')\n",
" df.set_index('time', inplace=True)\n",
" \n",
" # ATR hinzufügen\n",
" df['atr'] = ta.atr(df['high'], df['low'], df['close'], length=14)\n",
" \n",
" return df\n",
" \n",
" except Exception as e:\n",
" print(f\"Error getting rates: {e}\")\n",
" return None\n",
"\n",
"# Test der get_rates Funktion\n",
"test_data = get_rates(\"h4\", 50, symbol)\n",
"if test_data is not None:\n",
" print(f\"✅ get_rates working - got {len(test_data)} bars\")\n",
" print(f\"Latest price: {test_data['close'].iloc[-1]:.5f}\")\n",
"else:\n",
" print(\"❌ get_rates failed\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def check_risk_limits(symbol, volume=None, order_type=\"buy\", max_risk_per_trade=0.01):\n",
" \"\"\"\n",
" Prüft alle Risikolimits (vereinfachte Version)\n",
" \"\"\"\n",
" try:\n",
" account_info = mt.account_info()\n",
" if not account_info:\n",
" print(\"⚠️ Kontodaten nicht verfügbar.\")\n",
" return False\n",
" \n",
" # Einfache Checks\n",
" balance = account_info.balance\n",
" equity = account_info.equity\n",
" \n",
" # Basis-Risiko-Check\n",
" if equity < balance * 0.8: # Mehr als 20% Verlust\n",
" print(\"⚠️ Drawdown-Limit erreicht\")\n",
" return False\n",
" \n",
" return True\n",
" \n",
" except Exception as e:\n",
" print(f\"Error in risk check: {e}\")\n",
" return False\n",
"\n",
"def market_order(symbol, volume, order_type, stoploss=None, take_profit=None, deviation=20):\n",
" \"\"\"\n",
" Führt Market Order aus (vereinfachte Version)\n",
" \"\"\"\n",
" try:\n",
" price_dict = {\n",
" 'buy': mt.symbol_info_tick(symbol).ask,\n",
" 'sell': mt.symbol_info_tick(symbol).bid\n",
" }\n",
" \n",
" order_type_dict = {\n",
" 'buy': mt.ORDER_TYPE_BUY,\n",
" 'sell': mt.ORDER_TYPE_SELL\n",
" }\n",
" \n",
" request = {\n",
" \"action\": mt.TRADE_ACTION_DEAL,\n",
" \"symbol\": symbol,\n",
" \"volume\": volume,\n",
" \"type\": order_type_dict[order_type],\n",
" \"price\": price_dict[order_type],\n",
" \"sl\": stoploss,\n",
" \"tp\": take_profit,\n",
" \"deviation\": deviation,\n",
" \"magic\": 234000,\n",
" \"comment\": strategy_name,\n",
" \"type_time\": mt.ORDER_TIME_GTC,\n",
" \"type_filling\": mt.ORDER_FILLING_IOC,\n",
" }\n",
" \n",
" result = mt.order_send(request)\n",
" return result\n",
" \n",
" except Exception as e:\n",
" print(f\"Error in market order: {e}\")\n",
" return None\n",
"\n",
"print(\"✅ Hilfsfunktionen definiert\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 4. Market Regime Detection"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def detect_market_regime(df, lookback=50):\n",
" \"\"\"\n",
" Erkennt das aktuelle Marktregime (Trending vs. Ranging)\n",
" \"\"\"\n",
" try:\n",
" # ADX für Trendstärke\n",
" adx_data = ta.adx(df['high'], df['low'], df['close'], length=14)\n",
" if adx_data is None or 'ADX_14' not in adx_data.columns:\n",
" adx = 25.0 # Standardwert\n",
" else:\n",
" adx = adx_data['ADX_14'].iloc[-1] if not pd.isna(adx_data['ADX_14'].iloc[-1]) else 25.0\n",
" \n",
" # Bollinger Band Squeeze für Ranging Markets\n",
" try:\n",
" bb = ta.bbands(df['close'], length=20)\n",
" if bb is not None and len(bb.columns) >= 3:\n",
" bb_cols = bb.columns.tolist()\n",
" bb_upper = bb[bb_cols[0]] # Oberes Band\n",
" bb_middle = bb[bb_cols[1]] # Mittleres Band\n",
" bb_lower = bb[bb_cols[2]] # Unteres Band\n",
" bb_width = ((bb_upper - bb_lower) / bb_middle * 100).iloc[-lookback:].mean()\n",
" else:\n",
" bb_width = 4.0 # Standardwert\n",
" except:\n",
" bb_width = 4.0\n",
" \n",
" # Price Action Analysis\n",
" price_range = (df['high'].iloc[-lookback:].max() - df['low'].iloc[-lookback:].min())\n",
" atr_avg = df['atr'].iloc[-lookback:].mean()\n",
" range_ratio = price_range / (atr_avg * lookback) if atr_avg > 0 else 1.0\n",
" \n",
" # Volatility Cluster Detection\n",
" vol_cluster = df['atr'].iloc[-10:].std() / df['atr'].iloc[-50:].mean() if len(df) >= 50 else 1.0\n",
" \n",
" # Regime-Bestimmung\n",
" if adx > 25 and range_ratio > 1.5:\n",
" regime = 'trending'\n",
" strength = min(100, adx * 2)\n",
" elif vol_cluster > 1.5:\n",
" regime = 'volatile'\n",
" strength = min(100, vol_cluster * 50)\n",
" else:\n",
" regime = 'ranging'\n",
" strength = max(0, 100 - adx * 2)\n",
" \n",
" return {\n",
" 'regime': regime,\n",
" 'strength': strength,\n",
" 'adx': adx,\n",
" 'bb_width': bb_width,\n",
" 'range_ratio': range_ratio,\n",
" 'vol_cluster': vol_cluster\n",
" }\n",
" \n",
" except Exception as e:\n",
" print(f\"Error in regime detection: {e}\")\n",
" # Fallback\n",
" return {\n",
" 'regime': 'ranging',\n",
" 'strength': 50,\n",
" 'adx': 20,\n",
" 'bb_width': 4.0,\n",
" 'range_ratio': 1.0,\n",
" 'vol_cluster': 1.0\n",
" }\n",
"\n",
"# Test Market Regime Detection\n",
"if test_data is not None:\n",
" regime = detect_market_regime(test_data)\n",
" print(\"\\n🎯 Market Regime Test:\")\n",
" print(f\"Regime: {regime['regime'].upper()}\")\n",
" print(f\"Strength: {regime['strength']:.1f}%\")\n",
" print(f\"ADX: {regime['adx']:.1f}\")\n",
" print(f\"Volatility Cluster: {regime['vol_cluster']:.2f}\")\n",
"else:\n",
" print(\"❌ Cannot test regime detection without data\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5. Adaptive Confidence System"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def calculate_adaptive_confidence_threshold(regime_info, base_confidence=70):\n",
" \"\"\"\n",
" Berechnet adaptive Confidence-Schwelle basierend auf Marktregime\n",
" \"\"\"\n",
" regime = regime_info['regime']\n",
" strength = regime_info['strength']\n",
" adx = regime_info['adx']\n",
" \n",
" if regime == 'trending':\n",
" # In Trending Markets: niedrigere Schwelle bei starken Trends\n",
" if adx > 30:\n",
" return max(60, base_confidence - 15)\n",
" else:\n",
" return base_confidence - 10\n",
" \n",
" elif regime == 'ranging':\n",
" # In Ranging Markets: höhere Schwelle für mehr Selektivität\n",
" return base_confidence + 15\n",
" \n",
" elif regime == 'volatile':\n",
" # In Volatile Markets: deutlich höhere Schwelle\n",
" return base_confidence + 20\n",
" \n",
" return base_confidence\n",
"\n",
"# Test Adaptive Confidence\n",
"if test_data is not None:\n",
" regime = detect_market_regime(test_data)\n",
" adaptive_threshold = calculate_adaptive_confidence_threshold(regime)\n",
" print(f\"\\n🎚️ Adaptive Confidence Test:\")\n",
" print(f\"Base Confidence: 70%\")\n",
" print(f\"Regime: {regime['regime'].upper()}\")\n",
" print(f\"Adaptive Threshold: {adaptive_threshold}%\")\n",
" print(f\"Adjustment: {adaptive_threshold - 70:+d}%\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 6. Enhanced Trend Analysis"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def get_enhanced_trend(timeframe=\"H4\", lookback=150, symbol=\"XAUUSD\"):\n",
" \"\"\"\n",
" Verbesserte Trend-Analyse mit Regime-Awareness\n",
" \"\"\"\n",
" # Timeframe mapping\n",
" tf_map = {\"D1\": \"d1\", \"H4\": \"h4\", \"H1\": \"h1\", \"M30\": \"m30\", \"M15\": \"m15\", \"M5\": \"m5\"}\n",
" tf = tf_map.get(timeframe, timeframe.lower())\n",
" \n",
" try:\n",
" df = get_rates(tf, lookback, symbol)\n",
" if df is None or len(df) < 50:\n",
" return None\n",
" \n",
" # Bestehende Trend-Logik\n",
" df['close_smooth'] = savgol_filter(df['close'], min(15, len(df)//10), 3)\n",
" \n",
" # Linear Regression\n",
" X = np.arange(len(df)).reshape(-1, 1)\n",
" y = df['close_smooth'].values\n",
" model = LinearRegression().fit(X, y)\n",
" slope = model.coef_[0]\n",
" \n",
" # Market Regime Detection\n",
" regime_info = detect_market_regime(df.iloc[-50:])\n",
" \n",
" # Adaptive Slope Threshold basierend auf Regime\n",
" base_threshold = df['atr'].iloc[-1] * 0.0001\n",
" \n",
" if regime_info['regime'] == 'trending':\n",
" slope_threshold = base_threshold * 0.7 # Niedrigere Schwelle in Trends\n",
" elif regime_info['regime'] == 'ranging':\n",
" slope_threshold = base_threshold * 1.5 # Höhere Schwelle in Ranges\n",
" else: # volatile\n",
" slope_threshold = base_threshold * 1.2\n",
" \n",
" # Trend bestimmen\n",
" if slope > slope_threshold:\n",
" trend = \"uptrend\"\n",
" elif slope < -slope_threshold:\n",
" trend = \"downtrend\"\n",
" else:\n",
" trend = \"sideways\"\n",
" \n",
" # Enhanced Trend Strength\n",
" trend_strength = abs(slope) / slope_threshold if slope_threshold > 0 else 0\n",
" \n",
" return {\n",
" \"trend\": trend,\n",
" \"slope\": slope,\n",
" \"slope_threshold\": slope_threshold,\n",
" \"trend_strength\": trend_strength,\n",
" \"atr\": df['atr'].iloc[-1],\n",
" \"price\": df['close'].iloc[-1],\n",
" \"regime_info\": regime_info\n",
" }\n",
" \n",
" except Exception as e:\n",
" print(f\"Error in get_enhanced_trend: {e}\")\n",
" return None\n",
"\n",
"# Test Enhanced Trend Analysis\n",
"print(\"\\n🔍 Testing Enhanced Trend Analysis...\")\n",
"trend_test = get_enhanced_trend(\"H4\", 100, symbol)\n",
"if trend_test:\n",
" print(f\"✅ Trend: {trend_test['trend'].upper()}\")\n",
" print(f\"✅ Strength: {trend_test['trend_strength']:.2f}\")\n",
" print(f\"✅ Price: {trend_test['price']:.5f}\")\n",
" print(f\"✅ ATR: {trend_test['atr']:.5f}\")\n",
" print(f\"✅ Regime: {trend_test['regime_info']['regime'].upper()}\")\n",
"else:\n",
" print(\"❌ Enhanced trend analysis failed\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 7. Optimized Top-Down Analysis"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def extended_top_down_v2(symbol=\"XAUUSD\", lookback=150):\n",
" \"\"\"\n",
" Optimierte Top-Down-Analyse mit adaptiven Parametern\n",
" \"\"\"\n",
" \n",
" timeframes = [\"D1\", \"H4\", \"H1\", \"M30\", \"M15\", \"M5\"]\n",
" trend_info = {}\n",
" \n",
" print(f\"🔍 Analyzing {symbol} across {len(timeframes)} timeframes...\")\n",
" \n",
" # 1. Alle Timeframes analysieren\n",
" for tf in timeframes:\n",
" print(f\" Analyzing {tf}...\")\n",
" trend_info[tf] = get_enhanced_trend(tf, lookback, symbol)\n",
" if trend_info[tf] is None:\n",
" print(f\"⚠️ Keine Daten für {tf}\")\n",
" return None\n",
" \n",
" # 2. Market Regime aus H4 bestimmen (repräsentativ)\n",
" main_regime = trend_info[\"H4\"][\"regime_info\"]\n",
" \n",
" # 3. Adaptive Confidence Threshold\n",
" adaptive_confidence_threshold = calculate_adaptive_confidence_threshold(main_regime)\n",
" \n",
" # 4. Enhanced Standard-Trend (D1 + H4 mit Gewichtung)\n",
" d1_trend = trend_info[\"D1\"][\"trend\"]\n",
" h4_trend = trend_info[\"H4\"][\"trend\"]\n",
" d1_strength = trend_info[\"D1\"][\"trend_strength\"]\n",
" h4_strength = trend_info[\"H4\"][\"trend_strength\"]\n",
" \n",
" # Gewichteter Standard-Trend\n",
" if d1_trend == h4_trend and d1_trend != \"sideways\":\n",
" standard_trend = d1_trend\n",
" standard_strength = (d1_strength * 0.6 + h4_strength * 0.4)\n",
" elif d1_strength > h4_strength * 1.5: # D1 deutlich stärker\n",
" standard_trend = d1_trend\n",
" standard_strength = d1_strength * 0.8\n",
" elif h4_strength > d1_strength * 1.5: # H4 deutlich stärker\n",
" standard_trend = h4_trend\n",
" standard_strength = h4_strength * 0.8\n",
" else:\n",
" standard_trend = \"sideways\"\n",
" standard_strength = 0\n",
" \n",
" # 5. Enhanced Fast-Trend mit Regime-Awareness\n",
" fast_timeframes = [\"H1\", \"M30\", \"M15\", \"M5\"]\n",
" fast_trends = [trend_info[tf][\"trend\"] for tf in fast_timeframes]\n",
" fast_strengths = [trend_info[tf][\"trend_strength\"] for tf in fast_timeframes]\n",
" \n",
" # Regime-abhängige Fast-Trend Logik\n",
" if main_regime['regime'] == 'trending':\n",
" # In Trends: 2 von 4 TFs reichen\n",
" required_alignment = 2\n",
" else:\n",
" # In Ranging/Volatile: 3 von 4 TFs erforderlich\n",
" required_alignment = 3\n",
" \n",
" trend_counts = {'uptrend': 0, 'downtrend': 0, 'sideways': 0}\n",
" weighted_strengths = {'uptrend': 0, 'downtrend': 0}\n",
" \n",
" weights = [1.0, 0.8, 0.6, 0.4] # H1, M30, M15, M5\n",
" \n",
" for i, (trend, strength) in enumerate(zip(fast_trends, fast_strengths)):\n",
" trend_counts[trend] += 1\n",
" if trend != 'sideways':\n",
" weighted_strengths[trend] += strength * weights[i]\n",
" \n",
" # Fast-Trend bestimmen\n",
" max_count = max(trend_counts['uptrend'], trend_counts['downtrend'])\n",
" if max_count >= required_alignment:\n",
" if trend_counts['uptrend'] > trend_counts['downtrend']:\n",
" fast_trend = \"uptrend\"\n",
" elif trend_counts['downtrend'] > trend_counts['uptrend']:\n",
" fast_trend = \"downtrend\"\n",
" else:\n",
" # Bei Gleichstand: Stärke entscheidet\n",
" if weighted_strengths['uptrend'] > weighted_strengths['downtrend']:\n",
" fast_trend = \"uptrend\"\n",
" else:\n",
" fast_trend = \"downtrend\"\n",
" else:\n",
" fast_trend = \"sideways\"\n",
" \n",
" # 6. Top-Down-Trend Bestimmung\n",
" if standard_trend == fast_trend and standard_trend != \"sideways\":\n",
" top_down_trend = standard_trend\n",
" combined_strength = (standard_strength + weighted_strengths.get(fast_trend, 0)) / 2\n",
" else:\n",
" top_down_trend = \"sideways\"\n",
" combined_strength = 0\n",
" \n",
" # 7. Enhanced Confidence Calculation\n",
" weights = {\"D1\": 2.5, \"H4\": 2.0, \"H1\": 1.5, \"M30\": 1.0, \"M15\": 0.8, \"M5\": 0.6}\n",
" \n",
" weighted_matching = sum(\n",
" weights[tf] * trend_info[tf][\"trend_strength\"] \n",
" for tf in timeframes\n",
" if trend_info[tf][\"trend\"] == top_down_trend and trend_info[tf][\"trend\"] != \"sideways\"\n",
" )\n",
" \n",
" weighted_total = sum(\n",
" weights[tf] * trend_info[tf][\"trend_strength\"]\n",
" for tf in timeframes\n",
" if trend_info[tf][\"trend\"] != \"sideways\"\n",
" )\n",
" \n",
" confidence = round((weighted_matching / weighted_total) * 100, 2) if weighted_total > 0 else 0.0\n",
" \n",
" # 8. Risk-Adjusted Signal Strength\n",
" atr = trend_info[\"M5\"][\"atr\"]\n",
" rrr = 2.5 # Risk-Reward Ratio\n",
" \n",
" risk_adjusted_strength = confidence * combined_strength * min(2.0, rrr)\n",
" \n",
" # 9. Entry Signal mit adaptiven Kriterien\n",
" entry_signal = 0\n",
" signal_quality = \"none\"\n",
" \n",
" if (top_down_trend != \"sideways\" and \n",
" confidence >= adaptive_confidence_threshold and\n",
" risk_adjusted_strength >= 100):\n",
" \n",
" entry_signal = 1 if top_down_trend == \"uptrend\" else -1\n",
" \n",
" # Signal Quality Assessment\n",
" if confidence >= 85 and risk_adjusted_strength >= 150:\n",
" signal_quality = \"excellent\"\n",
" elif confidence >= 75 and risk_adjusted_strength >= 120:\n",
" signal_quality = \"good\"\n",
" else:\n",
" signal_quality = \"fair\"\n",
" \n",
" # 10. Enhanced Debug Output\n",
" debug_data = []\n",
" for tf in timeframes:\n",
" info = trend_info[tf]\n",
" debug_data.append([\n",
" tf,\n",
" info[\"trend\"],\n",
" f\"{info['trend_strength']:.2f}\",\n",
" f\"{info['atr']:.4f}\",\n",
" f\"{info['slope']:.6f}\",\n",
" f\"{info['price']:.2f}\"\n",
" ])\n",
" \n",
" print(f\"\\n📊 Enhanced Trend-Analyse für {symbol}\")\n",
" print(f\"🎯 Market Regime: {main_regime['regime'].upper()} (Strength: {main_regime['strength']:.0f}%)\")\n",
" print(f\"🎚️ Adaptive Confidence Threshold: {adaptive_confidence_threshold}%\")\n",
" print()\n",
" print(tabulate(debug_data, headers=[\"TF\", \"Trend\", \"Strength\", \"ATR\", \"Slope\", \"Price\"], tablefmt=\"psql\"))\n",
" print(f\"\\n➡️ Standard-Trend: {standard_trend} (Strength: {standard_strength:.2f})\")\n",
" print(f\"➡️ Fast-Trend: {fast_trend}\")\n",
" print(f\"➡️ Top-Down-Trend: {top_down_trend}\")\n",
" print(f\"➡️ Confidence: {confidence}% (Threshold: {adaptive_confidence_threshold}%)\")\n",
" print(f\"➡️ Risk-Adjusted Strength: {risk_adjusted_strength:.1f}\")\n",
" print(f\"➡️ Signal Quality: {signal_quality.upper()}\")\n",
" \n",
" return {\n",
" \"symbol\": symbol,\n",
" \"trend_info\": trend_info,\n",
" \"market_regime\": main_regime,\n",
" \"standard_trend\": standard_trend,\n",
" \"fast_trend\": fast_trend,\n",
" \"top_down_trend\": top_down_trend,\n",
" \"confidence\": confidence,\n",
" \"adaptive_threshold\": adaptive_confidence_threshold,\n",
" \"risk_adjusted_strength\": risk_adjusted_strength,\n",
" \"entry_signal\": entry_signal,\n",
" \"signal_quality\": signal_quality,\n",
" \"combined_strength\": combined_strength\n",
" }\n",
"\n",
"print(\"✅ Extended Top-Down V2 function defined\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 8. Test der optimierten Signallogik"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Test Enhanced Top-Down Analysis\n",
"print(\"🔍 Testing Enhanced Top-Down Analysis...\\n\")\n",
"signal_result = extended_top_down_v2(symbol)\n",
"\n",
"if signal_result:\n",
" print(f\"\\n🎯 SIGNAL SUMMARY:\")\n",
" print(f\"Entry Signal: {signal_result['entry_signal']}\")\n",
" print(f\"Confidence: {signal_result['confidence']}%\")\n",
" print(f\"Adaptive Threshold: {signal_result['adaptive_threshold']}%\")\n",
" print(f\"Signal Quality: {signal_result['signal_quality'].upper()}\")\n",
" print(f\"Market Regime: {signal_result['market_regime']['regime'].upper()}\")\n",
" print(f\"Risk-Adjusted Strength: {signal_result['risk_adjusted_strength']:.1f}\")\n",
" \n",
" # Zusätzliche Analyse\n",
" if signal_result['entry_signal'] != 0:\n",
" direction = \"LONG\" if signal_result['entry_signal'] == 1 else \"SHORT\"\n",
" print(f\"\\n🚀 TRADING SIGNAL: {direction}\")\n",
" print(f\"Quality: {signal_result['signal_quality'].upper()}\")\n",
" print(f\"Regime-optimized for: {signal_result['market_regime']['regime'].upper()} market\")\n",
" else:\n",
" print(f\"\\n⏸️ NO TRADING SIGNAL\")\n",
" print(f\"Reason: Confidence {signal_result['confidence']}% < Threshold {signal_result['adaptive_threshold']}%\")\n",
"else:\n",
" print(\"❌ Signal analysis failed\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 9. Vergleich mit ursprünglicher Logik"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def compare_signal_logic():\n",
" \"\"\"\n",
" Vergleicht V1.3 vs V1.4 Signallogik\n",
" \"\"\"\n",
" if signal_result:\n",
" print(\"\\n📊 VERGLEICH V1.3 vs V1.4\")\n",
" print(\"=\" * 50)\n",
" \n",
" # V1.3 hätte feste 80% Schwelle\n",
" v13_threshold = 80\n",
" v14_threshold = signal_result['adaptive_threshold']\n",
" current_confidence = signal_result['confidence']\n",
" \n",
" # V1.3 Signal\n",
" v13_signal = 1 if (signal_result['top_down_trend'] == 'uptrend' and current_confidence >= v13_threshold) else (\n",
" -1 if (signal_result['top_down_trend'] == 'downtrend' and current_confidence >= v13_threshold) else 0)\n",
" \n",
" # V1.4 Signal\n",
" v14_signal = signal_result['entry_signal']\n",
" \n",
" comparison_data = [\n",
" [\"Metric\", \"V1.3 (Old)\", \"V1.4 (New)\", \"Improvement\"],\n",
" [\"Confidence Threshold\", f\"{v13_threshold}%\", f\"{v14_threshold}%\", f\"{v14_threshold-v13_threshold:+d}%\"],\n",
" [\"Current Confidence\", f\"{current_confidence}%\", f\"{current_confidence}%\", \"Same\"],\n",
" [\"Entry Signal\", f\"{v13_signal}\", f\"{v14_signal}\", \"✅\" if v14_signal != 0 else \"⏸️\"],\n",
" [\"Market Regime\", \"Not considered\", signal_result['market_regime']['regime'].upper(), \"✅ New\"],\n",
" [\"Signal Quality\", \"Binary\", signal_result['signal_quality'].upper(), \"✅ Graded\"],\n",
" [\"Risk-Adj. Strength\", \"Not calculated\", f\"{signal_result['risk_adjusted_strength']:.1f}\", \"✅ New\"]\n",
" ]\n",
" \n",
" print(tabulate(comparison_data, headers=\"firstrow\", tablefmt=\"psql\"))\n",
" \n",
" # Fazit\n",
" if v13_signal != v14_signal:\n",
" if v14_signal != 0 and v13_signal == 0:\n",
" print(\"\\n✅ V1.4 ADVANTAGE: Signal erkannt, den V1.3 verpasst hätte!\")\n",
" print(f\" Grund: Adaptive Schwelle {v14_threshold}% vs. feste {v13_threshold}%\")\n",
" elif v13_signal != 0 and v14_signal == 0:\n",
" print(\"\\n🛡️ V1.4 ADVANTAGE: Riskantes Signal gefiltert!\")\n",
" print(f\" Grund: {signal_result['market_regime']['regime'].upper()} market requires higher confidence\")\n",
" else:\n",
" print(\"\\n🤝 SAME RESULT: Both versions agree on signal\")\n",
" \n",
" print(f\"\\n🎯 V1.4 Benefits:\")\n",
" print(f\" • Regime-aware threshold: {v14_threshold}% (vs fixed 80%)\")\n",
" print(f\" • Quality assessment: {signal_result['signal_quality'].upper()}\")\n",
" print(f\" • Risk-adjusted strength: {signal_result['risk_adjusted_strength']:.1f}\")\n",
" print(f\" • Market regime: {signal_result['market_regime']['regime'].upper()}\")\n",
"\n",
"compare_signal_logic()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 10. Quick Test ohne vollständige Analyse"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Für schnelle Tests ohne vollständige Multi-Timeframe Analyse\n",
"def quick_regime_test(symbol=\"XAUUSD\"):\n",
" \"\"\"\n",
" Schneller Test der Regime-Erkennung\n",
" \"\"\"\n",
" print(f\"⚡ Quick Regime Test for {symbol}\")\n",
" \n",
" # Hole H4 Daten\n",
" df = get_rates(\"h4\", 100, symbol)\n",
" if df is None:\n",
" print(\"❌ No data available\")\n",
" return\n",
" \n",
" # Regime-Erkennung\n",
" regime = detect_market_regime(df)\n",
" adaptive_threshold = calculate_adaptive_confidence_threshold(regime)\n",
" \n",
" print(f\"\\n📊 Current Market Conditions:\")\n",
" print(f\" Regime: {regime['regime'].upper()}\")\n",
" print(f\" Strength: {regime['strength']:.1f}%\")\n",
" print(f\" ADX: {regime['adx']:.1f}\")\n",
" print(f\" Adaptive Threshold: {adaptive_threshold}% (vs 80% fixed)\")\n",
" print(f\" Current Price: {df['close'].iloc[-1]:.5f}\")\n",
" \n",
" # Trading-Empfehlung basierend auf Regime\n",
" if regime['regime'] == 'trending':\n",
" print(f\"\\n🎯 TRENDING MARKET - Good for trend-following strategies\")\n",
" print(f\" • Lower confidence threshold: {adaptive_threshold}%\")\n",
" print(f\" • Expect stronger directional moves\")\n",
" elif regime['regime'] == 'ranging':\n",
" print(f\"\\n📊 RANGING MARKET - Be more selective\")\n",
" print(f\" • Higher confidence threshold: {adaptive_threshold}%\")\n",
" print(f\" • Look for range breakouts\")\n",
" else: # volatile\n",
" print(f\"\\n⚡ VOLATILE MARKET - Use wider stops\")\n",
" print(f\" • Highest confidence threshold: {adaptive_threshold}%\")\n",
" print(f\" • Expect choppy price action\")\n",
"\n",
"# Führe Quick Test aus\n",
"quick_regime_test(symbol)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 11. Status & Next Steps"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(\"\\n🎉 TradingBot V1.4 - Fixed Version Ready!\")\n",
"print(\"=\"*50)\n",
"print(\"\\n✅ Successfully Fixed:\")\n",
"print(\" • Removed external dependencies\")\n",
"print(\" • Integrated all helper functions\")\n",
"print(\" • Fixed import errors\")\n",
"print(\" • Tested all components\")\n",
"\n",
"print(\"\\n🚀 Key Features Working:\")\n",
"print(\" • Market Regime Detection\")\n",
"print(\" • Adaptive Confidence Thresholds\")\n",
"print(\" • Enhanced Trend Analysis\")\n",
"print(\" • Multi-Timeframe Signal Logic\")\n",
"print(\" • Risk-Adjusted Signal Strength\")\n",
"\n",
"print(\"\\n📋 Next Steps:\")\n",
"print(\" 1. Run extended_top_down_v2() for full analysis\")\n",
"print(\" 2. Test with different market conditions\")\n",
"print(\" 3. Compare results with your V1.3\")\n",
"print(\" 4. Implement automated trading loop\")\n",
"print(\" 5. Monitor performance in demo mode\")\n",
"\n",
"print(\"\\n🎯 Ready for Testing!\")\n",
"print(f\" Current Symbol: {symbol}\")\n",
"print(f\" MT5 Connected: {'✅' if mt.terminal_info() else '❌'}\")\n",
"print(f\" Strategy: {strategy_name}\")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"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
}
-569
View File
@@ -1,569 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# TradingBot V1.4 - Optimized Integration\n",
"\n",
"## Verbesserungen gegenüber V1.3:\n",
"\n",
"### 🎯 **Hauptverbesserungen:**\n",
"1. **Adaptive Confidence Threshold** - Automatische Anpassung an Marktbedingungen\n",
"2. **Market Regime Detection** - Erkennung von Trending/Ranging/Volatile Märkten\n",
"3. **Entry Timing Optimization** - Pullback-basierte Entries für bessere R/R\n",
"4. **Risk-Adjusted Signal Strength** - Kombiniert Confidence mit Trend-Stärke\n",
"5. **Performance Monitoring** - Automatisches Tracking der Signal-Performance\n",
"\n",
"### 📊 **Technische Verbesserungen:**\n",
"- Regime-abhängige Parameter-Anpassung\n",
"- Gewichtete Trend-Stärke-Berechnung\n",
"- Adaptive ATR-Multiplikatoren\n",
"- Enhanced Debug-Output mit Regime-Info"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. Import optimierte Funktionen"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Import der optimierten Funktionen\n",
"from TradingBot_V1.4_Optimized import (\n",
" detect_market_regime,\n",
" calculate_adaptive_confidence_threshold,\n",
" get_enhanced_trend,\n",
" extended_top_down_v2,\n",
" check_pullback_entry,\n",
" execute_trade_v2,\n",
" log_trade_performance,\n",
" analyze_performance,\n",
" setup_optimized_trading\n",
")\n",
"\n",
"# Bestehende Imports aus V1.3\n",
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"import mplfinance as mpf\n",
"import keyring as kr\n",
"import MetaTrader5 as mt\n",
"import requests\n",
"import re\n",
"from time import sleep\n",
"import sqlite3 as db\n",
"import pandas_ta as ta\n",
"import numpy as np\n",
"from sklearn.linear_model import LinearRegression\n",
"from scipy.signal import savgol_filter, find_peaks\n",
"from tabulate import tabulate\n",
"from ta.trend import ADXIndicator, EMAIndicator\n",
"from ta.momentum import RSIIndicator\n",
"from talib import CDLHAMMER, CDLSHOOTINGSTAR"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. Setup & Login (unverändert)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Setup optimiertes Trading\n",
"setup_optimized_trading()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Login zu MT5 (unverändert)\n",
"mt.initialize()\n",
" \n",
"login = 10800246\n",
"server = 'VantageInternational-Demo'\n",
"password = kr.get_password(server, str(login))\n",
"\n",
"mt.login(login, password, server)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Projekt Setup (unverändert)\n",
"project = \"trading-\" + server[-4::1]\n",
"project = project.lower()\n",
"print(f\"Project: {project}\")\n",
"\n",
"# Trading Parameter\n",
"symbol = \"XAUUSD\"\n",
"pause_trading = 0\n",
"strategy_name = \"TradingBot_V1.4_Optimized\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. Bestehende Hilfsfunktionen (unverändert)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Hier würden deine bestehenden Funktionen stehen:\n",
"# - get_rates()\n",
"# - market_order()\n",
"# - check_risk_limits()\n",
"# etc.\n",
"\n",
"# Beispiel get_rates Funktion (falls nicht vorhanden):\n",
"def get_rates(timeframe=\"h4\", count=200):\n",
" \"\"\"\n",
" Holt Kursdaten von MT5\n",
" \"\"\"\n",
" timeframes_dict = {\n",
" \"m1\": mt.TIMEFRAME_M1,\n",
" \"m5\": mt.TIMEFRAME_M5,\n",
" \"m15\": mt.TIMEFRAME_M15,\n",
" \"m30\": mt.TIMEFRAME_M30,\n",
" \"h1\": mt.TIMEFRAME_H1,\n",
" \"h4\": mt.TIMEFRAME_H4,\n",
" \"d1\": mt.TIMEFRAME_D1\n",
" }\n",
" \n",
" try:\n",
" rates = mt.copy_rates_from_pos(symbol, timeframes_dict[timeframe], 0, count)\n",
" if rates is None:\n",
" return None\n",
" \n",
" df = pd.DataFrame(rates)\n",
" df['time'] = pd.to_datetime(df['time'], unit='s')\n",
" df.set_index('time', inplace=True)\n",
" \n",
" # ATR hinzufügen\n",
" df['atr'] = ta.atr(df['high'], df['low'], df['close'], length=14)\n",
" \n",
" return df\n",
" \n",
" except Exception as e:\n",
" print(f\"Error getting rates: {e}\")\n",
" return None"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 4. Test der optimierten Funktionen"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Test Market Regime Detection\n",
"df_test = get_rates(\"h4\", 100)\n",
"if df_test is not None:\n",
" regime = detect_market_regime(df_test)\n",
" print(\"🎯 Market Regime Analysis:\")\n",
" print(f\"Regime: {regime['regime'].upper()}\")\n",
" print(f\"Strength: {regime['strength']:.1f}%\")\n",
" print(f\"ADX: {regime['adx']:.1f}\")\n",
" print(f\"Volatility Cluster: {regime['vol_cluster']:.2f}\")\n",
"else:\n",
" print(\"❌ Could not get test data\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Test Enhanced Top-Down Analysis\n",
"print(\"🔍 Testing Enhanced Top-Down Analysis...\\n\")\n",
"signal_result = extended_top_down_v2(symbol)\n",
"\n",
"if signal_result:\n",
" print(f\"\\n🎯 SIGNAL SUMMARY:\")\n",
" print(f\"Entry Signal: {signal_result['entry_signal']}\")\n",
" print(f\"Confidence: {signal_result['confidence']}%\")\n",
" print(f\"Adaptive Threshold: {signal_result['adaptive_threshold']}%\")\n",
" print(f\"Signal Quality: {signal_result['signal_quality'].upper()}\")\n",
" print(f\"Market Regime: {signal_result['market_regime']['regime'].upper()}\")\n",
" print(f\"Risk-Adjusted Strength: {signal_result['risk_adjusted_strength']:.1f}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5. Optimierte Trade-Ausführung"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Konfiguration für optimierten Trading Bot\n",
"OPTIMIZED_CONFIG = {\n",
" 'symbol': symbol,\n",
" 'atr_mult': 1.5,\n",
" 'base_confidence': 70, # Wird automatisch angepasst\n",
" 'max_risk_per_trade': 0.01,\n",
" 'risk_filter': True,\n",
" 'min_atr': 0.0010,\n",
" 'use_pullback_entry': True,\n",
" 'debug': True\n",
"}\n",
"\n",
"print(\"⚙️ Optimized Trading Configuration:\")\n",
"for key, value in OPTIMIZED_CONFIG.items():\n",
" print(f\" {key}: {value}\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Test der optimierten Trade-Funktion\n",
"def test_optimized_trading():\n",
" \"\"\"\n",
" Testet die optimierte Trading-Logik\n",
" \"\"\"\n",
" print(\"🚀 Testing Optimized Trade Execution...\\n\")\n",
" \n",
" try:\n",
" result = execute_trade_v2(**OPTIMIZED_CONFIG)\n",
" \n",
" if result:\n",
" print(\"✅ Trade executed successfully!\")\n",
" return result\n",
" else:\n",
" print(\"⏸️ No trade executed (conditions not met)\")\n",
" return None\n",
" \n",
" except Exception as e:\n",
" print(f\"❌ Error in trade execution: {e}\")\n",
" return None\n",
"\n",
"# Führe Test aus\n",
"test_result = test_optimized_trading()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 6. Performance Monitoring"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Aktuelle Performance analysieren\n",
"print(\"📊 Analyzing Recent Performance...\\n\")\n",
"analyze_performance(symbol, days_back=7) # Letzte 7 Tage"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 7. Automatisierung mit optimierter Logik"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Wrapper-Funktion für Scheduler\n",
"def optimized_trading_job():\n",
" \"\"\"\n",
" Hauptfunktion für automatisierten Trading mit optimierter Logik\n",
" \"\"\"\n",
" try:\n",
" print(f\"\\n⏰ {pd.Timestamp.now().strftime('%Y-%m-%d %H:%M:%S')} - Running Optimized Trading Check\")\n",
" \n",
" # Führe optimierte Trade-Analyse aus\n",
" result = execute_trade_v2(**OPTIMIZED_CONFIG)\n",
" \n",
" if result:\n",
" print(\"✅ Trade executed with optimized logic!\")\n",
" else:\n",
" print(\"⏸️ No trade - waiting for better conditions\")\n",
" \n",
" # Performance-Update alle 6 Stunden\n",
" current_hour = pd.Timestamp.now().hour\n",
" if current_hour % 6 == 0: # 0, 6, 12, 18 Uhr\n",
" analyze_performance(symbol, days_back=1)\n",
" \n",
" except Exception as e:\n",
" print(f\"❌ Error in optimized trading job: {e}\")\n",
"\n",
"# Test der Job-Funktion\n",
"optimized_trading_job()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 8. Scheduler Setup mit optimierter Logik"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from apscheduler.schedulers.background import BackgroundScheduler\n",
"\n",
"# Scheduler für optimierten Trading Bot\n",
"optimized_scheduler = BackgroundScheduler()\n",
"\n",
"# Hinzufügen des optimierten Trading Jobs\n",
"# Läuft alle 5 Minuten während der Handelszeiten\n",
"optimized_scheduler.add_job(\n",
" optimized_trading_job, \n",
" 'cron', \n",
" year=\"*\", \n",
" month=\"*\", \n",
" day_of_week=\"mon,tue,wed,thu,fri\", \n",
" hour='0-23', \n",
" minute='*/5',\n",
" id='optimized_trading'\n",
")\n",
"\n",
"print(\"⚙️ Optimized Scheduler configured:\")\n",
"print(\" - Trading checks every 5 minutes\")\n",
" print(\" - Monday to Friday, 24 hours\")\n",
"print(\" - Enhanced signal logic active\")\n",
"print(\" - Performance monitoring included\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Scheduler starten\n",
"print(\"🚀 Starting Optimized Trading Bot...\")\n",
"optimized_scheduler.start()\n",
"print(\"✅ Optimized Trading Bot is now running!\")\n",
"print(\"\\n📋 Active Jobs:\")\n",
"for job in optimized_scheduler.get_jobs():\n",
" print(f\" - {job.id}: {job.next_run_time}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 9. Monitoring & Control"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Status Check\n",
"def check_optimized_bot_status():\n",
" \"\"\"\n",
" Überprüft den Status des optimierten Trading Bots\n",
" \"\"\"\n",
" print(\"🔍 Optimized Trading Bot Status:\")\n",
" print(f\" MT5 Connection: {'✅' if mt.terminal_info() else '❌'}\")\n",
" print(f\" Scheduler Running: {'✅' if optimized_scheduler.running else '❌'}\")\n",
" print(f\" Active Jobs: {len(optimized_scheduler.get_jobs())}\")\n",
" \n",
" # Aktuelle Signal-Info\n",
" try:\n",
" signal_info = extended_top_down_v2(symbol)\n",
" if signal_info:\n",
" print(f\" Current Signal: {signal_info['entry_signal']}\")\n",
" print(f\" Confidence: {signal_info['confidence']}%\")\n",
" print(f\" Market Regime: {signal_info['market_regime']['regime'].upper()}\")\n",
" print(f\" Signal Quality: {signal_info['signal_quality'].upper()}\")\n",
" except Exception as e:\n",
" print(f\" Signal Check: ❌ Error: {e}\")\n",
"\n",
"check_optimized_bot_status()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 10. Vergleich V1.3 vs V1.4"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def compare_versions():\n",
" \"\"\"\n",
" Vergleicht die alte und neue Signallogik\n",
" \"\"\"\n",
" print(\"📊 COMPARISON: V1.3 vs V1.4\")\n",
" print(\"=\" * 50)\n",
" \n",
" comparison_data = [\n",
" [\"Feature\", \"V1.3\", \"V1.4\"],\n",
" [\"Confidence Threshold\", \"Fixed 80%\", \"Adaptive 60-90%\"],\n",
" [\"Market Regime\", \"Not considered\", \"Active detection\"],\n",
" [\"Entry Timing\", \"Immediate\", \"Pullback optimization\"],\n",
" [\"Signal Strength\", \"Basic confidence\", \"Risk-adjusted strength\"],\n",
" [\"Performance Tracking\", \"Manual\", \"Automatic logging\"],\n",
" [\"Parameter Adaptation\", \"Static\", \"Dynamic (regime-based)\"],\n",
" [\"Risk Management\", \"Basic\", \"Enhanced (regime-aware)\"],\n",
" [\"Signal Quality\", \"Binary\", \"Graded (excellent/good/fair)\"],\n",
" [\"Trend Strength\", \"Not weighted\", \"Weighted by timeframe\"]\n",
" ]\n",
" \n",
" print(tabulate(comparison_data, headers=\"firstrow\", tablefmt=\"psql\"))\n",
" \n",
" print(\"\\n🎯 Key Improvements in V1.4:\")\n",
" improvements = [\n",
" \"🔄 Adapts to market conditions automatically\",\n",
" \"⏰ Better entry timing reduces risk\",\n",
" \"📊 Comprehensive performance tracking\",\n",
" \"🎚️ Dynamic parameter adjustment\",\n",
" \"🔍 Enhanced signal quality assessment\",\n",
" \"⚖️ Risk-adjusted position sizing\"\n",
" ]\n",
" \n",
" for improvement in improvements:\n",
" print(f\" {improvement}\")\n",
"\n",
"compare_versions()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 11. Control Panel"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Stoppe alle Jobs\n",
"optimized_scheduler.remove_all_jobs()\n",
"print(\"⏹️ All jobs removed\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Scheduler herunterfahren\n",
"optimized_scheduler.shutdown()\n",
"print(\"🔴 Optimized Trading Bot stopped\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 📝 Zusammenfassung der Optimierungen\n",
"\n",
"### ✅ **Implementierte Verbesserungen:**\n",
"\n",
"1. **🎯 Adaptive Confidence Threshold**\n",
" - Automatische Anpassung an Marktregime\n",
" - Trending: 60-75% | Ranging: 85% | Volatile: 90%\n",
"\n",
"2. **📊 Market Regime Detection**\n",
" - ADX-basierte Trendstärke-Analyse\n",
" - Bollinger Band Width für Ranging-Erkennung\n",
" - Volatility Cluster Detection\n",
"\n",
"3. **⏰ Entry Timing Optimization**\n",
" - Pullback zu EMA21 für bessere R/R\n",
" - Regime-abhängige Entry-Kriterien\n",
"\n",
"4. **💪 Risk-Adjusted Signal Strength**\n",
" - Kombiniert Confidence × Trend-Stärke × RRR\n",
" - Gewichtete Timeframe-Analyse\n",
"\n",
"5. **📈 Performance Monitoring**\n",
" - Automatisches Logging aller Trades\n",
" - Regime-basierte Performance-Analyse\n",
" - JSON-Export für weitere Analyse\n",
"\n",
"### 🎚️ **Nächste Schritte:**\n",
"1. Teste den Bot im Demo-Modus für 1-2 Wochen\n",
"2. Analysiere die Performance-Logs\n",
"3. Optimiere Parameter basierend auf Ergebnissen\n",
"4. Bei positiven Ergebnissen: Live-Trading aktivieren"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"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
}
-633
View File
@@ -1,633 +0,0 @@
"""
TradingBot V1.4 - Optimized Version
Verbesserte Entry Signal Logik basierend auf Analyse-Empfehlungen
Hauptverbesserungen:
1. Adaptive Confidence Threshold
2. Market Regime Detection
3. Entry Timing Optimization
4. Risk-Adjusted Signal Strength
5. Performance Monitoring
"""
import pandas as pd
import numpy as np
import MetaTrader5 as mt
import pandas_ta as ta
from scipy.signal import savgol_filter, find_peaks
from sklearn.linear_model import LinearRegression
from tabulate import tabulate
from datetime import datetime, timedelta
import json
# =============================================================================
# 1. MARKET REGIME DETECTION
# =============================================================================
def detect_market_regime(df, lookback=50):
"""
Erkennt das aktuelle Marktregime (Trending vs. Ranging)
Returns:
- regime: 'trending', 'ranging', 'volatile'
- strength: 0-100 (Stärke des Regimes)
"""
# ADX für Trendstärke
adx = ta.adx(df['high'], df['low'], df['close'], length=14)['ADX_14'].iloc[-1]
# Bollinger Band Squeeze für Ranging Markets
bb = ta.bbands(df['close'], length=20)
bb_width = ((bb['BBU_20_2.0'] - bb['BBL_20_2.0']) / bb['BBM_20_2.0'] * 100).iloc[-lookback:].mean()
# Price Action Analysis
price_range = (df['high'].iloc[-lookback:].max() - df['low'].iloc[-lookback:].min())
atr_avg = df['atr'].iloc[-lookback:].mean()
range_ratio = price_range / (atr_avg * lookback)
# Volatility Cluster Detection
vol_cluster = df['atr'].iloc[-10:].std() / df['atr'].iloc[-50:].mean()
# Regime-Bestimmung
if adx > 25 and range_ratio > 1.5:
regime = 'trending'
strength = min(100, adx * 2)
elif vol_cluster > 1.5:
regime = 'volatile'
strength = min(100, vol_cluster * 50)
else:
regime = 'ranging'
strength = max(0, 100 - adx * 2)
return {
'regime': regime,
'strength': strength,
'adx': adx,
'bb_width': bb_width,
'range_ratio': range_ratio,
'vol_cluster': vol_cluster
}
# =============================================================================
# 2. ADAPTIVE CONFIDENCE SYSTEM
# =============================================================================
def calculate_adaptive_confidence_threshold(regime_info, base_confidence=70):
"""
Berechnet adaptive Confidence-Schwelle basierend auf Marktregime
"""
regime = regime_info['regime']
strength = regime_info['strength']
adx = regime_info['adx']
if regime == 'trending':
# In Trending Markets: niedrigere Schwelle bei starken Trends
if adx > 30:
return max(60, base_confidence - 15)
else:
return base_confidence - 10
elif regime == 'ranging':
# In Ranging Markets: höhere Schwelle für mehr Selektivität
return base_confidence + 15
elif regime == 'volatile':
# In Volatile Markets: deutlich höhere Schwelle
return base_confidence + 20
return base_confidence
# =============================================================================
# 3. ENHANCED TREND ANALYSIS
# =============================================================================
def get_enhanced_trend(timeframe="H4", lookback=150, symbol="XAUUSD"):
"""
Verbesserte Trend-Analyse mit Regime-Awareness
"""
from your_existing_functions import get_rates # Import your existing function
# Timeframe mapping
tf_map = {"D1": "d1", "H4": "h4", "H1": "h1", "M30": "m30", "M15": "m15", "M5": "m5"}
tf = tf_map.get(timeframe, timeframe.lower())
try:
df = get_rates(tf, lookback)
if df is None or len(df) < 50:
return None
# Bestehende Trend-Logik
df['close_smooth'] = savgol_filter(df['close'], min(15, len(df)//10), 3)
df['atr'] = ta.atr(df['high'], df['low'], df['close'], length=14)
# Linear Regression
X = np.arange(len(df)).reshape(-1, 1)
y = df['close_smooth'].values
model = LinearRegression().fit(X, y)
slope = model.coef_[0]
# Market Regime Detection
regime_info = detect_market_regime(df.iloc[-50:])
# Adaptive Slope Threshold basierend auf Regime
base_threshold = df['atr'].iloc[-1] * 0.0001
if regime_info['regime'] == 'trending':
slope_threshold = base_threshold * 0.7 # Niedrigere Schwelle in Trends
elif regime_info['regime'] == 'ranging':
slope_threshold = base_threshold * 1.5 # Höhere Schwelle in Ranges
else: # volatile
slope_threshold = base_threshold * 1.2
# Trend bestimmen
if slope > slope_threshold:
trend = "uptrend"
elif slope < -slope_threshold:
trend = "downtrend"
else:
trend = "sideways"
# Enhanced Trend Strength
trend_strength = abs(slope) / slope_threshold if slope_threshold > 0 else 0
return {
"trend": trend,
"slope": slope,
"slope_threshold": slope_threshold,
"trend_strength": trend_strength,
"atr": df['atr'].iloc[-1],
"price": df['close'].iloc[-1],
"regime_info": regime_info
}
except Exception as e:
print(f"Error in get_enhanced_trend: {e}")
return None
# =============================================================================
# 4. OPTIMIZED TOP-DOWN ANALYSIS
# =============================================================================
def extended_top_down_v2(symbol="XAUUSD", lookback=150):
"""
Optimierte Top-Down-Analyse mit adaptiven Parametern
"""
timeframes = ["D1", "H4", "H1", "M30", "M15", "M5"]
trend_info = {}
# 1. Alle Timeframes analysieren
for tf in timeframes:
trend_info[tf] = get_enhanced_trend(tf, lookback, symbol)
if trend_info[tf] is None:
print(f"⚠️ Keine Daten für {tf}")
return None
# 2. Market Regime aus H4 bestimmen (repräsentativ)
main_regime = trend_info["H4"]["regime_info"]
# 3. Adaptive Confidence Threshold
adaptive_confidence_threshold = calculate_adaptive_confidence_threshold(main_regime)
# 4. Enhanced Standard-Trend (D1 + H4 mit Gewichtung)
d1_trend = trend_info["D1"]["trend"]
h4_trend = trend_info["H4"]["trend"]
d1_strength = trend_info["D1"]["trend_strength"]
h4_strength = trend_info["H4"]["trend_strength"]
# Gewichteter Standard-Trend
if d1_trend == h4_trend and d1_trend != "sideways":
standard_trend = d1_trend
standard_strength = (d1_strength * 0.6 + h4_strength * 0.4)
elif d1_strength > h4_strength * 1.5: # D1 deutlich stärker
standard_trend = d1_trend
standard_strength = d1_strength * 0.8
elif h4_strength > d1_strength * 1.5: # H4 deutlich stärker
standard_trend = h4_trend
standard_strength = h4_strength * 0.8
else:
standard_trend = "sideways"
standard_strength = 0
# 5. Enhanced Fast-Trend mit Regime-Awareness
fast_timeframes = ["H1", "M30", "M15", "M5"]
fast_trends = [trend_info[tf]["trend"] for tf in fast_timeframes]
fast_strengths = [trend_info[tf]["trend_strength"] for tf in fast_timeframes]
# Regime-abhängige Fast-Trend Logik
if main_regime['regime'] == 'trending':
# In Trends: 2 von 4 TFs reichen
required_alignment = 2
else:
# In Ranging/Volatile: 3 von 4 TFs erforderlich
required_alignment = 3
trend_counts = {'uptrend': 0, 'downtrend': 0, 'sideways': 0}
weighted_strengths = {'uptrend': 0, 'downtrend': 0}
weights = [1.0, 0.8, 0.6, 0.4] # H1, M30, M15, M5
for i, (trend, strength) in enumerate(zip(fast_trends, fast_strengths)):
trend_counts[trend] += 1
if trend != 'sideways':
weighted_strengths[trend] += strength * weights[i]
# Fast-Trend bestimmen
max_count = max(trend_counts['uptrend'], trend_counts['downtrend'])
if max_count >= required_alignment:
if trend_counts['uptrend'] > trend_counts['downtrend']:
fast_trend = "uptrend"
elif trend_counts['downtrend'] > trend_counts['uptrend']:
fast_trend = "downtrend"
else:
# Bei Gleichstand: Stärke entscheidet
if weighted_strengths['uptrend'] > weighted_strengths['downtrend']:
fast_trend = "uptrend"
else:
fast_trend = "downtrend"
else:
fast_trend = "sideways"
# 6. Top-Down-Trend Bestimmung
if standard_trend == fast_trend and standard_trend != "sideways":
top_down_trend = standard_trend
combined_strength = (standard_strength + weighted_strengths[fast_trend]) / 2
else:
top_down_trend = "sideways"
combined_strength = 0
# 7. Enhanced Confidence Calculation
weights = {"D1": 2.5, "H4": 2.0, "H1": 1.5, "M30": 1.0, "M15": 0.8, "M5": 0.6}
weighted_matching = sum(
weights[tf] * trend_info[tf]["trend_strength"]
for tf in timeframes
if trend_info[tf]["trend"] == top_down_trend and trend_info[tf]["trend"] != "sideways"
)
weighted_total = sum(
weights[tf] * trend_info[tf]["trend_strength"]
for tf in timeframes
if trend_info[tf]["trend"] != "sideways"
)
confidence = round((weighted_matching / weighted_total) * 100, 2) if weighted_total > 0 else 0.0
# 8. Risk-Adjusted Signal Strength
atr = trend_info["M5"]["atr"]
rrr = 2.5 # Risk-Reward Ratio
risk_adjusted_strength = confidence * combined_strength * min(2.0, rrr)
# 9. Entry Signal mit adaptiven Kriterien
entry_signal = 0
signal_quality = "none"
if (top_down_trend != "sideways" and
confidence >= adaptive_confidence_threshold and
risk_adjusted_strength >= 100):
entry_signal = 1 if top_down_trend == "uptrend" else -1
# Signal Quality Assessment
if confidence >= 85 and risk_adjusted_strength >= 150:
signal_quality = "excellent"
elif confidence >= 75 and risk_adjusted_strength >= 120:
signal_quality = "good"
else:
signal_quality = "fair"
# 10. Enhanced Debug Output
debug_data = []
for tf in timeframes:
info = trend_info[tf]
debug_data.append([
tf,
info["trend"],
f"{info['trend_strength']:.2f}",
f"{info['atr']:.4f}",
f"{info['slope']:.6f}",
f"{info['price']:.2f}"
])
print(f"\n📊 Enhanced Trend-Analyse für {symbol}")
print(f"🎯 Market Regime: {main_regime['regime'].upper()} (Strength: {main_regime['strength']:.0f}%)")
print(f"🎚️ Adaptive Confidence Threshold: {adaptive_confidence_threshold}%")
print()
print(tabulate(debug_data, headers=["TF", "Trend", "Strength", "ATR", "Slope", "Price"], tablefmt="psql"))
print(f"\n➡️ Standard-Trend: {standard_trend} (Strength: {standard_strength:.2f})")
print(f"➡️ Fast-Trend: {fast_trend}")
print(f"➡️ Top-Down-Trend: {top_down_trend}")
print(f"➡️ Confidence: {confidence}% (Threshold: {adaptive_confidence_threshold}%)")
print(f"➡️ Risk-Adjusted Strength: {risk_adjusted_strength:.1f}")
print(f"➡️ Signal Quality: {signal_quality.upper()}")
return {
"symbol": symbol,
"trend_info": trend_info,
"market_regime": main_regime,
"standard_trend": standard_trend,
"fast_trend": fast_trend,
"top_down_trend": top_down_trend,
"confidence": confidence,
"adaptive_threshold": adaptive_confidence_threshold,
"risk_adjusted_strength": risk_adjusted_strength,
"entry_signal": entry_signal,
"signal_quality": signal_quality,
"combined_strength": combined_strength
}
# =============================================================================
# 5. ENTRY TIMING OPTIMIZATION
# =============================================================================
def check_pullback_entry(symbol, signal_info, timeframe="M5"):
"""
Prüft optimale Entry-Timing durch Pullback-Analyse
"""
if signal_info["entry_signal"] == 0:
return False, "No base signal"
try:
from your_existing_functions import get_rates # Import your existing function
df = get_rates(timeframe.lower(), 50)
if df is None or len(df) < 20:
return False, "Insufficient data"
# EMAs für Pullback-Erkennung
df['ema21'] = df['close'].ewm(span=21).mean()
df['ema50'] = df['close'].ewm(span=50).mean()
current_price = df['close'].iloc[-1]
ema21 = df['ema21'].iloc[-1]
ema50 = df['ema50'].iloc[-1]
signal_direction = signal_info["entry_signal"]
if signal_direction == 1: # Long Signal
# Pullback zu EMA21 oder Support
if current_price <= ema21 * 1.002 and ema21 > ema50:
return True, "Pullback to EMA21 for Long"
elif current_price <= ema21 * 0.998:
return True, "Below EMA21 - Good Long Entry"
elif signal_direction == -1: # Short Signal
# Pullback zu EMA21 oder Resistance
if current_price >= ema21 * 0.998 and ema21 < ema50:
return True, "Pullback to EMA21 for Short"
elif current_price >= ema21 * 1.002:
return True, "Above EMA21 - Good Short Entry"
return False, "Waiting for better entry timing"
except Exception as e:
print(f"Error in pullback check: {e}")
return True, "Using immediate entry (fallback)"
# =============================================================================
# 6. ENHANCED EXECUTE TRADE FUNCTION
# =============================================================================
def execute_trade_v2(
symbol="XAUUSD",
atr_mult=1.5,
base_confidence=70,
max_risk_per_trade=0.01,
risk_filter=True,
min_atr=0.0010,
use_pullback_entry=True,
debug=True
):
"""
Optimierte Trade-Ausführung mit allen Verbesserungen
"""
# 1. Enhanced Signal Analysis
signal_info = extended_top_down_v2(symbol)
if signal_info is None:
print("❌ Signal-Analyse fehlgeschlagen")
return None
entry_signal = signal_info["entry_signal"]
confidence = signal_info["confidence"]
adaptive_threshold = signal_info["adaptive_threshold"]
signal_quality = signal_info["signal_quality"]
market_regime = signal_info["market_regime"]
# 2. Get Price/ATR from M5
m5_info = signal_info["trend_info"]["M5"]
price = m5_info["price"]
atr = m5_info["atr"]
# 3. Enhanced Pre-checks
reason = ""
if confidence < adaptive_threshold:
reason = f"Confidence {confidence}% < adaptive threshold {adaptive_threshold}%"
elif entry_signal == 0:
reason = f"No entry signal (Trend: {signal_info['top_down_trend']}, Regime: {market_regime['regime']})"
elif price is None or atr is None:
reason = "Price/ATR not available"
elif risk_filter and atr < min_atr:
reason = f"ATR {atr:.5f} < min_atr {min_atr}"
elif signal_quality == "none":
reason = "Signal quality insufficient"
else:
# 4. Entry Timing Check
if use_pullback_entry:
pullback_ok, pullback_reason = check_pullback_entry(symbol, signal_info)
if not pullback_ok:
reason = f"Entry timing: {pullback_reason}"
if not reason:
# 5. Enhanced Risk Checks
from your_existing_functions import check_risk_limits # Import your existing function
risk_ok = check_risk_limits(symbol, max_risk_per_trade=max_risk_per_trade)
if not risk_ok:
reason = "Risk limits exceeded"
# 6. Execute Trade if all checks pass
if not reason:
# Enhanced SL/TP calculation based on regime
regime_mult = 1.0
if market_regime['regime'] == 'volatile':
regime_mult = 1.3 # Wider stops in volatile markets
elif market_regime['regime'] == 'ranging':
regime_mult = 0.8 # Tighter stops in ranging markets
adjusted_atr_mult = atr_mult * regime_mult
if entry_signal == 1: # Long
stop_loss = price - adjusted_atr_mult * atr
take_profit = price + adjusted_atr_mult * atr * 2.5 # Better RRR
else: # Short
stop_loss = price + adjusted_atr_mult * atr
take_profit = price - adjusted_atr_mult * atr * 2.5
# Dynamic Position Sizing
stop_distance = adjusted_atr_mult * atr
risk_amount = max_risk_per_trade * 10000 # Assuming account balance
volume = min(0.1, risk_amount / (stop_distance * 100000)) # Simplified calculation
# Log Enhanced Trade Info
print(f"\n🚀 ENHANCED TRADE EXECUTION")
print(f"Symbol: {symbol}")
print(f"Direction: {'LONG' if entry_signal == 1 else 'SHORT'}")
print(f"Price: {price:.5f}")
print(f"Volume: {volume:.2f}")
print(f"Stop Loss: {stop_loss:.5f}")
print(f"Take Profit: {take_profit:.5f}")
print(f"Confidence: {confidence}% (Threshold: {adaptive_threshold}%)")
print(f"Signal Quality: {signal_quality.upper()}")
print(f"Market Regime: {market_regime['regime'].upper()}")
print(f"ATR Multiplier: {adjusted_atr_mult:.2f} (Base: {atr_mult})")
print(f"Risk per Trade: {max_risk_per_trade*100:.1f}%")
# Execute the actual trade
try:
from your_existing_functions import market_order # Import your existing function
order_result = market_order(
symbol=symbol,
volume=volume,
order_type="buy" if entry_signal == 1 else "sell",
stoploss=stop_loss,
take_profit=take_profit
)
# Log Trade to Performance Monitor
log_trade_performance(signal_info, order_result)
return order_result
except Exception as e:
print(f"❌ Trade execution failed: {e}")
return None
else:
if debug:
print(f"\n⏸️ TRADE SKIPPED: {reason}")
print(f"Confidence: {confidence}% | Threshold: {adaptive_threshold}%")
print(f"Signal Quality: {signal_quality} | Regime: {market_regime['regime']}")
return None
# =============================================================================
# 7. PERFORMANCE MONITORING
# =============================================================================
def log_trade_performance(signal_info, order_result):
"""
Loggt Trade-Performance für Analyse und Optimierung
"""
trade_data = {
'timestamp': datetime.now().isoformat(),
'symbol': signal_info['symbol'],
'entry_signal': signal_info['entry_signal'],
'confidence': signal_info['confidence'],
'adaptive_threshold': signal_info['adaptive_threshold'],
'signal_quality': signal_info['signal_quality'],
'market_regime': signal_info['market_regime']['regime'],
'regime_strength': signal_info['market_regime']['strength'],
'risk_adjusted_strength': signal_info['risk_adjusted_strength'],
'order_result': str(order_result) if order_result else None
}
# Save to JSON file for analysis
try:
filename = f"trade_performance_{signal_info['symbol']}_{datetime.now().strftime('%Y%m')}.json"
try:
with open(filename, 'r') as f:
data = json.load(f)
except FileNotFoundError:
data = []
data.append(trade_data)
with open(filename, 'w') as f:
json.dump(data, f, indent=2)
except Exception as e:
print(f"Warning: Could not log performance data: {e}")
def analyze_performance(symbol="XAUUSD", days_back=30):
"""
Analysiert Performance der letzten Trades
"""
try:
filename = f"trade_performance_{symbol}_{datetime.now().strftime('%Y%m')}.json"
with open(filename, 'r') as f:
data = json.load(f)
# Filter last X days
cutoff = datetime.now() - timedelta(days=days_back)
recent_trades = [
trade for trade in data
if datetime.fromisoformat(trade['timestamp']) > cutoff
]
if not recent_trades:
print(f"No trades found in last {days_back} days")
return
# Analysis
total_trades = len(recent_trades)
by_regime = {}
by_confidence = {'high': 0, 'medium': 0, 'low': 0}
by_quality = {}
for trade in recent_trades:
# By regime
regime = trade['market_regime']
by_regime[regime] = by_regime.get(regime, 0) + 1
# By confidence
conf = trade['confidence']
if conf >= 85:
by_confidence['high'] += 1
elif conf >= 75:
by_confidence['medium'] += 1
else:
by_confidence['low'] += 1
# By quality
quality = trade['signal_quality']
by_quality[quality] = by_quality.get(quality, 0) + 1
print(f"\n📊 PERFORMANCE ANALYSIS - Last {days_back} days")
print(f"Total Trades: {total_trades}")
print(f"\nBy Market Regime:")
for regime, count in by_regime.items():
print(f" {regime.upper()}: {count} ({count/total_trades*100:.1f}%)")
print(f"\nBy Confidence Level:")
for level, count in by_confidence.items():
print(f" {level.upper()}: {count} ({count/total_trades*100:.1f}%)")
print(f"\nBy Signal Quality:")
for quality, count in by_quality.items():
print(f" {quality.upper()}: {count} ({count/total_trades*100:.1f}%)")
except Exception as e:
print(f"Could not analyze performance: {e}")
# =============================================================================
# 8. QUICK SETUP FUNCTION
# =============================================================================
def setup_optimized_trading():
"""
Quick setup für optimiertes Trading
"""
print("🚀 Setting up Optimized Trading Bot V1.4")
print("\nKey Improvements:")
print("✅ Adaptive confidence thresholds")
print("✅ Market regime detection")
print("✅ Enhanced entry timing")
print("✅ Risk-adjusted signal strength")
print("✅ Performance monitoring")
print("\nReady to trade with enhanced logic!")
if __name__ == "__main__":
setup_optimized_trading()
File diff suppressed because it is too large. Load diff
-394
View File
@@ -1,394 +0,0 @@
"""
TradingBot V1.4 - Relaxed Version
Weniger restriktive Parameter für mehr Trading-Signale
Hauptänderungen:
- Niedrigere Confidence-Schwellen
- Weniger strenge Signal-Quality-Filter
- Relaxed Risk-Adjusted Strength
"""
# Import der Fixed Version als Basis
from TradingBot_V1.4_Fixed import *
def calculate_adaptive_confidence_threshold_relaxed(regime_info, base_confidence=60):
"""
Relaxed Version: Niedrigere Schwellen für mehr Signale
"""
regime = regime_info['regime']
strength = regime_info['strength']
adx = regime_info['adx']
if regime == 'trending':
# In Trending Markets: noch niedrigere Schwelle
if adx > 30:
return max(50, base_confidence - 20) # War -15
else:
return base_confidence - 15 # War -10
elif regime == 'ranging':
# In Ranging Markets: weniger streng
return base_confidence + 10 # War +15
elif regime == 'volatile':
# In Volatile Markets: weniger restriktiv
return base_confidence + 15 # War +20
return base_confidence
def extended_top_down_v2_relaxed(symbol="XAUUSD", lookback=150):
"""
Relaxed Version der Top-Down-Analyse für mehr Trading-Signale
"""
timeframes = ["D1", "H4", "H1", "M30", "M15", "M5"]
trend_info = {}
print(f"🔍 Analyzing {symbol} with RELAXED parameters...")
# 1. Alle Timeframes analysieren
for tf in timeframes:
trend_info[tf] = get_enhanced_trend(tf, lookback, symbol)
if trend_info[tf] is None:
print(f"⚠️ Keine Daten für {tf}")
return None
# 2. Market Regime aus H4 bestimmen
main_regime = trend_info["H4"]["regime_info"]
# 3. RELAXED Adaptive Confidence Threshold
adaptive_confidence_threshold = calculate_adaptive_confidence_threshold_relaxed(main_regime)
# 4. Standard-Trend (gleich wie vorher)
d1_trend = trend_info["D1"]["trend"]
h4_trend = trend_info["H4"]["trend"]
d1_strength = trend_info["D1"]["trend_strength"]
h4_strength = trend_info["H4"]["trend_strength"]
if d1_trend == h4_trend and d1_trend != "sideways":
standard_trend = d1_trend
standard_strength = (d1_strength * 0.6 + h4_strength * 0.4)
elif d1_strength > h4_strength * 1.5:
standard_trend = d1_trend
standard_strength = d1_strength * 0.8
elif h4_strength > d1_strength * 1.5:
standard_trend = h4_trend
standard_strength = h4_strength * 0.8
else:
standard_trend = "sideways"
standard_strength = 0
# 5. RELAXED Fast-Trend (weniger TFs erforderlich)
fast_timeframes = ["H1", "M30", "M15", "M5"]
fast_trends = [trend_info[tf]["trend"] for tf in fast_timeframes]
fast_strengths = [trend_info[tf]["trend_strength"] for tf in fast_timeframes]
# RELAXED: Immer nur 2 von 4 TFs erforderlich (statt regime-abhängig)
required_alignment = 2
trend_counts = {'uptrend': 0, 'downtrend': 0, 'sideways': 0}
weighted_strengths = {'uptrend': 0, 'downtrend': 0}
weights = [1.0, 0.8, 0.6, 0.4]
for i, (trend, strength) in enumerate(zip(fast_trends, fast_strengths)):
trend_counts[trend] += 1
if trend != 'sideways':
weighted_strengths[trend] += strength * weights[i]
max_count = max(trend_counts['uptrend'], trend_counts['downtrend'])
if max_count >= required_alignment:
if trend_counts['uptrend'] > trend_counts['downtrend']:
fast_trend = "uptrend"
elif trend_counts['downtrend'] > trend_counts['uptrend']:
fast_trend = "downtrend"
else:
if weighted_strengths['uptrend'] > weighted_strengths['downtrend']:
fast_trend = "uptrend"
else:
fast_trend = "downtrend"
else:
fast_trend = "sideways"
# 6. Top-Down-Trend Bestimmung
if standard_trend == fast_trend and standard_trend != "sideways":
top_down_trend = standard_trend
combined_strength = (standard_strength + weighted_strengths.get(fast_trend, 0)) / 2
else:
top_down_trend = "sideways"
combined_strength = 0
# 7. Enhanced Confidence Calculation (gleich)
weights = {"D1": 2.5, "H4": 2.0, "H1": 1.5, "M30": 1.0, "M15": 0.8, "M5": 0.6}
weighted_matching = sum(
weights[tf] * trend_info[tf]["trend_strength"]
for tf in timeframes
if trend_info[tf]["trend"] == top_down_trend and trend_info[tf]["trend"] != "sideways"
)
weighted_total = sum(
weights[tf] * trend_info[tf]["trend_strength"]
for tf in timeframes
if trend_info[tf]["trend"] != "sideways"
)
confidence = round((weighted_matching / weighted_total) * 100, 2) if weighted_total > 0 else 0.0
# 8. RELAXED Risk-Adjusted Signal Strength
atr = trend_info["M5"]["atr"]
rrr = 2.5
risk_adjusted_strength = confidence * combined_strength * min(2.0, rrr)
# 9. RELAXED Entry Signal (niedrigere Schwelle)
entry_signal = 0
signal_quality = "none"
# RELAXED: Niedrigere Schwelle für risk_adjusted_strength
min_strength = 80 # War 100
if (top_down_trend != "sideways" and
confidence >= adaptive_confidence_threshold and
risk_adjusted_strength >= min_strength):
entry_signal = 1 if top_down_trend == "uptrend" else -1
# RELAXED Signal Quality (niedrigere Schwellen)
if confidence >= 80 and risk_adjusted_strength >= 130: # War 85/150
signal_quality = "excellent"
elif confidence >= 70 and risk_adjusted_strength >= 100: # War 75/120
signal_quality = "good"
else:
signal_quality = "fair"
# 10. Debug Output
debug_data = []
for tf in timeframes:
info = trend_info[tf]
debug_data.append([
tf,
info["trend"],
f"{info['trend_strength']:.2f}",
f"{info['atr']:.4f}",
f"{info['slope']:.6f}",
f"{info['price']:.2f}"
])
print(f"\n📊 RELAXED Trend-Analyse für {symbol}")
print(f"🎯 Market Regime: {main_regime['regime'].upper()} (Strength: {main_regime['strength']:.0f}%)")
print(f"🎚️ RELAXED Adaptive Threshold: {adaptive_confidence_threshold}% (vs standard V1.4)")
print()
print(tabulate(debug_data, headers=["TF", "Trend", "Strength", "ATR", "Slope", "Price"], tablefmt="psql"))
print(f"\n➡️ Standard-Trend: {standard_trend} (Strength: {standard_strength:.2f})")
print(f"➡️ Fast-Trend: {fast_trend}")
print(f"➡️ Top-Down-Trend: {top_down_trend}")
print(f"➡️ Confidence: {confidence}% (RELAXED Threshold: {adaptive_confidence_threshold}%)")
print(f"➡️ Risk-Adjusted Strength: {risk_adjusted_strength:.1f} (Min: {min_strength})")
print(f"➡️ Signal Quality: {signal_quality.upper()}")
# Vergleich mit Standard V1.4
standard_threshold = calculate_adaptive_confidence_threshold(main_regime)
print(f"\n🔄 RELAXED vs STANDARD V1.4:")
print(f" Standard V1.4 threshold: {standard_threshold}%")
print(f" Relaxed V1.4 threshold: {adaptive_confidence_threshold}%")
print(f" Difference: {adaptive_confidence_threshold - standard_threshold:+d}% (more lenient)")
return {
"symbol": symbol,
"trend_info": trend_info,
"market_regime": main_regime,
"standard_trend": standard_trend,
"fast_trend": fast_trend,
"top_down_trend": top_down_trend,
"confidence": confidence,
"adaptive_threshold": adaptive_confidence_threshold,
"risk_adjusted_strength": risk_adjusted_strength,
"entry_signal": entry_signal,
"signal_quality": signal_quality,
"combined_strength": combined_strength,
"min_strength_used": min_strength
}
def execute_trade_v2_relaxed(
symbol="XAUUSD",
atr_mult=1.5,
base_confidence=60, # Niedriger als 70
max_risk_per_trade=0.01,
risk_filter=True,
min_atr=0.0008, # Niedriger als 0.0010
use_pullback_entry=False, # DISABLED für mehr Signale
debug=True
):
"""
RELAXED Trade-Ausführung mit weniger restriktiven Parametern
"""
# 1. RELAXED Signal Analysis
signal_info = extended_top_down_v2_relaxed(symbol)
if signal_info is None:
print("❌ Signal-Analyse fehlgeschlagen")
return None
entry_signal = signal_info["entry_signal"]
confidence = signal_info["confidence"]
adaptive_threshold = signal_info["adaptive_threshold"]
signal_quality = signal_info["signal_quality"]
market_regime = signal_info["market_regime"]
# 2. Get Price/ATR from M5
m5_info = signal_info["trend_info"]["M5"]
price = m5_info["price"]
atr = m5_info["atr"]
# 3. RELAXED Pre-checks
reason = ""
if confidence < adaptive_threshold:
reason = f"Confidence {confidence}% < relaxed threshold {adaptive_threshold}%"
elif entry_signal == 0:
reason = f"No entry signal (Trend: {signal_info['top_down_trend']}, Regime: {market_regime['regime']})"
elif price is None or atr is None:
reason = "Price/ATR not available"
elif risk_filter and atr < min_atr:
reason = f"ATR {atr:.5f} < min_atr {min_atr}"
else:
# 4. SKIP Entry Timing Check (use_pullback_entry=False)
# 5. RELAXED Risk Checks
risk_ok = check_risk_limits(symbol, max_risk_per_trade=max_risk_per_trade)
if not risk_ok:
reason = "Risk limits exceeded"
# 6. Execute Trade if all checks pass
if not reason:
# Standard SL/TP calculation
regime_mult = 1.0
if market_regime['regime'] == 'volatile':
regime_mult = 1.2 # Weniger drastisch als 1.3
elif market_regime['regime'] == 'ranging':
regime_mult = 0.9 # Weniger drastisch als 0.8
adjusted_atr_mult = atr_mult * regime_mult
if entry_signal == 1: # Long
stop_loss = price - adjusted_atr_mult * atr
take_profit = price + adjusted_atr_mult * atr * 2.5
else: # Short
stop_loss = price + adjusted_atr_mult * atr
take_profit = price - adjusted_atr_mult * atr * 2.5
# Position Sizing
account_info = mt.account_info()
if account_info:
balance = account_info.balance
risk_amount = balance * max_risk_per_trade
if symbol == "XAUUSD":
volume = min(0.1, max(0.01, risk_amount / (adjusted_atr_mult * atr * 100)))
else:
volume = 0.01
else:
volume = 0.01
# Log Enhanced Trade Info
print(f"\n🚀 RELAXED TRADE EXECUTION")
print(f"Symbol: {symbol}")
print(f"Direction: {'LONG' if entry_signal == 1 else 'SHORT'}")
print(f"Price: {price:.5f}")
print(f"Volume: {volume:.2f}")
print(f"Stop Loss: {stop_loss:.5f}")
print(f"Take Profit: {take_profit:.5f}")
print(f"Confidence: {confidence}% (RELAXED Threshold: {adaptive_threshold}%)")
print(f"Signal Quality: {signal_quality.upper()}")
print(f"Market Regime: {market_regime['regime'].upper()}")
print(f"Pullback Entry: DISABLED (immediate entry)")
print(f"Risk per Trade: {max_risk_per_trade*100:.1f}%")
# Execute trade
try:
order_result = market_order(
symbol=symbol,
volume=volume,
order_type="buy" if entry_signal == 1 else "sell",
stoploss=stop_loss,
take_profit=take_profit
)
log_trade_performance(signal_info, order_result)
return order_result
except Exception as e:
print(f"❌ Trade execution failed: {e}")
return None
else:
if debug:
print(f"\n⏸️ RELAXED TRADE SKIPPED: {reason}")
print(f"Confidence: {confidence}% | Relaxed Threshold: {adaptive_threshold}%")
print(f"Signal Quality: {signal_quality} | Regime: {market_regime['regime']}")
return None
def compare_all_versions(symbol="XAUUSD"):
"""
Vergleicht alle Versionen: V1.3, V1.4 Standard, V1.4 Relaxed
"""
print("🔄 COMPARING ALL VERSIONS")
print("=" * 40)
try:
# V1.4 Standard
signal_std = extended_top_down_v2(symbol, lookback=100)
# V1.4 Relaxed
signal_rel = extended_top_down_v2_relaxed(symbol, lookback=100)
if signal_std and signal_rel:
comparison_data = [
["Version", "Confidence", "Threshold", "Signal", "Quality", "Would Trade"],
["V1.3 (simulated)", f"{signal_std['confidence']:.1f}%", "80%",
"1" if signal_std['confidence'] >= 80 and signal_std['top_down_trend'] != 'sideways' else "0",
"N/A", "✅" if signal_std['confidence'] >= 80 and signal_std['top_down_trend'] != 'sideways' else "❌"],
["V1.4 Standard", f"{signal_std['confidence']:.1f}%", f"{signal_std['adaptive_threshold']}%",
str(signal_std['entry_signal']), signal_std['signal_quality'],
"✅" if signal_std['entry_signal'] != 0 else "❌"],
["V1.4 Relaxed", f"{signal_rel['confidence']:.1f}%", f"{signal_rel['adaptive_threshold']}%",
str(signal_rel['entry_signal']), signal_rel['signal_quality'],
"✅" if signal_rel['entry_signal'] != 0 else "❌"]
]
print(tabulate(comparison_data, headers="firstrow", tablefmt="psql"))
# Empfehlung
trading_count = sum([
1 if signal_std['confidence'] >= 80 and signal_std['top_down_trend'] != 'sideways' else 0,
1 if signal_std['entry_signal'] != 0 else 0,
1 if signal_rel['entry_signal'] != 0 else 0
])
print(f"\n📊 TRADING SIGNALS: {trading_count}/3 versions would trade")
if trading_count == 0:
print("🛑 NO VERSION would trade - market conditions not suitable")
elif trading_count == 1:
print("⚡ Only one version trades - high selectivity")
elif trading_count == 2:
print("🎯 Two versions agree - moderate confidence")
else:
print("🚀 All versions agree - strong signal!")
return signal_rel
except Exception as e:
print(f"Error in comparison: {e}")
return None
if __name__ == "__main__":
print("🚀 TradingBot V1.4 - RELAXED Version Ready!")
print("Less restrictive parameters for more trading signals")
print("\nKey changes:")
print("• Lower confidence thresholds")
print("• Disabled pullback entry timing")
print("• Lower risk-adjusted strength requirement")
print("• More lenient signal quality assessment")
print("\nUse: extended_top_down_v2_relaxed() for analysis")
print("Use: execute_trade_v2_relaxed() for trading")
File diff suppressed because it is too large. Load diff
-2060
View File
File diff suppressed because it is too large. Load diff
-498
View File
@@ -1,498 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 🚨 Trading Bot Fix - Warum handelt er nicht mehr?\n",
"\n",
"## Systematische Diagnose und Lösungen"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Imports\n",
"import pandas as pd\n",
"import numpy as np\n",
"import MetaTrader5 as mt\n",
"import pandas_ta as ta\n",
"from scipy.signal import savgol_filter\n",
"from sklearn.linear_model import LinearRegression\n",
"from tabulate import tabulate\n",
"from datetime import datetime\n",
"\n",
"# Deine bestehenden Funktionen\n",
"try:\n",
" from TradingBot_V1.4_Fixed import extended_top_down_v2, get_rates, detect_market_regime\n",
" print(\"✅ V1.4 functions imported successfully\")\n",
"except ImportError as e:\n",
" print(f\"❌ Import error: {e}\")\n",
" print(\"Continuing with basic diagnosis...\")\n",
"\n",
"symbol = \"XAUUSD\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. 🔍 Grundlegende Diagnose"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(\"🔍 TRADING BOT DIAGNOSIS\")\n",
"print(\"=\" * 50)\n",
"\n",
"issues_found = []\n",
"\n",
"# MT5 Connection Check\n",
"print(\"\\n1️⃣ MT5 Connection Check:\")\n",
"terminal_info = mt.terminal_info()\n",
"if terminal_info:\n",
" print(\" ✅ MT5 connected\")\n",
" print(f\" Company: {terminal_info.company}\")\n",
" print(f\" Connected: {terminal_info.connected}\")\n",
" print(f\" Trade allowed: {terminal_info.trade_allowed}\")\n",
" if not terminal_info.trade_allowed:\n",
" issues_found.append(\"Trading not allowed in terminal\")\n",
"else:\n",
" print(\" ❌ MT5 not connected\")\n",
" issues_found.append(\"MT5 connection failed\")\n",
"\n",
"# Account Info Check\n",
"print(\"\\n2️⃣ Account Info Check:\")\n",
"account_info = mt.account_info()\n",
"if account_info:\n",
" print(f\" ✅ Account: {account_info.login}\")\n",
" print(f\" Balance: {account_info.balance}\")\n",
" print(f\" Equity: {account_info.equity}\")\n",
" print(f\" Trade allowed: {account_info.trade_allowed}\")\n",
" if not account_info.trade_allowed:\n",
" issues_found.append(\"Trading not allowed on account\")\n",
"else:\n",
" print(\" ❌ Cannot get account info\")\n",
" issues_found.append(\"Account info unavailable\")\n",
"\n",
"# Symbol Info Check\n",
"print(f\"\\n3️⃣ Symbol Info Check ({symbol}):\")\n",
"symbol_info = mt.symbol_info(symbol)\n",
"if symbol_info:\n",
" print(f\" ✅ Symbol exists: {symbol_info.name}\")\n",
" print(f\" Trade mode: {symbol_info.trade_mode}\")\n",
" print(f\" Min volume: {symbol_info.volume_min}\")\n",
" if symbol_info.trade_mode == 0:\n",
" issues_found.append(f\"Trading disabled for {symbol}\")\n",
"else:\n",
" print(f\" ❌ Symbol {symbol} not found\")\n",
" issues_found.append(f\"Symbol {symbol} not available\")\n",
"\n",
"# Current Price Check\n",
"print(\"\\n4️⃣ Price Data Check:\")\n",
"tick = mt.symbol_info_tick(symbol)\n",
"if tick:\n",
" print(f\" ✅ Current price: Bid={tick.bid}, Ask={tick.ask}\")\n",
" spread = tick.ask - tick.bid\n",
" print(f\" Spread: {spread:.5f}\")\n",
" if spread > 0.01:\n",
" issues_found.append(f\"High spread: {spread:.5f}\")\n",
"else:\n",
" print(\" ❌ No current price data\")\n",
" issues_found.append(\"No price data available\")\n",
"\n",
"print(f\"\\n📋 Issues Found: {len(issues_found)}\")\n",
"for i, issue in enumerate(issues_found, 1):\n",
" print(f\" {i}. {issue}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. 📊 Signal-Analyse: Warum kein Trade?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Teste deine optimierte V1.4 Logik\n",
"print(\"🔍 SIGNAL ANALYSIS - Why no trading?\")\n",
"print(\"=\" * 50)\n",
"\n",
"try:\n",
" # Hole Signal-Info\n",
" signal_info = extended_top_down_v2(symbol, lookback=100)\n",
" \n",
" if signal_info:\n",
" print(f\"\\n📊 CURRENT SIGNAL STATUS:\")\n",
" print(f\"Entry Signal: {signal_info['entry_signal']}\")\n",
" print(f\"Confidence: {signal_info['confidence']:.1f}%\")\n",
" print(f\"Adaptive Threshold: {signal_info['adaptive_threshold']:.1f}%\")\n",
" print(f\"Signal Quality: {signal_info['signal_quality'].upper()}\")\n",
" print(f\"Market Regime: {signal_info['market_regime']['regime'].upper()}\")\n",
" print(f\"Top-Down Trend: {signal_info['top_down_trend'].upper()}\")\n",
" print(f\"Risk-Adjusted Strength: {signal_info['risk_adjusted_strength']:.1f}\")\n",
" \n",
" # Analyse warum kein Signal\n",
" print(f\"\\n🔍 WHY NO TRADING SIGNAL:\")\n",
" \n",
" reasons = []\n",
" \n",
" if signal_info['top_down_trend'] == 'sideways':\n",
" reasons.append(\"❌ No clear trend direction (sideways market)\")\n",
" \n",
" if signal_info['confidence'] < signal_info['adaptive_threshold']:\n",
" deficit = signal_info['adaptive_threshold'] - signal_info['confidence']\n",
" reasons.append(f\"❌ Confidence too low: {signal_info['confidence']:.1f}% < {signal_info['adaptive_threshold']:.1f}% (need {deficit:.1f}% more)\")\n",
" \n",
" if signal_info['risk_adjusted_strength'] < 100:\n",
" reasons.append(f\"❌ Risk-adjusted strength too low: {signal_info['risk_adjusted_strength']:.1f} < 100\")\n",
" \n",
" if signal_info['signal_quality'] == 'none':\n",
" reasons.append(\"❌ Signal quality insufficient\")\n",
" \n",
" if reasons:\n",
" for reason in reasons:\n",
" print(f\" {reason}\")\n",
" else:\n",
" print(\" ✅ All signal criteria met - check other filters\")\n",
" \n",
" # Vergleich mit V1.3\n",
" print(f\"\\n🔄 V1.3 vs V1.4 COMPARISON:\")\n",
" v13_threshold = 80\n",
" v13_would_trade = (\n",
" signal_info['top_down_trend'] != 'sideways' and \n",
" signal_info['confidence'] >= v13_threshold\n",
" )\n",
" v14_trades = signal_info['entry_signal'] != 0\n",
" \n",
" print(f\" V1.3 would trade: {'✅' if v13_would_trade else '❌'} (fixed 80% threshold)\")\n",
" print(f\" V1.4 trades: {'✅' if v14_trades else '❌'} (adaptive {signal_info['adaptive_threshold']:.1f}% threshold)\")\n",
" \n",
" if v13_would_trade and not v14_trades:\n",
" print(f\" 🛡️ V1.4 is MORE SELECTIVE in {signal_info['market_regime']['regime'].upper()} market\")\n",
" elif not v13_would_trade and v14_trades:\n",
" print(f\" 🚀 V1.4 found opportunity V1.3 missed!\")\n",
" \n",
" else:\n",
" print(\"❌ Could not get signal info\")\n",
" \n",
"except Exception as e:\n",
" print(f\"❌ Error in signal analysis: {e}\")\n",
" print(\"Will try simplified analysis...\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. 🔧 Quick Fixes"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(\"🔧 QUICK FIXES TO TRY\")\n",
"print(\"=\" * 30)\n",
"\n",
"# Fix 1: Temporär niedrigere Schwelle\n",
"print(\"\\n1️⃣ LOWER THRESHOLD TEMPORARILY:\")\n",
"print(\" Copy this code to make V1.4 less selective:\")\n",
"print(\"\")\n",
"quick_fix_1 = '''def quick_fix_lower_threshold(signal_info):\n",
" # Reduziere adaptive Schwelle um 15%\n",
" original_threshold = signal_info['adaptive_threshold']\n",
" new_threshold = max(60, original_threshold - 15)\n",
" \n",
" print(f\"Original threshold: {original_threshold}%\")\n",
" print(f\"New threshold: {new_threshold}%\")\n",
" \n",
" if signal_info['confidence'] >= new_threshold:\n",
" print(\"✅ Would trade with lower threshold!\")\n",
" return True\n",
" else:\n",
" print(f\"❌ Still need {new_threshold - signal_info['confidence']:.1f}% more confidence\")\n",
" return False'''\n",
"\n",
"print(quick_fix_1)\n",
"\n",
"# Fix 2: Bypass Pullback Entry\n",
"print(\"\\n\\n2️⃣ BYPASS PULLBACK ENTRY:\")\n",
"print(\" Set: use_pullback_entry = False\")\n",
"print(\" This allows immediate entries instead of waiting for pullbacks\")\n",
"\n",
"# Fix 3: Allow Fair Quality\n",
"print(\"\\n3️⃣ ALLOW 'FAIR' SIGNAL QUALITY:\")\n",
"print(\" Modify signal quality check to accept 'fair' signals\")\n",
"\n",
"# Fix 4: Emergency V1.3 Mode\n",
"print(\"\\n4️⃣ EMERGENCY V1.3 MODE:\")\n",
"print(\" Use simplified logic similar to your original bot\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 4. 🚨 Emergency V1.3-Style Trading"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def emergency_trading_signal(symbol=\"XAUUSD\"):\n",
" \"\"\"\n",
" Vereinfachte V1.3-ähnliche Logik als Fallback\n",
" \"\"\"\n",
" print(\"🚨 EMERGENCY V1.3-STYLE TRADING\")\n",
" print(\"=\" * 40)\n",
" \n",
" try:\n",
" # Einfache get_rates Funktion\n",
" def simple_get_rates(tf, count):\n",
" tf_map = {\"h4\": mt.TIMEFRAME_H4, \"m5\": mt.TIMEFRAME_M5}\n",
" rates = mt.copy_rates_from_pos(symbol, tf_map[tf], 0, count)\n",
" if rates is None:\n",
" return None\n",
" df = pd.DataFrame(rates)\n",
" df['atr'] = ta.atr(df['high'], df['low'], df['close'], length=14)\n",
" return df\n",
" \n",
" # Hole H4 und M5 Daten\n",
" h4_df = simple_get_rates(\"h4\", 150)\n",
" m5_df = simple_get_rates(\"m5\", 100)\n",
" \n",
" if h4_df is None or m5_df is None:\n",
" return 0, \"No data available\"\n",
" \n",
" print(f\"Got H4 data: {len(h4_df)} bars\")\n",
" print(f\"Got M5 data: {len(m5_df)} bars\")\n",
" \n",
" # Vereinfachte Trend-Analyse H4\n",
" h4_df['close_smooth'] = savgol_filter(h4_df['close'], 15, 3)\n",
" X = np.arange(len(h4_df)).reshape(-1, 1)\n",
" y = h4_df['close_smooth'].values\n",
" model = LinearRegression().fit(X, y)\n",
" slope_h4 = model.coef_[0]\n",
" \n",
" atr_h4 = h4_df['atr'].iloc[-1]\n",
" threshold_h4 = atr_h4 * 0.0001\n",
" \n",
" if slope_h4 > threshold_h4:\n",
" h4_trend = \"uptrend\"\n",
" elif slope_h4 < -threshold_h4:\n",
" h4_trend = \"downtrend\"\n",
" else:\n",
" h4_trend = \"sideways\"\n",
" \n",
" print(f\"H4 Trend: {h4_trend} (slope: {slope_h4:.6f})\")\n",
" \n",
" # Vereinfachte Trend-Analyse M5\n",
" m5_df['close_smooth'] = savgol_filter(m5_df['close'], 15, 3)\n",
" X_m5 = np.arange(len(m5_df)).reshape(-1, 1)\n",
" y_m5 = m5_df['close_smooth'].values\n",
" model_m5 = LinearRegression().fit(X_m5, y_m5)\n",
" slope_m5 = model_m5.coef_[0]\n",
" \n",
" atr_m5 = m5_df['atr'].iloc[-1]\n",
" threshold_m5 = atr_m5 * 0.0001\n",
" \n",
" if slope_m5 > threshold_m5:\n",
" m5_trend = \"uptrend\"\n",
" elif slope_m5 < -threshold_m5:\n",
" m5_trend = \"downtrend\"\n",
" else:\n",
" m5_trend = \"sideways\"\n",
" \n",
" print(f\"M5 Trend: {m5_trend} (slope: {slope_m5:.6f})\")\n",
" \n",
" # Vereinfachte Confidence\n",
" if h4_trend == m5_trend and h4_trend != \"sideways\":\n",
" confidence = 85 # Hoch wenn aligned\n",
" signal = 1 if h4_trend == \"uptrend\" else -1\n",
" trend_agreement = \"✅ ALIGNED\"\n",
" else:\n",
" confidence = 45 # Niedrig wenn nicht aligned\n",
" signal = 0\n",
" trend_agreement = \"❌ NOT ALIGNED\"\n",
" \n",
" print(f\"Trend Agreement: {trend_agreement}\")\n",
" print(f\"Confidence: {confidence}%\")\n",
" \n",
" # V1.3-ähnliche niedrige Schwelle\n",
" emergency_threshold = 70\n",
" \n",
" print(f\"Emergency Threshold: {emergency_threshold}%\")\n",
" \n",
" if confidence >= emergency_threshold and signal != 0:\n",
" direction = \"LONG\" if signal == 1 else \"SHORT\"\n",
" return signal, f\"🚀 EMERGENCY {direction} SIGNAL! Confidence: {confidence}%\"\n",
" else:\n",
" return 0, f\"❌ No emergency signal: confidence {confidence}% < {emergency_threshold}%\"\n",
" \n",
" except Exception as e:\n",
" return 0, f\"Error in emergency analysis: {e}\"\n",
"\n",
"# Test Emergency Signal\n",
"emergency_signal, emergency_reason = emergency_trading_signal(symbol)\n",
"print(f\"\\n🎯 EMERGENCY RESULT:\")\n",
"print(f\"Signal: {emergency_signal}\")\n",
"print(f\"Reason: {emergency_reason}\")\n",
"\n",
"if emergency_signal != 0:\n",
" print(\"\\n🚀 EMERGENCY SIGNAL DETECTED!\")\n",
" print(\"You could use this as a fallback trading signal.\")\n",
"else:\n",
" print(\"\\n⏸️ Even emergency logic shows no signal\")\n",
" print(\"Market conditions may genuinely not be suitable for trading.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5. 🔄 Test mit deiner ursprünglichen V1.3 Funktion"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(\"🔄 TESTING YOUR ORIGINAL V1.3 LOGIC\")\n",
"print(\"=\" * 40)\n",
"\n",
"# Hier würdest du deine ursprüngliche extended_top_down() Funktion aus V1.3 aufrufen\n",
"print(\"To test your original logic, run:\")\n",
"print(\"\")\n",
"print(\"# Copy your original extended_top_down() function here\")\n",
"print(\"# Then run:\")\n",
"print(\"original_result = extended_top_down(symbol)\")\n",
"print(\"print(f'Original V1.3 result: {original_result}')\")\n",
"print(\"\")\n",
"print(\"This will show you if your V1.3 logic would still trade.\")\n",
"print(\"If V1.3 trades but V1.4 doesn't, we know V1.4 is too restrictive.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 6. 🎯 Immediate Solutions"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(\"🎯 IMMEDIATE SOLUTIONS TO GET TRADING AGAIN\")\n",
"print(\"=\" * 50)\n",
"\n",
"solutions = [\n",
" \"1️⃣ QUICK FIX - Lower Adaptive Threshold:\",\n",
" \" In execute_trade_v2(), change:\",\n",
" \" adaptive_threshold = signal_info['adaptive_threshold'] - 15\",\n",
" \"\",\n",
" \"2️⃣ DISABLE PULLBACK ENTRY:\",\n",
" \" Set: use_pullback_entry = False\",\n",
" \" This removes the timing filter\",\n",
" \"\",\n",
" \"3️⃣ ACCEPT FAIR SIGNALS:\",\n",
" \" Allow signal_quality = 'fair' to trade\",\n",
" \"\",\n",
" \"4️⃣ EMERGENCY MODE:\",\n",
" \" Use the emergency_trading_signal() function above\",\n",
" \" as your main trading logic temporarily\",\n",
" \"\",\n",
" \"5️⃣ HYBRID APPROACH:\",\n",
" \" If V1.4 says no trade, check emergency signal\",\n",
" \" If emergency signal exists, trade with smaller volume\",\n",
" \"\",\n",
" \"6️⃣ REVERT TO V1.3:\",\n",
" \" Temporarily go back to your original bot\",\n",
" \" while we fine-tune V1.4 parameters\"\n",
"]\n",
"\n",
"for solution in solutions:\n",
" print(solution)\n",
"\n",
"print(\"\\n\" + \"=\" * 50)\n",
"print(\"🚨 MOST LIKELY ISSUE: V1.4 is TOO SELECTIVE\")\n",
"print(\"V1.4 was designed to be more careful, which means fewer trades.\")\n",
"print(\"This is actually GOOD for avoiding bad trades, but may feel like 'not working'.\")\n",
"print(\"\")\n",
"print(\"💡 RECOMMENDATION:\")\n",
"print(\"1. Try the emergency signal above\")\n",
"print(\"2. If it works, gradually tune V1.4 to be less restrictive\")\n",
"print(\"3. Compare results over 1-2 weeks to see which performs better\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 7. 📊 Parameter Tuning"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Zeige aktuelle Parameter und Tuning-Optionen\n",
"print(\"📊 PARAMETER TUNING OPTIONS\")\n",
"print(\"=\" * 35)\n",
"\n",
"tuning_options = [\n",
" \"Current V1.4 Parameters (too restrictive?):\",\n",
" \"• Base confidence: 70%\",\n",
" \"• Trending adjustment: -10 to -15%\",\n",
" \"• Ranging adjustment: +15%\",\n",
" \"• Volatile adjustment: +20%\",\n",
" \"• Min risk-adjusted strength: 100\",\n",
" \"\",\n",
" \"Suggested Relaxed Parameters:\",\n",
" \"• Base confidence: 60%\",\n",
" \"• Trending adjustment: -15 to -20%\",\n",
" \"• Ranging adjustment: +10%\",\n",
" \"• Volatile adjustment: +15%\",\n",
" \"• Min risk-adjusted strength: 80\",\n",
" \"\",\n",
" \"Very Relaxed (V1.3-like):\",\n",
" \"• Fixed confidence: 75%\",\n",
" \"• No regime adjustments\",\n",
" \"• No signal quality filter\",\n",
" \"• No pullback entry timing\"\n",
"]\n",
"\n",
"for option in tuning_options:\n",
" print(option)"
]
}\n",
],\n",
"metadata": {\n",
"kernelspec": {\n",
\"display_name\": \"Python 3\",\n",
\"language\": \"python\",\n",
\"name\": \"python3\"\n },\n \"language_info\": {\n \"codemirror_mode\": {\n \"name\": \"ipython\",\n \"version\": 3\n },\n \"file_extension\": \".py\",\n \"mimetype\": \"text/x-python\",\n \"name\": \"python\",\n \"nbconvert_exporter\": \"python\",\n \"pygments_lexer\": \"ipython3\",\n \"version\": \"3.11.5\"\n }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+324
View File
@@ -0,0 +1,324 @@
# 🚀 TradingBot V1.8 - Aggressive Mode (Nur NY Session)
**Deployment Datum:** 26. November 2025
**Status:** ✅ Aktiv auf VPS
**Strategie:** Nur NY Session (13:00-21:00 UTC)
---
## 📊 Warum dieser Wechsel?
### Performance-Analyse nach 2 Wochen (V1.7):
| Session | Trades | Profit | Win-Rate | Entscheidung |
|---------|--------|--------|----------|--------------|
| **NY** | 21 | **+$660** | **47.6%** | ✅ **NUR DIESE aktiviert!** |
| Overlap | 44 | -$208 | 27.3% | ❌ Deaktiviert |
| Asian | 43 | +$202 | 30.2% | ❌ Deaktiviert |
| London | 26 | +$79 | 30.8% | ❌ Deaktiviert |
### 🎯 Key Findings:
1. **NY Session dominiert:**
- 90% des Gesamt-Profits ($660 von $733)
- 47.6% Win-Rate (beste Session!)
- $31.43 Profit pro Trade (höchste Effizienz)
2. **Overlap bleibt problematisch:**
- Kumuliert -$208 über 2 Wochen
- Win-Rate nur 27.3%
- Trotz Erholung in Woche 2 negativ
3. **Asian & London mittelmäßig:**
- Win-Rates ~30% (zu niedrig)
- Zwar positiv, aber nicht profitabel genug
- Fressen durch Verluste die Gewinne auf
---
## ⚙️ V1.8 Konfiguration
### Session Filter:
```python
'enabled_sessions': {
'asian': False, # ❌ DEAKTIVIERT
'london': False, # ❌ DEAKTIVIERT
'overlap': False, # ❌ DEAKTIVIERT
'ny': True, # ✅ NUR NY AKTIV (13:00-21:00 UTC)
}
```
### Trading Parameter (unverändert):
```python
'base_confidence': 60, # Confidence Threshold
'atr_mult': 1.5, # ATR Multiplikator
'max_risk_per_trade': 0.01, # 1% Risk pro Trade
'min_atr': 0.0008, # Minimum ATR
'risk_filter': True, # ATR Risk Filter aktiv
'use_pullback_entry': False # Kein Pullback Entry
```
---
## 📈 Erwartete Performance (V1.8)
### Basierend auf 2-Wochen-Daten:
| Metrik | V1.7 (2 Wochen) | V1.8 Erwartung | Verbesserung |
|--------|-----------------|----------------|--------------|
| **Trades** | 134 | ~21 pro Woche | -84% (sehr selektiv!) |
| **Win-Rate** | 32.09% | **~48%** | +15.91% ✅ |
| **Net Profit** | $733 | ~$660 | -10% ⚠️ |
| **Profit/Trade** | $5.47 | **$31.43** | +475% ✅✅ |
| **Max Drawdown** | 81% | **<50%** (erwartet) | -31% ✅ |
| **Profit Factor** | 1.162 | **>1.5** (erwartet) | +29% ✅ |
### 🎯 Trade-off Analyse:
**✅ Vorteile:**
- **Höchste Win-Rate** (~48% statt 32%)
- **Beste Profit-Effizienz** ($31/Trade statt $5/Trade)
- **Minimaler Drawdown** (weniger Trades = weniger Risiko)
- **Höchste Qualität** (nur beste Trading-Session)
- **Weniger Stress** (nur 8h pro Tag aktiv)
**⚠️ Nachteile:**
- **Weniger Trades** (~21 statt 134 pro 2 Wochen)
- **Weniger Profit-Chancen** (verpasst Asian/London/Overlap)
- **Absoluter Profit evtl. niedriger** (aber pro Trade VIEL höher!)
---
## 🕐 Trading Zeiten (V1.8)
### NY Session:
- **Start:** 13:00 UTC (14:00 MEZ / 15:00 MESZ)
- **Ende:** 21:00 UTC (22:00 MEZ / 23:00 MESZ)
- **Dauer:** 8 Stunden
- **Adaptive Intervalle:** 5/15/30 Minuten (basierend auf Volatilität)
### Blockierte Zeiten:
- **Asian (00:00-08:00 UTC):** ❌ Keine Trades
- **London (08:00-16:00 UTC):** ❌ Keine Trades (außer NY Overlap)
- **Overlap (13:00-16:00 UTC):** ❌ Keine Trades (in V1.8 deaktiviert)
**Log-Ausgabe bei blockierten Sessions:**
```
⏸️ Trading SKIP: Session blocked: Asian has +$202, but only 30.2% win-rate
⏸️ Trading SKIP: Session blocked: London has +$79, but only 30.8% win-rate
⏸️ Trading SKIP: Session blocked: Overlap has -$208 cumulative, 27.3% win-rate
```
**Log-Ausgabe bei NY Session:**
```
✅ Session: NY - NY allowed: +$660 profit, 47.6% win-rate (BEST!)
📊 Confidence Threshold: 60%
⏱️ Intervall: 15 min
```
---
## 📋 Monitoring Checklist (nächste 1-2 Wochen)
### Täglich prüfen:
- [ ] Bot läuft auf VPS (keine Crashes)
- [ ] Nur NY Session Trades im Log
- [ ] Keine Asian/London/Overlap Trades
- [ ] Confidence Threshold bei 60%
- [ ] Log zeigt: `⏸️ Trading SKIP` für andere Sessions
### Nach 1 Woche (ca. 3. Dezember):
```bash
python analyze_mt5_profitability.py
```
**Prüfe:**
1. **Win-Rate:** Sollte >40% sein (idealerweise 45-50%)
2. **Profit Factor:** Sollte >1.4 sein
3. **Max Drawdown:** Sollte <60% sein
4. **NY Trades:** Sollte ~10-12 Trades sein
5. **Andere Sessions:** Sollten 0 neue Trades sein
### Nach 2 Wochen (ca. 10. Dezember):
**Entscheidung:**
#### Szenario A: Win-Rate >45%
```
✅ V1.8 ist ein ERFOLG!
→ Behalte Aggressive Mode
→ Optional: Confidence auf 70% erhöhen für noch höhere Qualität
```
#### Szenario B: Win-Rate 40-45%
```
✅ V1.8 funktioniert gut
→ Behalte Aggressive Mode
→ Monitor weitere 2 Wochen
```
#### Szenario C: Win-Rate 35-40%
```
⚠️ Schlechter als erwartet
→ Teste Option C: NY + Overlap + Confidence 75%
```
#### Szenario D: Win-Rate <35%
```
❌ Aggressive Mode funktioniert nicht
→ Zurück zu V1.7 (NY + Overlap)
→ ODER: NY + Asian + London (alle positiven Sessions)
```
---
## 🔧 Schnell-Anpassungen (falls nötig)
### Alle Sessions wieder aktivieren:
```python
# In session_filter_patch.py
'enabled_sessions': {
'asian': True,
'london': True,
'overlap': True,
'ny': True,
}
```
### Nur NY + Overlap (zurück zu V1.7):
```python
'enabled_sessions': {
'asian': False,
'london': False,
'overlap': True, # ✅
'ny': True,
}
```
### NY + alle positiven Sessions:
```python
'enabled_sessions': {
'asian': True, # ✅ +$202
'london': True, # ✅ +$79
'overlap': False, # ❌ -$208
'ny': True, # ✅ +$660
}
```
### Confidence erhöhen (falls Win-Rate gut):
```python
'base_confidence': 70, # von 60 auf 70
# ODER
'base_confidence': 75, # für ultra-konservativ
```
---
## 📊 Performance-Vergleich
### V1.6 (Original - ALLE Sessions):
- Trades: 134 (2 Wochen)
- Win-Rate: 32.09%
- Net Profit: $733
- Profit/Trade: $5.47
- Max Drawdown: 81%
### V1.7 (NY + Overlap):
- Trades: 65 (2 Wochen, aktive Sessions)
- Win-Rate: 32.09%
- Net Profit: $733
- Profit/Trade: $11.28
- Max Drawdown: 81%
### V1.8 (Nur NY - JETZT):
- Trades: ~21 (2 Wochen, erwartet)
- Win-Rate: **~48%** (erwartet)
- Net Profit: ~$660
- Profit/Trade: **$31.43**
- Max Drawdown: **<50%** (erwartet)
---
## 🎯 Erfolgs-Kriterien für V1.8
### Must-Have (Minimum):
- ✅ Win-Rate >40%
- ✅ Profit Factor >1.3
- ✅ Max Drawdown <60%
- ✅ Profit/Trade >$25
### Nice-to-Have (Ziel):
- 🎯 Win-Rate >45%
- 🎯 Profit Factor >1.5
- 🎯 Max Drawdown <50%
- 🎯 Profit/Trade >$30
### Excellent (Best Case):
- 🏆 Win-Rate >48%
- 🏆 Profit Factor >1.7
- 🏆 Max Drawdown <40%
- 🏆 Profit/Trade >$35
---
## 🔄 Nächste Phasen (Roadmap)
### Phase 2A (nach V1.8 Validierung):
**Falls V1.8 erfolgreich (Win-Rate >45%):**
- Confidence Threshold auf 70-75% erhöhen
- Erwartung: Win-Rate >50%, weniger Trades, höchste Qualität
### Phase 2B (Infrastructure):
- SQLite Migration für besseres Datenmanagement
- Telegram Notifications für Mobile Monitoring
- Automatische Performance-Reports
### Phase 3 (Advanced):
- Backtesting Framework für historische Analyse
- ML Signal Filter (Random Forest / XGBoost)
- Multi-Symbol Support (XAUUSD + andere Paare)
---
## 📚 Dokumentation
- **Diese Datei:** V1.8 Aggressive Mode Dokumentation
- [V1.7_SESSION_FILTER_AKTIVIERT.md](V1.7_SESSION_FILTER_AKTIVIERT.md) - Vorherige Version
- [CONFIDENCE_THRESHOLD_GUIDE.md](CONFIDENCE_THRESHOLD_GUIDE.md) - Threshold Anleitung
- [SESSION_FILTER_INSTALLATION.md](SESSION_FILTER_INSTALLATION.md) - Installation Guide
- [session_filter_patch.py](session_filter_patch.py) - Config Datei
---
## ✅ Deployment Checklist
- [x] Config angepasst (nur NY Session)
- [x] File auf VPS kopiert
- [x] Bot neu gestartet
- [x] Log prüfen: Nur NY Trades
- [ ] Nach 1 Woche: Performance analysieren
- [ ] Nach 2 Wochen: Entscheidung für nächste Phase
---
## 🎲 Zusammenfassung
**TradingBot V1.8** ist jetzt im **Ultra-Selektiven Modus**:
- Nur die **beste Trading-Session** (NY)
- Höchste **Win-Rate** (~48%)
- Beste **Profit-Effizienz** ($31/Trade)
- Minimales **Risiko** (weniger Drawdown)
**Trade-off:**
Weniger Trades = weniger absolute Profit-Chancen, ABER: Jeder Trade hat deutlich höhere Erfolgswahrscheinlichkeit!
**Philosophie:**
"Qualität über Quantität" - Lieber 10 gute Trades als 100 mittelmäßige!
---
**Viel Erfolg mit V1.8! 🚀**
Melde dich in 1-2 Wochen mit den Performance-Daten!
-75
View File
@@ -1,75 +0,0 @@
{
"trading_config": {
"symbol": "XAUUSD",
"base_confidence": 70,
"atr_multiplier": 1.5,
"max_risk_per_trade": 0.01,
"min_atr": 0.0010,
"use_pullback_entry": true,
"strategy_name": "TradingBot_V1.4_Optimized"
},
"regime_thresholds": {
"trending": {
"min_adx": 25,
"confidence_adjustment": -10,
"atr_mult_adjustment": 0.0
},
"ranging": {
"max_adx": 20,
"confidence_adjustment": 15,
"atr_mult_adjustment": -0.2
},
"volatile": {
"vol_cluster_threshold": 1.5,
"confidence_adjustment": 20,
"atr_mult_adjustment": 0.3
}
},
"timeframe_weights": {
"D1": 2.5,
"H4": 2.0,
"H1": 1.5,
"M30": 1.0,
"M15": 0.8,
"M5": 0.6
},
"signal_quality_thresholds": {
"excellent": {
"min_confidence": 85,
"min_risk_adjusted_strength": 150
},
"good": {
"min_confidence": 75,
"min_risk_adjusted_strength": 120
},
"fair": {
"min_confidence": 60,
"min_risk_adjusted_strength": 100
}
},
"risk_management": {
"max_daily_loss": 0.05,
"max_drawdown": 0.10,
"max_positions": 3,
"spread_filter": true,
"max_spread": 3.0
},
"schedule_settings": {
"check_interval_minutes": 5,
"trading_days": ["mon", "tue", "wed", "thu", "fri"],
"trading_hours": "0-23",
"performance_analysis_hours": [0, 6, 12, 18]
},
"debug_settings": {
"verbose_logging": true,
"save_performance_logs": true,
"print_regime_info": true,
"log_skipped_trades": true
}
}
-542
View File
@@ -1,542 +0,0 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 28,
"id": "02ce9da2",
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"import keyring as kr\n",
"import MetaTrader5 as mt\n",
"import requests\n",
"import re\n",
"from time import sleep\n",
"from time import strftime\n",
"import datetime as dt\n",
"import sqlite3 as db\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "ffcf5c1a",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 2,
"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": 3,
"id": "d94de78e",
"metadata": {},
"outputs": [],
"source": [
"symbols = ['BTCUSD', 'ETHUSD', \n",
" 'XRPUSD', 'XAUUSD', 'EURUSD', 'EURNZD']"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "f225d16e",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"SymbolInfo(custom=False, chart_mode=0, select=True, visible=True, session_deals=0, session_buy_orders=0, session_sell_orders=0, volume=0, volumehigh=0, volumelow=0, time=1747583136, digits=2, spread=1603, spread_float=True, ticks_bookdepth=0, trade_calc_mode=5, trade_mode=4, start_time=0, expiration_time=0, trade_stops_level=0, trade_freeze_level=0, trade_exemode=2, swap_mode=5, swap_rollover3days=5, margin_hedged_use_leg=False, expiration_mode=15, filling_mode=2, order_mode=63, order_gtc_mode=0, option_mode=0, option_right=0, bid=103854.84, bidhigh=104085.24, bidlow=102892.04, ask=103870.87, askhigh=104101.27, asklow=102908.07, last=0.0, lasthigh=0.0, lastlow=0.0, volume_real=0.0, volumehigh_real=0.0, volumelow_real=0.0, option_strike=0.0, point=0.01, trade_tick_value=0.01, trade_tick_value_profit=0.01, trade_tick_value_loss=0.01, trade_tick_size=0.01, trade_contract_size=1.0, trade_accrued_interest=0.0, trade_face_value=0.0, trade_liquidity_rate=0.0, volume_min=0.01, volume_max=100.0, volume_step=0.01, volume_limit=0.0, swap_long=-19.0, swap_short=10.0, margin_initial=0.0, margin_maintenance=0.0, session_volume=0.0, session_turnover=0.0, session_interest=0.0, session_buy_orders_volume=0.0, session_sell_orders_volume=0.0, session_open=103363.54, session_close=103363.54, session_aw=0.0, session_price_settlement=0.0, session_price_limit_min=0.0, session_price_limit_max=0.0, margin_hedged=0.0, price_change=0.4753, price_volatility=0.0, price_theoretical=0.0, price_greeks_delta=0.0, price_greeks_theta=0.0, price_greeks_gamma=0.0, price_greeks_vega=0.0, price_greeks_rho=0.0, price_greeks_omega=0.0, price_sensitivity=0.0, basis='', category='', currency_base='BTC', currency_profit='USD', currency_margin='BTC', bank='', description='Bitcoin', exchange='', formula='', isin='', name='BTCUSD', page='', path='Crypto Currency\\\\Crypto Major\\\\BTCUSD')"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"mt.symbol_info('BTCUSD')"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "329ff8fe",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"datetime.datetime(2025, 5, 18, 21, 59, 2, 465512)"
]
},
"execution_count": 65,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"current_date_and_time = dt.datetime.now()\n",
"format = '%Y-%m-%d %H:%M:%S'\n",
"current_date_and_time.strftime(format)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5f56252c",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 150,
"id": "3ce21edb",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'XAUUSD': 0.97, 'EURUSD': 0.87, 'EURNZD': 0.47, 'ETHUSD': -0.0, 'BTCUSD': -1.65, 'XRPUSD': -3.22}\n"
]
},
{
"data": {
"text/plain": [
"{'BTCUSD': -1.65,\n",
" 'ETHUSD': -0.0,\n",
" 'XRPUSD': -3.22,\n",
" 'XAUUSD': 0.97,\n",
" 'EURUSD': 0.87,\n",
" 'EURNZD': 0.47}"
]
},
"execution_count": 150,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pricemovement = {}\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",
"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",
"pricemovement"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b30f529c",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 68,
"id": "f174bc75",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0\n"
]
}
],
"source": [
"con = db.connect(\"trading.db\")\n",
"print(con.total_changes)\n"
]
},
{
"cell_type": "code",
"execution_count": 69,
"id": "f2ff9f72",
"metadata": {},
"outputs": [],
"source": [
"cursor = con.cursor()"
]
},
{
"cell_type": "code",
"execution_count": 70,
"id": "0b4facf6",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<sqlite3.Cursor at 0x268bf0321c0>"
]
},
"execution_count": 70,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cursor.execute(\"Create Table If Not Exists pricemovment (date TEXT,symbol TEXT, movement INTEGER)\")"
]
},
{
"cell_type": "code",
"execution_count": 151,
"id": "107514d6",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"BTCUSD -1.65\n",
"ETHUSD -0.0\n",
"XRPUSD -3.22\n",
"XAUUSD 0.97\n",
"EURUSD 0.87\n",
"EURNZD 0.47\n"
]
}
],
"source": [
"for key, value in pricemovement.items():\n",
" print(key, value)\n",
" current_date_and_time = dt.datetime.now()\n",
" format = '%Y-%m-%d %H:%M:%S'\n",
" current_date_and_time.strftime(format)\n",
" cursor.execute(\"Insert into pricemovment values(?, ?, ?)\", (current_date_and_time, key, value))\n",
" con.commit()"
]
},
{
"cell_type": "code",
"execution_count": 152,
"id": "b99a7d5f",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"BTCUSD\n",
"[('2025-05-18 22:02:41.439814', 'BTCUSD', 0.13), ('2025-05-18 22:06:10.375867', 'BTCUSD', 0.2), ('2025-05-18 22:42:44.244148', 'BTCUSD', 0.65), ('2025-05-18 22:57:00.481991', 'BTCUSD', 0.65)]\n",
"ETHUSD\n",
"[('2025-05-18 22:02:41.441815', 'ETHUSD', -5.19), ('2025-05-18 22:06:10.379865', 'ETHUSD', -4.86), ('2025-05-18 22:42:44.249142', 'ETHUSD', -3.92), ('2025-05-18 22:57:00.485990', 'ETHUSD', -4.05)]\n",
"XRPUSD\n",
"[('2025-05-18 22:02:41.441815', 'XRPUSD', -0.63), ('2025-05-18 22:06:10.382865', 'XRPUSD', -0.37), ('2025-05-18 22:42:44.252143', 'XRPUSD', 0.45), ('2025-05-18 22:57:00.487996', 'XRPUSD', 0.45)]\n",
"XAUUSD\n",
"[('2025-05-18 22:02:41.441815', 'XAUUSD', -1.21), ('2025-05-18 22:06:10.384868', 'XAUUSD', -1.21), ('2025-05-18 22:42:44.255142', 'XAUUSD', -1.21), ('2025-05-18 22:57:00.491343', 'XAUUSD', -1.21)]\n",
"EURUSD\n",
"[('2025-05-18 22:02:41.441815', 'EURUSD', -0.2), ('2025-05-18 22:06:10.387868', 'EURUSD', -0.2), ('2025-05-18 22:42:44.258146', 'EURUSD', -0.2), ('2025-05-18 22:57:00.493342', 'EURUSD', -0.2)]\n",
"EURNZD\n",
"[('2025-05-18 22:02:41.441815', 'EURNZD', -0.29), ('2025-05-18 22:06:10.426110', 'EURNZD', -0.29), ('2025-05-18 22:42:44.262143', 'EURNZD', -0.29), ('2025-05-18 22:57:00.496339', 'EURNZD', -0.29)]\n"
]
}
],
"source": [
"for s in symbols:\n",
" print(s)\n",
" cursor.execute(f\"Select * from pricemovment where date like '2025-05-18%' and symbol = '{s}'\")\n",
" inhalt = cursor.fetchall()\n",
" print(inhalt)"
]
},
{
"cell_type": "code",
"execution_count": 155,
"id": "9b8fc8e9",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>date</th>\n",
" <th>symbol</th>\n",
" <th>percentage</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>2025-05-19 14:42:14.686479</td>\n",
" <td>BTCUSD</td>\n",
" <td>-1.72</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2025-05-19 14:42:14.735008</td>\n",
" <td>ETHUSD</td>\n",
" <td>-0.04</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>2025-05-19 14:42:14.738010</td>\n",
" <td>XRPUSD</td>\n",
" <td>-3.05</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>2025-05-19 14:42:14.741009</td>\n",
" <td>XAUUSD</td>\n",
" <td>1.30</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>2025-05-19 14:42:14.743007</td>\n",
" <td>EURUSD</td>\n",
" <td>0.92</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>2025-05-19 14:42:14.746007</td>\n",
" <td>EURNZD</td>\n",
" <td>0.43</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>2025-05-19 14:57:55.112334</td>\n",
" <td>BTCUSD</td>\n",
" <td>-1.65</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>2025-05-19 14:57:55.116333</td>\n",
" <td>ETHUSD</td>\n",
" <td>0.00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8</th>\n",
" <td>2025-05-19 14:57:55.124334</td>\n",
" <td>XRPUSD</td>\n",
" <td>-3.22</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9</th>\n",
" <td>2025-05-19 14:57:55.128902</td>\n",
" <td>XAUUSD</td>\n",
" <td>0.97</td>\n",
" </tr>\n",
" <tr>\n",
" <th>10</th>\n",
" <td>2025-05-19 14:57:55.186314</td>\n",
" <td>EURUSD</td>\n",
" <td>0.87</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11</th>\n",
" <td>2025-05-19 14:57:55.202850</td>\n",
" <td>EURNZD</td>\n",
" <td>0.47</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" date symbol percentage\n",
"0 2025-05-19 14:42:14.686479 BTCUSD -1.72\n",
"1 2025-05-19 14:42:14.735008 ETHUSD -0.04\n",
"2 2025-05-19 14:42:14.738010 XRPUSD -3.05\n",
"3 2025-05-19 14:42:14.741009 XAUUSD 1.30\n",
"4 2025-05-19 14:42:14.743007 EURUSD 0.92\n",
"5 2025-05-19 14:42:14.746007 EURNZD 0.43\n",
"6 2025-05-19 14:57:55.112334 BTCUSD -1.65\n",
"7 2025-05-19 14:57:55.116333 ETHUSD 0.00\n",
"8 2025-05-19 14:57:55.124334 XRPUSD -3.22\n",
"9 2025-05-19 14:57:55.128902 XAUUSD 0.97\n",
"10 2025-05-19 14:57:55.186314 EURUSD 0.87\n",
"11 2025-05-19 14:57:55.202850 EURNZD 0.47"
]
},
"execution_count": 155,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cursor.execute(\"Select * from pricemovment where date like '2025-05-19%'\")\n",
"inhalt = cursor.fetchall()\n",
"inhalt = pd.DataFrame(inhalt, columns=['date', 'symbol', 'percentage'])\n",
"\n",
"for s in symbols:\n",
" x = inhalt.loc[inhalt['symbol'] == s].percentage.diff()\n",
" pd.concat([inhalt, x])\n",
" \n",
"inhalt\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 187,
"id": "6f27e0ac",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[1.3, 0.97]"
]
},
"execution_count": 187,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"list = inhalt.loc[inhalt['symbol'] == 'XAUUSD'].percentage.to_list()\n",
"list\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "31180731",
"metadata": {},
"outputs": [],
"source": [
"cursor.execute(\"Insert into pricemovement values(?, ?, ?)\", ())"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e5425f12",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 59,
"id": "1422339e",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<sqlite3.Cursor at 0x268bee8ab40>"
]
},
"execution_count": 59,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cursor.execute('Drop Table pricemovment')"
]
},
{
"cell_type": "code",
"execution_count": 74,
"id": "3d94a299",
"metadata": {},
"outputs": [],
"source": [
"con.commit()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bf1487ac",
"metadata": {},
"outputs": [],
"source": [
"cursor.execute('INSERT INTO pricemovement VALUES(1, datetime('now'))'"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ce546c4d",
"metadata": {},
"outputs": [],
"source": [
"con.close()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "354653fc",
"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
}
-630
View File
@@ -1,630 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "6d202eb3",
"metadata": {},
"source": [
"# Import Libaries"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "5d0e0f92",
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"import pandas_ta as ta\n",
"import MetaTrader5 as mt\n",
"import keyring as kr"
]
},
{
"cell_type": "markdown",
"id": "de2abb26",
"metadata": {},
"source": [
"# Login"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "51d9b448",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 2,
"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": 3,
"id": "c92d8dee",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'trading-demo'"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"project = \"trading-\" + server[-4::1]\n",
"project = project.lower()\n",
"project"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "16e26255",
"metadata": {},
"outputs": [],
"source": [
"symbols = ['XAUUSD']"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "20de0d64",
"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": 6,
"id": "e65dfd75",
"metadata": {},
"outputs": [],
"source": [
"symbol = 'XAUUSD'"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "874862b3",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 107,
"id": "95f9b002",
"metadata": {},
"outputs": [],
"source": [
"def get_rates():\n",
"\n",
" ohlc = mt.copy_rates_from_pos(symbol, mt.TIMEFRAME_M5, 0, 200)\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": "markdown",
"id": "42dd19c7",
"metadata": {},
"source": [
"# Plotting Price Data"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "17a837df",
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline\n",
"\n",
"import matplotlib.pyplot as plt\n",
"from matplotlib.animation import FuncAnimation\n",
"from scipy.signal import savgol_filter\n",
"from scipy.signal import find_peaks\n",
"from IPython import display\n",
"from IPython.display import HTML\n",
"pd.set_option('mode.chained_assignment', None)"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "be326702",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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 truncated
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"#df2 = df.iloc[0:500]\n",
"df2 = df\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",
"\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "e27cba63",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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 truncated
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"#df2 = df.iloc[0:500]\n",
"df2 = df\n",
"\n",
"df2[\"close_smooth\"] = savgol_filter(df2.close, 49, 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",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "b00d9b70",
"metadata": {},
"source": [
"# Detecting Extrema"
]
},
{
"cell_type": "code",
"execution_count": 112,
"id": "2c1a99ec",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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 truncated
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"downtrend\n"
]
}
],
"source": [
"#df2 = df.iloc[0:500]\n",
"df2 = get_rates()\n",
"\n",
"df2[\"close_smooth\"] = savgol_filter(df2.close, 49, 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 = 15, \n",
" width = 3, prominence=atr)\n",
"\n",
"troughs_idx, _ = find_peaks(-1*df2.close_smooth, distance = 15, \n",
" width = 3, prominence=atr)\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",
"plt.show()\n",
"\n",
"#print(peaks_idx[-1], troughs_idx[-1])\n",
"\n",
"if peaks_idx[-1] > troughs_idx[-1]:\n",
" print(\"downtrend\")\n",
"else:\n",
" print(\"uptrend\")"
]
},
{
"cell_type": "markdown",
"id": "3865822f",
"metadata": {},
"source": [
"# Finding Runs"
]
},
{
"cell_type": "code",
"execution_count": 89,
"id": "5a190d91",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[21] [85] Line2D(_child2) Line2D(_child3)\n",
"1 0\n"
]
},
{
"data": {
"image/png": "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 truncated
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"df2 = df.iloc[0:100]\n",
"#df2 = df.tail(50)\n",
"\n",
"df2[\"close_smooth\"] = savgol_filter(df2.close, 49, 5)\n",
"\n",
"fig, ax = plt.subplots()\n",
"plt.xticks(rotation=-30)\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 = 15, \n",
" width = 3, prominence=atr)\n",
"\n",
"troughs_idx, _ = find_peaks(-1*df2.close_smooth, distance = 15, \n",
" width = 3, prominence=atr)\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",
"print(peaks_idx, troughs_idx, peaks, troughs)\n",
"\n",
"up_run_length = 0\n",
"up_run = True\n",
"down_run_length = 0\n",
"while up_run:\n",
" if 2 + up_run_length > len(peaks_idx) or 2 + up_run_length > len(troughs_idx):\n",
" break\n",
" if df2.close_smooth.iloc[peaks_idx[-1 - up_run_length]] > df2.close_smooth.iloc[peaks_idx[-2 - up_run_length]] and \\\n",
" df2.close_smooth.iloc[troughs_idx[-1 - up_run_length]] > df2.close_smooth.iloc[troughs_idx[-2 - up_run_length]]:\n",
" up_run_length += 1\n",
" else:\n",
" up_run = False \n",
"\n",
"# down_run_length = 0\n",
"# down_run = True\n",
"# while down_run:\n",
"# if 2 + down_run_length > len(peaks_idx) or 2 + down_run_length > len(troughs_idx):\n",
"# break\n",
" \n",
"# if df2.close_smooth.iloc[peaks_idx[-1 - down_run_length]] < df2.close_smooth.iloc[peaks_idx[-2 - down_run_length]] and \\\n",
"# df2.close_smooth.iloc[troughs_idx[-1 - down_run_length]] < + df2.close_smooth.iloc[troughs_idx[-2 - down_run_length]]:\n",
"# down_run_length += 1\n",
"# else:\n",
"# down_run = False\n",
" \n",
"\n",
"if up_run_length > 0:\n",
" ax.set_facecolor((150/255, 255/255, 159/255, 0.3))\n",
" pause_trading = 0\n",
"else:# down_run_length > 0:\n",
" ax.set_facecolor((255/255, 255/255, 80/255, 0.3))\n",
" pause_trading = 1\n",
" \n",
"print(pause_trading, up_run_length)\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 55,
"id": "6b7b9586",
"metadata": {},
"outputs": [],
"source": [
"#if df2.close_smooth.iloc[peaks_idx[-1 - down_run_length]] < df2.close_smooth.iloc[peaks_idx[-2 - down_run_length]] :\n",
"#\\\n",
"if df2.close_smooth.iloc[troughs_idx[-1 - down_run_length]] < df2.close_smooth.iloc[troughs_idx[-1 - down_run_length]]:\n",
" print(True)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "564deae7",
"metadata": {},
"outputs": [],
"source": [
"!pip install ffmpeg-python "
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "414f56a7",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 31,
"id": "e8e6c15e",
"metadata": {
"scrolled": false
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"c:\\ProgramData\\anaconda3\\Lib\\site-packages\\matplotlib\\animation.py:1740: UserWarning: Can not start iterating the frames for the initial draw. This can be caused by passing in a 0 length sequence for *frames*.\n",
"\n",
"If you passed *frames* as a generator it may be exhausted due to a previous display or save.\n",
" warnings.warn(\n"
]
},
{
"ename": "RuntimeError",
"evalue": "Requested MovieWriter (ffmpeg) not available",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mRuntimeError\u001b[0m Traceback (most recent call last)",
"Cell \u001b[1;32mIn[31], line 85\u001b[0m\n\u001b[0;32m 81\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m price, price_smooth, peaks, troughs\n\u001b[0;32m 84\u001b[0m anim \u001b[38;5;241m=\u001b[39m FuncAnimation(fig, animate, frames\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mlen\u001b[39m(df)\u001b[38;5;241m-\u001b[39mbars_in_frame, interval\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m40\u001b[39m, blit\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m)\n\u001b[1;32m---> 85\u001b[0m video \u001b[38;5;241m=\u001b[39m HTML(anim\u001b[38;5;241m.\u001b[39mto_html5_video())\n\u001b[0;32m 86\u001b[0m display\u001b[38;5;241m.\u001b[39mdisplay(video)\n",
"File \u001b[1;32mc:\\ProgramData\\anaconda3\\Lib\\site-packages\\matplotlib\\animation.py:1284\u001b[0m, in \u001b[0;36mAnimation.to_html5_video\u001b[1;34m(self, embed_limit)\u001b[0m\n\u001b[0;32m 1281\u001b[0m path \u001b[38;5;241m=\u001b[39m Path(tmpdir, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtemp.m4v\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m 1282\u001b[0m \u001b[38;5;66;03m# We create a writer manually so that we can get the\u001b[39;00m\n\u001b[0;32m 1283\u001b[0m \u001b[38;5;66;03m# appropriate size for the tag\u001b[39;00m\n\u001b[1;32m-> 1284\u001b[0m Writer \u001b[38;5;241m=\u001b[39m writers[mpl\u001b[38;5;241m.\u001b[39mrcParams[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124manimation.writer\u001b[39m\u001b[38;5;124m'\u001b[39m]]\n\u001b[0;32m 1285\u001b[0m writer \u001b[38;5;241m=\u001b[39m Writer(codec\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mh264\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[0;32m 1286\u001b[0m bitrate\u001b[38;5;241m=\u001b[39mmpl\u001b[38;5;241m.\u001b[39mrcParams[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124manimation.bitrate\u001b[39m\u001b[38;5;124m'\u001b[39m],\n\u001b[0;32m 1287\u001b[0m fps\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m1000.\u001b[39m \u001b[38;5;241m/\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_interval)\n\u001b[0;32m 1288\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msave(\u001b[38;5;28mstr\u001b[39m(path), writer\u001b[38;5;241m=\u001b[39mwriter)\n",
"File \u001b[1;32mc:\\ProgramData\\anaconda3\\Lib\\site-packages\\matplotlib\\animation.py:148\u001b[0m, in \u001b[0;36mMovieWriterRegistry.__getitem__\u001b[1;34m(self, name)\u001b[0m\n\u001b[0;32m 146\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mis_available(name):\n\u001b[0;32m 147\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_registered[name]\n\u001b[1;32m--> 148\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mRuntimeError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mRequested MovieWriter (\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mname\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m) not available\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n",
"\u001b[1;31mRuntimeError\u001b[0m: Requested MovieWriter (ffmpeg) not available"
]
},
{
"data": {
"image/png": "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 truncated
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import matplotlib\n",
"matplotlib.rcParams['animation.embed_limit'] = 2**128\n",
"\n",
"bars_in_frame = 300\n",
"\n",
"\n",
"fig, ax = plt.subplots()\n",
"\n",
"# increase video quality\n",
"#fig, ax = plt.subplots(figsize=(8,8), dpi=300)\n",
"\n",
"price, = ax.plot([], c='grey', lw=3, alpha=0.5, zorder=5)\n",
"price_smooth, = ax.plot([], c='b', lw=5, zorder=5)\n",
"peaks, = ax.plot([], c=\"r\", linestyle='None', markersize = 15.0, marker = \"o\", zorder=10)\n",
"troughs, = ax.plot([], c=\"g\", linestyle='None', markersize = 15.0, marker = \"o\", zorder=10)\n",
"\n",
"\n",
"## Might turn the yaxis off, can be annoying\n",
"ax.set_ylim(15000,20000)\n",
"ax.set_xlim(0,bars_in_frame)\n",
"\n",
"def animate(frame):\n",
" \n",
" frames_behind = 30\n",
"\n",
" df2 = df.iloc[-len(df) + frame + 30:frame+bars_in_frame + 30]\n",
" df2[\"close_smooth\"] = savgol_filter(df2.close, 49, 5)\n",
"\n",
" df2 = df2.iloc[frames_behind:]\n",
" \n",
" x_coords = [x for x in range(len(df2.close_smooth))]\n",
" \n",
" price.set_data((x_coords, df2.close))\n",
" price_smooth.set_data((x_coords, df2.close_smooth))\n",
" \n",
" first_atr = df2.atr.iloc[0]\n",
" \n",
" ax.set_ylim(df2.close_smooth.min() - 10*first_atr, df2.close_smooth.max() + 10*first_atr)\n",
" \n",
" peaks_idx, _ = find_peaks(df2.close_smooth, distance = 15, \n",
" width = 3, prominence=first_atr)\n",
"\n",
" troughs_idx, _ = find_peaks(-1*df2.close_smooth, distance = 15, \n",
" width = 3, prominence=first_atr)\n",
" \n",
" up_run_length = 0\n",
" up_run = True\n",
" while up_run:\n",
" if 2 + up_run_length > len(peaks_idx) or 2 + up_run_length > len(troughs_idx):\n",
" break\n",
"\n",
" if df2.close_smooth.iloc[peaks_idx[-1 - up_run_length]] > df2.close_smooth.iloc[peaks_idx[-2 - up_run_length]] and \\\n",
" df2.close_smooth.iloc[troughs_idx[-1 - up_run_length]] > df2.close_smooth.iloc[troughs_idx[-2 - up_run_length]]:\n",
" up_run_length += 1\n",
" else:\n",
" up_run = False\n",
"\n",
" down_run_length = 0\n",
" down_run = True\n",
" while down_run:\n",
" if 2 + down_run_length > len(peaks_idx) or 2 + down_run_length > len(troughs_idx):\n",
" break\n",
" \n",
" if df2.close_smooth.iloc[peaks_idx[-1 - down_run_length]] < df2.close_smooth.iloc[peaks_idx[-2 - down_run_length]] and \\\n",
" df2.close_smooth.iloc[troughs_idx[-1 - down_run_length]] < + df2.close_smooth.iloc[troughs_idx[-2 - down_run_length]]:\n",
" down_run_length += 1\n",
" else:\n",
" down_run = False\n",
" \n",
" peaks.set_data((peaks_idx, df2.close_smooth.iloc[peaks_idx]))\n",
" troughs.set_data((troughs_idx, df2.close_smooth.iloc[troughs_idx]))\n",
" \n",
" if up_run_length > 0:\n",
" \n",
" ax.set_facecolor((150/255, 255/255, 159/255, 0.3))\n",
" elif down_run_length > 0:\n",
" ax.set_facecolor((255/255, 150/255, 150/255, 0.3))\n",
" else:\n",
" ax.set_facecolor(\"white\")\n",
" \n",
" return price, price_smooth, peaks, troughs\n",
"\n",
"\n",
"anim = FuncAnimation(fig, animate, frames=len(df)-bars_in_frame, interval=40, blit=True)\n",
"video = HTML(anim.to_html5_video())\n",
"display.display(video)"
]
},
{
"cell_type": "markdown",
"id": "87748618",
"metadata": {},
"source": [
"# Saving our animation"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8d808048",
"metadata": {},
"outputs": [],
"source": [
"with open('video-hd.html', 'w') as f:\n",
" f.write(video.data)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "21838944",
"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
}
@@ -1,2 +0,0 @@
[ZoneTransfer]
ZoneId=3
+322
View File
@@ -0,0 +1,322 @@
#!/usr/bin/env python3
"""
📥 JSON Trade History → SQLite Database Importer
Importiert alte Trade-Daten aus JSON-Dateien in die trading_bot.db
"""
import json
import sqlite3
import os
from datetime import datetime
import glob
# ==========================================
# CONFIGURATION
# ==========================================
DB_PATH = "trading_bot.db"
JSON_PATTERN = "trade_performance_*.json" # Alle JSON-Dateien mit diesem Muster
# ==========================================
# DATABASE CONNECTION
# ==========================================
def get_db_connection():
"""Verbindung zur Datenbank herstellen"""
conn = sqlite3.connect(DB_PATH)
conn.row_factory = sqlite3.Row
return conn
# ==========================================
# IMPORT FUNCTIONS
# ==========================================
def parse_trade_data(trade, index=0):
"""
Konvertiert JSON Trade-Daten ins Datenbank-Format
"""
# Generate unique ticket from timestamp + index (für historische Daten ohne echtes Ticket)
timestamp = trade.get('timestamp', '')
ticket = hash(timestamp + str(index)) % 1000000000 # Unique ticket generieren
# Basis-Daten
data = {
'ticket': ticket,
'position_id': 0, # Nicht in JSON vorhanden
'symbol': trade.get('symbol', 'XAUUSD'),
'strategy_name': 'TradingBot_' + trade.get('version', 'V1.6'),
'type': 'BUY' if trade.get('entry_signal') == 1 else 'SELL' if trade.get('entry_signal') == -1 else 'UNKNOWN',
'volume': 0.01, # Default, nicht in JSON
'entry_price': 0.0, # Nicht in JSON
'exit_price': None,
'sl_price': None,
'tp_price': None,
'entry_time': trade.get('timestamp'),
'exit_time': None,
'duration_hours': None,
'session': trade.get('session', 'unknown'),
'regime': trade.get('market_regime', 'unknown'),
'quality': trade.get('signal_quality', 'unknown'),
'confidence': trade.get('confidence', 0.0),
'timeframe_alignment': trade.get('timeframe_alignment', 2),
'profit': None, # Nicht in JSON
'commission': 0.0,
'swap': 0.0,
'net_profit': None,
'profit_pct': None,
'risk_amount': trade.get('risk_amount'),
'risk_pct': trade.get('risk_pct', 0.01),
'rr_ratio': None,
'status': 'historical', # Markiere als historische Daten
'exit_reason': 'imported_from_json'
}
return data
def import_json_file(filepath, conn):
"""
Importiert eine JSON-Datei in die Datenbank
"""
print(f"\n📄 Processing: {os.path.basename(filepath)}")
try:
with open(filepath, 'r') as f:
trades = json.load(f)
if not isinstance(trades, list):
print(f" ⚠️ Skipped: Not a list of trades")
return 0
imported_count = 0
skipped_count = 0
cursor = conn.cursor()
for i, trade in enumerate(trades):
try:
# Parse trade data (mit Index für unique ticket)
data = parse_trade_data(trade, index=i)
# Check if already exists (by timestamp + symbol)
cursor.execute("""
SELECT id FROM trades
WHERE entry_time = ? AND symbol = ?
""", (data['entry_time'], data['symbol']))
if cursor.fetchone():
skipped_count += 1
continue
# Insert into database
cursor.execute("""
INSERT INTO trades (
ticket, position_id, symbol, strategy_name, type, volume,
entry_price, exit_price, sl_price, tp_price,
entry_time, exit_time, duration_hours,
session, regime, quality, confidence, timeframe_alignment,
profit, commission, swap, net_profit, profit_pct,
risk_amount, risk_pct, rr_ratio,
status, exit_reason
) VALUES (
?, ?, ?, ?, ?, ?,
?, ?, ?, ?,
?, ?, ?,
?, ?, ?, ?, ?,
?, ?, ?, ?, ?,
?, ?, ?,
?, ?
)
""", (
data['ticket'], data['position_id'], data['symbol'],
data['strategy_name'], data['type'], data['volume'],
data['entry_price'], data['exit_price'], data['sl_price'], data['tp_price'],
data['entry_time'], data['exit_time'], data['duration_hours'],
data['session'], data['regime'], data['quality'],
data['confidence'], data['timeframe_alignment'],
data['profit'], data['commission'], data['swap'],
data['net_profit'], data['profit_pct'],
data['risk_amount'], data['risk_pct'], data['rr_ratio'],
data['status'], data['exit_reason']
))
imported_count += 1
except Exception as e:
print(f" ⚠️ Error importing trade: {e}")
continue
conn.commit()
print(f" ✅ Imported: {imported_count} trades")
print(f" ⏭️ Skipped: {skipped_count} trades (duplicates)")
return imported_count
except Exception as e:
print(f" ❌ Error reading file: {e}")
return 0
def import_all_json_files():
"""
Importiert alle JSON-Dateien im aktuellen Verzeichnis
"""
print("=" * 80)
print("📥 JSON TO DATABASE IMPORTER")
print("=" * 80)
# Finde alle JSON-Dateien
json_files = glob.glob(JSON_PATTERN)
if not json_files:
print(f"\n⚠️ No JSON files found matching pattern: {JSON_PATTERN}")
print("\nSearching for any trade_performance*.json files...")
json_files = glob.glob("trade_performance*.json")
if not json_files:
print("\n❌ No JSON files found!")
print("\nMake sure you have JSON files in this directory:")
print(f" {os.getcwd()}")
return
print(f"\n📊 Found {len(json_files)} JSON file(s):")
for f in json_files:
print(f" • {os.path.basename(f)}")
# Verbinde zur Datenbank
print(f"\n🔌 Connecting to database: {DB_PATH}")
if not os.path.exists(DB_PATH):
print(f"\n❌ Database not found: {DB_PATH}")
print("\n💡 Please run the Trading Bot first to create the database!")
return
conn = get_db_connection()
# Importiere jede Datei
total_imported = 0
for json_file in json_files:
imported = import_json_file(json_file, conn)
total_imported += imported
conn.close()
# Summary
print("\n" + "=" * 80)
print("📊 IMPORT SUMMARY")
print("=" * 80)
print(f"Files processed: {len(json_files)}")
print(f"Total trades imported: {total_imported}")
print(f"\n✅ Import complete!")
# Zeige Statistik
show_database_stats()
def show_database_stats():
"""
Zeigt Statistiken der importierten Daten
"""
conn = get_db_connection()
cursor = conn.cursor()
print("\n" + "=" * 80)
print("📈 DATABASE STATISTICS")
print("=" * 80)
# Total trades
cursor.execute("SELECT COUNT(*) FROM trades")
total = cursor.fetchone()[0]
print(f"\nTotal trades in database: {total}")
# By session
cursor.execute("""
SELECT session, COUNT(*) as count
FROM trades
GROUP BY session
ORDER BY count DESC
""")
print("\nTrades by Session:")
for row in cursor.fetchall():
session = row[0] or 'unknown'
count = row[1]
pct = (count / total * 100) if total > 0 else 0
print(f" {session:10s}: {count:4d} ({pct:5.1f}%)")
# By version
cursor.execute("""
SELECT strategy_name, COUNT(*) as count
FROM trades
GROUP BY strategy_name
ORDER BY count DESC
""")
print("\nTrades by Version:")
for row in cursor.fetchall():
version = row[0]
count = row[1]
print(f" {version:20s}: {count:4d}")
# Date range
cursor.execute("""
SELECT
MIN(entry_time) as first_trade,
MAX(entry_time) as last_trade
FROM trades
""")
row = cursor.fetchone()
if row[0]:
print(f"\nDate Range:")
print(f" First trade: {row[0]}")
print(f" Last trade: {row[1]}")
conn.close()
print("\n" + "=" * 80)
# ==========================================
# MANUAL IMPORT FUNCTION
# ==========================================
def import_specific_file(filepath):
"""
Importiert eine spezifische JSON-Datei
Usage:
python import_json_to_db.py <filepath>
"""
print("=" * 80)
print("📥 MANUAL JSON IMPORT")
print("=" * 80)
if not os.path.exists(filepath):
print(f"\n❌ File not found: {filepath}")
return
if not os.path.exists(DB_PATH):
print(f"\n❌ Database not found: {DB_PATH}")
print("\n💡 Please run the Trading Bot first to create the database!")
return
conn = get_db_connection()
imported = import_json_file(filepath, conn)
conn.close()
print(f"\n✅ Import complete! Imported {imported} trades.")
show_database_stats()
# ==========================================
# MAIN
# ==========================================
if __name__ == "__main__":
import sys
if len(sys.argv) > 1:
# Manual import of specific file
filepath = sys.argv[1]
import_specific_file(filepath)
else:
# Auto-import all JSON files
import_all_json_files()
+531
View File
@@ -0,0 +1,531 @@
"""
🔧 INFRASTRUCTURE PATCH - SQLite + Telegram Integration
Verbindet TradingBot mit Database Logging und Telegram Notifications
INTEGRATION:
- Automatisches DB Logging bei Trade Entry/Exit
- Telegram Notifications für alle Events
- Performance Tracking
- Error Handling
USAGE:
1. Import am Anfang des Notebooks
2. Initialize Infrastructure
3. Wrapper um execute_trade und Position Management
"""
from trading_database import TradingDatabase
from telegram_notifier import TelegramNotifier, load_telegram_config
from datetime import datetime
from typing import Dict, Optional, Callable
import json
import os
class TradingInfrastructure:
"""
Infrastruktur-Manager für Database + Telegram Integration
"""
def __init__(
self,
db_path: str = "trading_bot.db",
telegram_config: Dict = None,
enable_telegram: bool = True,
enable_database: bool = True
):
"""
Initialize Infrastructure
Args:
db_path: Path to SQLite database
telegram_config: Dict with bot_token and chat_id
enable_telegram: Enable Telegram notifications
enable_database: Enable database logging
"""
self.enable_telegram = enable_telegram
self.enable_database = enable_database
# Initialize Database
if self.enable_database:
try:
self.db = TradingDatabase(db_path)
print(f"✅ Database initialized: {db_path}")
except Exception as e:
print(f"❌ Database initialization failed: {e}")
self.enable_database = False
self.db = None
else:
self.db = None
# Initialize Telegram
if self.enable_telegram:
try:
if telegram_config is None:
telegram_config = load_telegram_config()
if telegram_config:
self.telegram = TelegramNotifier(
bot_token=telegram_config['bot_token'],
chat_id=telegram_config['chat_id']
)
print("✅ Telegram notifications enabled")
else:
print("⚠️ No Telegram config found, notifications disabled")
self.enable_telegram = False
self.telegram = None
except Exception as e:
print(f"❌ Telegram initialization failed: {e}")
self.enable_telegram = False
self.telegram = None
else:
self.telegram = None
# ==========================================
# TRADE LOGGING
# ==========================================
def log_trade_entry(self, trade_data: Dict):
"""
Log trade entry to database and send notification
Args:
trade_data: Dictionary with trade information
"""
# Log to database
if self.enable_database and self.db:
try:
self.db.log_trade_entry(trade_data)
except Exception as e:
print(f"⚠️ Database logging failed: {e}")
# Send Telegram notification
if self.enable_telegram and self.telegram:
try:
self.telegram.notify_trade_entry(trade_data)
except Exception as e:
print(f"⚠️ Telegram notification failed: {e}")
def log_trade_exit(self, ticket: int, exit_data: Dict):
"""
Log trade exit to database and send notification
Args:
ticket: MT5 ticket number
exit_data: Dictionary with exit information
"""
# Update database
if self.enable_database and self.db:
try:
self.db.update_trade_exit(ticket, exit_data)
except Exception as e:
print(f"⚠️ Database update failed: {e}")
# Send Telegram notification
if self.enable_telegram and self.telegram:
try:
# Get full trade data from database
if self.db:
trades = self.db.cursor.execute(
"SELECT * FROM trades WHERE ticket = ?",
(ticket,)
).fetchone()
if trades:
trade_dict = dict(trades)
trade_dict.update(exit_data)
self.telegram.notify_trade_exit(trade_dict)
else:
# Fallback if no database
self.telegram.notify_trade_exit(exit_data)
except Exception as e:
print(f"⚠️ Telegram notification failed: {e}")
# ==========================================
# WRAPPER FUNCTIONS
# ==========================================
def create_monitored_execute_trade(self, original_execute_func: Callable):
"""
Create a wrapper around execute_trade function that logs to infrastructure
Args:
original_execute_func: Original execute_trade_v2_adaptive function
Returns:
Wrapped function with logging
"""
def wrapped_execute_trade(*args, **kwargs):
"""
Wrapped execute trade with infrastructure logging
"""
try:
# Call original function
result = original_execute_func(*args, **kwargs)
# If trade was executed, result should contain trade info
# This depends on your execute_trade implementation
# You might need to modify execute_trade to return trade data
return result
except Exception as e:
# Log error
if self.enable_telegram and self.telegram:
self.telegram.send_error_alert(
str(e),
f"Error in execute_trade for {kwargs.get('symbol', 'unknown')}"
)
raise
return wrapped_execute_trade
def extract_trade_data_from_mt5(self, position, strategy_name: str, session: str,
confidence: float = None, quality: str = None) -> Dict:
"""
Extract trade data from MT5 position for logging
Args:
position: MT5 position object
strategy_name: Strategy name
session: Trading session
confidence: Signal confidence
quality: Signal quality
Returns:
Dictionary with trade data
"""
return {
'ticket': position.ticket,
'position_id': position.identifier,
'symbol': position.symbol,
'strategy_name': strategy_name,
'type': 'BUY' if position.type == 0 else 'SELL',
'volume': position.volume,
'entry_price': position.price_open,
'sl_price': position.sl,
'tp_price': position.tp,
'entry_time': datetime.fromtimestamp(position.time).strftime('%Y-%m-%d %H:%M:%S'),
'session': session,
'confidence': confidence,
'quality': quality,
'risk_pct': 0.01, # From config
'status': 'open'
}
# ==========================================
# STATUS & MONITORING
# ==========================================
def send_bot_started(self, config: Dict):
"""
Send bot started notification
Args:
config: Bot configuration
"""
if self.enable_telegram and self.telegram:
try:
self.telegram.send_bot_started(config)
except Exception as e:
print(f"⚠️ Telegram notification failed: {e}")
def send_bot_stopped(self, reason: str = "Manual stop"):
"""
Send bot stopped notification
Args:
reason: Stop reason
"""
if self.enable_telegram and self.telegram:
try:
self.telegram.send_bot_stopped(reason)
except Exception as e:
print(f"⚠️ Telegram notification failed: {e}")
def send_daily_report(self):
"""Send daily performance report"""
if not (self.enable_database and self.enable_telegram):
return
try:
stats = self.db.get_daily_summary()
self.telegram.send_daily_report(stats)
except Exception as e:
print(f"⚠️ Daily report failed: {e}")
def send_weekly_report(self):
"""Send weekly performance report"""
if not (self.enable_database and self.enable_telegram):
return
try:
stats = self.db.get_overall_statistics(days=7)
session_perf = self.db.get_session_performance(days=7)
self.telegram.send_weekly_report(stats, session_perf)
except Exception as e:
print(f"⚠️ Weekly report failed: {e}")
def log_bot_status(self, status: str, config: Dict = None, error_message: str = None):
"""
Log bot status to database
Args:
status: 'running', 'stopped', 'error'
config: Optional bot configuration
error_message: Optional error message
"""
if not (self.enable_database and self.db):
return
try:
status_data = {
'status': status,
'version': config.get('version', 'V1.8') if config else 'V1.8',
'active_sessions': [s for s, enabled in config.get('enabled_sessions', {}).items() if enabled] if config else [],
'confidence_threshold': config.get('base_confidence', 60) if config else 60,
'error_message': error_message
}
self.db.log_bot_status(status_data)
except Exception as e:
print(f"⚠️ Status logging failed: {e}")
# ==========================================
# MIGRATION & UTILITIES
# ==========================================
def migrate_json_files(self, json_folder: str = "."):
"""
Migrate all JSON performance files to SQLite
Args:
json_folder: Folder containing JSON files
"""
if not (self.enable_database and self.db):
print("❌ Database not enabled")
return
import glob
json_files = glob.glob(os.path.join(json_folder, "trade_performance_*.json"))
if not json_files:
print("⚠️ No JSON files found")
return
print(f"📁 Found {len(json_files)} JSON files")
for json_file in json_files:
print(f"\n🔄 Migrating: {json_file}")
try:
self.db.migrate_from_json(json_file)
except Exception as e:
print(f"❌ Migration failed for {json_file}: {e}")
print("\n✅ Migration complete")
def get_performance_summary(self, days: int = 7) -> Dict:
"""
Get performance summary
Args:
days: Number of days to analyze
Returns:
Dictionary with statistics
"""
if not (self.enable_database and self.db):
return {}
try:
stats = self.db.get_overall_statistics(days=days)
session_perf = self.db.get_session_performance(days=days)
return {
'overall': stats,
'sessions': session_perf
}
except Exception as e:
print(f"⚠️ Performance summary failed: {e}")
return {}
def close(self):
"""Close all connections"""
if self.db:
self.db.close()
def __enter__(self):
"""Context manager entry"""
return self
def __exit__(self, exc_type, exc_val, exc_tb):
"""Context manager exit"""
self.close()
# ==========================================
# SCHEDULER INTEGRATION
# ==========================================
def create_scheduled_reports(infrastructure: TradingInfrastructure, scheduler):
"""
Add scheduled reports to APScheduler
Args:
infrastructure: TradingInfrastructure instance
scheduler: APScheduler instance
"""
# Daily report at 22:00 UTC
scheduler.add_job(
infrastructure.send_daily_report,
'cron',
hour=22,
minute=0,
id='daily_report',
replace_existing=True
)
# Weekly report on Sunday at 23:00 UTC
scheduler.add_job(
infrastructure.send_weekly_report,
'cron',
day_of_week='sun',
hour=23,
minute=0,
id='weekly_report',
replace_existing=True
)
print("✅ Scheduled reports added:")
print(" 📊 Daily report: 22:00 UTC")
print(" 📈 Weekly report: Sunday 23:00 UTC")
# ==========================================
# INTEGRATION HELPER
# ==========================================
def create_infrastructure_config() -> Dict:
"""
Create infrastructure configuration
Returns:
Dictionary with configuration
"""
return {
'database': {
'enabled': True,
'path': 'trading_bot.db'
},
'telegram': {
'enabled': True,
'notifications': {
'trade_entry': True,
'trade_exit': True,
'daily_report': True,
'weekly_report': True,
'error_alerts': True
}
}
}
# ==========================================
# USAGE EXAMPLE
# ==========================================
if __name__ == "__main__":
print("="*70)
print("🔧 INFRASTRUCTURE PATCH - Setup Check")
print("="*70)
# Initialize infrastructure
infra = TradingInfrastructure(
db_path="trading_bot.db",
enable_telegram=False # Disable for testing
)
print("\n📊 Checking database...")
if infra.db:
stats = infra.db.get_overall_statistics()
print(f" Total Trades: {stats.get('total_trades', 0)}")
print(f" Win Rate: {stats.get('win_rate', 0)}%")
print("\n" + "="*70)
print("✅ Infrastructure ready!")
print("="*70)
print("""
📋 Integration Steps:
1. Configure Telegram (optional):
- Run: python telegram_notifier.py
- Follow setup instructions
- Create telegram_config.json
2. In your Notebook, add at the beginning:
```python
from infrastructure_patch import TradingInfrastructure, create_scheduled_reports
from session_filter_patch import SESSION_WHITELIST_CONFIG
# Initialize infrastructure
infra = TradingInfrastructure(
db_path="trading_bot.db",
enable_telegram=True,
enable_database=True
)
# Send bot started notification
infra.send_bot_started(SESSION_WHITELIST_CONFIG)
# Add scheduled reports to your scheduler
create_scheduled_reports(infra, scheduler)
```
3. When opening a trade, log it:
```python
# After position opened
trade_data = infra.extract_trade_data_from_mt5(
position, strategy_name, session, confidence, quality
)
infra.log_trade_entry(trade_data)
```
4. When closing a trade, log exit:
```python
# After position closed
exit_data = {
'exit_price': close_price,
'exit_time': datetime.now(),
'profit': profit,
'net_profit': net_profit,
'exit_reason': 'tp' or 'sl'
}
infra.log_trade_exit(ticket, exit_data)
```
5. Optional - Migrate existing JSON data:
```python
infra.migrate_json_files(".")
```
""")
infra.close()
-1963
View File
File diff suppressed because it is too large. Load diff
-199
View File
@@ -1,199 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Import Libaries"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"import keyring as kr"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Save Pwd to keyring\n",
"\n",
"- **servicename** – The name of the service i.e to a certain organization with which the person is related to.\n",
"- **username** – Username of the person.\n",
"- **password** – Password associated with that username.\n",
"\n",
"```python\n",
"kr.set_password(\"servicename\",\"username\",\"pwd\")\n",
"```\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"# Live Acccount\n",
"login = 10676507\n",
"password = '5l5^hbEL'\n",
"server = 'VantageInternational-Live 4'"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"# Demo Acccount\n",
"login = 10800246\n",
"password = '%dN!Zu96'\n",
"server = 'VantageInternational-Demo'"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"kr.set_password(server, str(login), password)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Get Password\n",
"\n",
"To retrieve the saved password we will use the get_password() method. It takes two parameters.\n",
"\n",
"- Servicename\n",
"- Username\n",
"\n",
"```python\n",
"print(kr.get_password(\"Servicename\",\"Username\"))\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"5l5^hbEL\n"
]
}
],
"source": [
"print(kr.get_password(server,str(login)))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Retrievieng Credentials"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Username : 10676507\n",
"Password : 5l5^hbEL\n"
]
}
],
"source": [
"cred = kr.get_credential(server,\"\") \n",
" \n",
"print(\"Username : \",cred.username) \n",
"print(\"Password : \",cred.password)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Delete from Keyring\n",
"\n",
"To delete a password we will use the delete_password() method. It also takes two parameters:\n",
"\n",
"- Servicename\n",
"- Username\n",
"\n",
"```python\n",
"kr.delete_password(\"Servicename\", \"Username\") \n",
"```"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"kr.delete_password(server, str(login)) "
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"None\n"
]
}
],
"source": [
"print(kr.get_password(server, str(login)))"
]
},
{
"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
}
+59
View File
@@ -0,0 +1,59 @@
======================================================================
TRADINGBOT V1.6 - DETAILED PERFORMANCE REPORT
======================================================================
Generated: 2025-11-13 01:07:34
ZEITRAUM
----------------------------------------------------------------------
Start: 2025-10-31 00:43
Ende: 2025-11-13 00:45
Tage: 14 Tage
Total Trades: 112
Trades/Tag: 8.00
SESSION VERTEILUNG
----------------------------------------------------------------------
Asian : 44 ( 39.29%)
London : 27 ( 24.11%)
Ny : 13 ( 11.61%)
Overlap : 28 ( 25.00%)
MARKET REGIME
----------------------------------------------------------------------
Ranging : 112 (100.00%)
ADAPTIVE INTERVALS
----------------------------------------------------------------------
5 Min: 13 ( 11.61%)
15 Min: 63 ( 56.25%)
30 Min: 36 ( 32.14%)
HOURLY DISTRIBUTION (Top 10)
----------------------------------------------------------------------
14:00 UTC: 11 ( 9.82%)
15:00 UTC: 11 ( 9.82%)
09:00 UTC: 9 ( 8.04%)
02:00 UTC: 8 ( 7.14%)
13:00 UTC: 7 ( 6.25%)
03:00 UTC: 6 ( 5.36%)
16:00 UTC: 6 ( 5.36%)
04:00 UTC: 5 ( 4.46%)
06:00 UTC: 5 ( 4.46%)
11:00 UTC: 5 ( 4.46%)
WICHTIGE ERKENNTNISSE
----------------------------------------------------------------------
• Aktivste Session: ASIAN (44 trades)
• Häufigstes Regime: RANGING (112 trades)
• Meist genutztes Interval: 15 min (63 trades)
• Durchschnittliche Confidence: 85.0%
• Durchschnittliches Risk/Reward: 2.45
WARNUNG
----------------------------------------------------------------------
Dieser Report zeigt nur Signal-Generierung und Entry-Daten.
Für echte Profitabilitäts-Bewertung werden Exit-Daten
und P&L aus MT5 benötigt.
======================================================================
-2379
View File
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+288
View File
@@ -0,0 +1,288 @@
"""
🎯 SESSION FILTER PATCH - TradingBot V1.6 to V1.7
Optimiert Trading basierend auf Performance-Analyse
ÄNDERUNGEN:
1. Deaktiviert Asian Session (25.6% Win-Rate, -$199 Verlust)
2. Aktiviert nur NY + Overlap (beste Performance)
3. Optional: London Session (Break-Even)
PERFORMANCE-IMPACT:
- Asian ausschalten: -$199 eliminiert
- Nur NY+Overlap: +$581 (49% mehr Profit)
- Win-Rate: 30.9% → ~38%
"""
# ==========================================
# SESSION WHITELIST CONFIGURATION
# ==========================================
SESSION_WHITELIST_CONFIG = {
# Welche Sessions erlauben?
'enabled_sessions': {
'asian': False, # ❌ DEAKTIVIERT: +$202, aber nur 30.2% Win-Rate
'london': False, # ❌ DEAKTIVIERT: +$79, aber nur 30.8% Win-Rate
'overlap': False, # ❌ DEAKTIVIERT: -$208 kumuliert (2 Wochen), 27.3% Win-Rate
'ny': True, # ✅ NUR NY AKTIV: +$660, 47.6% Win-Rate (BESTE!)
},
# Trading Parameter
'base_confidence': 60, # 🎯 CONFIDENCE THRESHOLD (60=relaxed, 70=balanced, 75=konservativ, 80=sehr strikt)
'atr_mult': 1.5, # ATR Multiplikator für SL/TP
'max_risk_per_trade': 0.01, # Max Risk pro Trade (1%)
'min_atr': 0.0008, # Minimum ATR für Risk Filter
# Trading Optionen
'risk_filter': True, # ATR-basierter Risk Filter
'use_pullback_entry': False, # Pullback Entry Strategie
# Alternativ: Aggressive Mode (nur NY)
'aggressive_mode': False, # ⚠️ Nicht nötig - already configured via enabled_sessions
# Alternativ: Conservative Mode (NY + Overlap + London)
'conservative_mode': False, # ⚠️ Nicht aktiv
# Debug-Modus
'debug': True,
}
# ==========================================
# SESSION FILTER FUNCTION
# ==========================================
def is_session_allowed(session_name, config=SESSION_WHITELIST_CONFIG):
"""
Prüft ob Trading in aktueller Session erlaubt ist
Args:
session_name: 'asian', 'london', 'overlap', 'ny'
config: Configuration Dictionary
Returns:
(allowed: bool, reason: str)
"""
# Aggressive Mode: Nur NY
if config['aggressive_mode']:
allowed = session_name == 'ny'
reason = f"Aggressive Mode: Only NY session" if not allowed else "NY session - best performance"
return allowed, reason
# Conservative Mode: Alle außer Asian
if config['conservative_mode']:
allowed = session_name != 'asian'
reason = f"Conservative Mode: Asian disabled" if not allowed else f"{session_name.upper()} session allowed"
return allowed, reason
# Standard: Whitelist-basiert
allowed = config['enabled_sessions'].get(session_name, False)
if not allowed:
reasons = {
'asian': "Session blocked: Asian has -$199 loss, 25.6% win-rate",
'london': "Session blocked: London is break-even, 29.6% win-rate",
'overlap': "Session blocked: Not in whitelist",
'ny': "Session blocked: Not in whitelist",
}
reason = reasons.get(session_name, f"Session {session_name} not in whitelist")
else:
performance = {
'ny': "+$372 profit, 50.0% win-rate (BEST!)",
'overlap': "+$209 profit, 32.1% win-rate (GOOD)",
'london': "+$7 profit, 29.6% win-rate (Break-even)",
}
reason = f"{session_name.upper()} allowed: {performance.get(session_name, 'In whitelist')}"
return allowed, reason
# ==========================================
# SESSION FILTER WRAPPER
# ==========================================
def create_session_filtered_check(
rhythm_manager,
execute_func,
symbol,
strategy_name,
max_positions,
logger,
datetime,
config=None
):
"""
Factory-Funktion die eine gefilterte Trading-Check-Funktion erstellt
Args:
rhythm_manager: AdaptiveRhythmManager Instanz
execute_func: execute_trade_v2_adaptive Funktion
symbol: Trading Symbol (z.B. "XAUUSD")
strategy_name: Strategy Name
max_positions: Max Positionen
logger: Logger Instanz
datetime: datetime module
config: Optional custom config, sonst SESSION_WHITELIST_CONFIG
Returns:
Gefilterte adaptive_trading_check Funktion
"""
if config is None:
config = SESSION_WHITELIST_CONFIG
# Hole Trading-Parameter aus Config
confidence_threshold = config.get('base_confidence', 60)
atr_mult = config.get('atr_mult', 1.5)
max_risk = config.get('max_risk_per_trade', 0.01)
risk_filter = config.get('risk_filter', True)
min_atr = config.get('min_atr', 0.0008)
use_pullback = config.get('use_pullback_entry', False)
def adaptive_trading_check_filtered():
"""
🆕 V1.7: Session-gefilterte Trading Check Funktion
"""
try:
# 1. Prüfe aktuelle Session
session = rhythm_manager.get_current_session()
allowed, reason = is_session_allowed(session, config)
if not allowed:
if config['debug']:
logger.info(f"⏸️ Trading SKIP: {reason}")
return
# 2. Berechne optimales Intervall
optimal_interval = rhythm_manager.calculate_optimal_interval()
current_minute = datetime.now().minute
# 3. Trading nur zu berechneten Zeitpunkten
if current_minute % optimal_interval == 0:
logger.info(f"\n⏰ {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - ADAPTIVE Check")
logger.info(f"✅ Session: {session.upper()} - {reason}")
logger.info(f"📊 Confidence Threshold: {confidence_threshold}%")
logger.info(f"⏱️ Intervall: {optimal_interval} min")
# Führe Trading aus mit Parametern aus Config
execute_func(
symbol=symbol,
atr_mult=atr_mult,
base_confidence=confidence_threshold,
max_risk_per_trade=max_risk,
risk_filter=risk_filter,
min_atr=min_atr,
use_pullback_entry=use_pullback,
max_positions=max_positions,
strategy_name=strategy_name,
debug=True
)
except Exception as e:
logger.error(f"Fehler im Session-Filtered Trading Check: {e}")
return adaptive_trading_check_filtered
# ==========================================
# USAGE INSTRUCTIONS
# ==========================================
"""
📋 ANLEITUNG - Wie den Patch anwenden:
SCHRITT 1: Dieses File ins gleiche Verzeichnis wie das Notebook kopieren
SCHRITT 2: In Cell 24 (Adaptive Scheduler) folgendes ändern:
VORHER:
```python
def adaptive_trading_check():
try:
optimal_interval = rhythm_manager.calculate_optimal_interval()
...
```
NACHHER:
```python
# Importiere Session Filter
from session_filter_patch import (
adaptive_trading_check_with_session_filter,
SESSION_WHITELIST_CONFIG,
is_session_allowed
)
# Alias für Kompatibilität
adaptive_trading_check = adaptive_trading_check_with_session_filter
```
SCHRITT 3: Scheduler neu starten
SCHRITT 4: Teste mit verschiedenen Modi:
# Standard Mode (NY + Overlap)
SESSION_WHITELIST_CONFIG['enabled_sessions'] = {
'asian': False, 'london': False,
'overlap': True, 'ny': True
}
# Aggressive Mode (nur NY, 50% Win-Rate!)
SESSION_WHITELIST_CONFIG['aggressive_mode'] = True
# Conservative Mode (alles außer Asian)
SESSION_WHITELIST_CONFIG['conservative_mode'] = True
SCHRITT 5: Monitor Performance für 1-2 Wochen
"""
# ==========================================
# TESTING
# ==========================================
if __name__ == "__main__":
print("="*70)
print("🧪 SESSION FILTER TESTS")
print("="*70)
sessions = ['asian', 'london', 'overlap', 'ny']
print("\n📊 STANDARD MODE (NY + Overlap):")
print("-" * 70)
for session in sessions:
allowed, reason = is_session_allowed(session)
emoji = "✅" if allowed else "❌"
print(f"{emoji} {session.upper():8s}: {reason}")
print("\n📊 AGGRESSIVE MODE (nur NY):")
print("-" * 70)
test_config = SESSION_WHITELIST_CONFIG.copy()
test_config['aggressive_mode'] = True
for session in sessions:
allowed, reason = is_session_allowed(session, test_config)
emoji = "✅" if allowed else "❌"
print(f"{emoji} {session.upper():8s}: {reason}")
print("\n📊 CONSERVATIVE MODE (alles außer Asian):")
print("-" * 70)
test_config = SESSION_WHITELIST_CONFIG.copy()
test_config['conservative_mode'] = True
test_config['aggressive_mode'] = False
for session in sessions:
allowed, reason = is_session_allowed(session, test_config)
emoji = "✅" if allowed else "❌"
print(f"{emoji} {session.upper():8s}: {reason}")
print("\n" + "="*70)
print("✅ Tests complete")
print("="*70)
print("\n💡 ERWARTETE PERFORMANCE-VERBESSERUNG:")
print(" Standard Mode (NY + Overlap):")
print(" • Trades: 40 statt 110 (-64%)")
print(" • Profit: +$581 statt +$389 (+49%)")
print(" • Win-Rate: ~38% statt 30.9%")
print("\n Aggressive Mode (nur NY):")
print(" • Trades: 12 statt 110 (-89%)")
print(" • Profit: +$372 statt +$389 (-4%, aber 50% Win-Rate!)")
print(" • Win-Rate: 50% statt 30.9% (+19.1%)")
+13
View File
@@ -0,0 +1,13 @@
{
"bot_token": "YOUR_BOT_TOKEN_HERE",
"chat_id": "YOUR_CHAT_ID_HERE",
"notifications": {
"trade_entry": true,
"trade_exit": true,
"daily_report": true,
"weekly_report": true,
"error_alerts": true
},
"daily_report_time": "22:00",
"weekly_report_day": "Sunday"
}
+551
View File
@@ -0,0 +1,551 @@
"""
📱 TELEGRAM NOTIFIER - Mobile Trading Notifications
Sendet Trade Updates, Performance Reports und Alerts
FEATURES:
- Trade Entry/Exit Notifications
- Daily/Weekly Performance Reports
- Error Alerts
- Bot Status Updates
- Custom Commands (/status, /report)
"""
import requests
import json
from datetime import datetime, timedelta
from typing import Dict, List, Optional
import os
class TelegramNotifier:
"""
Telegram Bot Integration für Trading Notifications
"""
def __init__(self, bot_token: str, chat_id: str):
"""
Initialize Telegram Bot
Args:
bot_token: Telegram Bot Token (von @BotFather)
chat_id: Telegram Chat ID (deine User ID)
"""
self.bot_token = bot_token
self.chat_id = chat_id
self.base_url = f"https://api.telegram.org/bot{bot_token}"
# Test connection
self._test_connection()
def _test_connection(self):
"""Test Telegram API connection"""
try:
response = requests.get(f"{self.base_url}/getMe", timeout=5)
if response.status_code == 200:
bot_info = response.json()
print(f"✅ Telegram Bot connected: @{bot_info['result']['username']}")
else:
print(f"⚠️ Telegram connection issue: {response.status_code}")
except Exception as e:
print(f"❌ Telegram connection failed: {e}")
def send_message(self, text: str, parse_mode: str = "Markdown") -> bool:
"""
Send a text message to Telegram
Args:
text: Message text (supports Markdown)
parse_mode: 'Markdown' or 'HTML'
Returns:
True if successful, False otherwise
"""
try:
url = f"{self.base_url}/sendMessage"
payload = {
'chat_id': self.chat_id,
'text': text,
'parse_mode': parse_mode,
'disable_web_page_preview': True
}
response = requests.post(url, json=payload, timeout=10)
if response.status_code == 200:
return True
else:
print(f"⚠️ Telegram send failed: {response.status_code}")
return False
except Exception as e:
print(f"❌ Telegram error: {e}")
return False
# ==========================================
# TRADE NOTIFICATIONS
# ==========================================
def notify_trade_entry(self, trade_data: Dict):
"""
Notify about new trade entry
Args:
trade_data: Dictionary with trade information
"""
type_emoji = "🟢" if trade_data['type'] == 'BUY' else "🔴"
session_emoji = self._get_session_emoji(trade_data.get('session', 'unknown'))
message = f"""
{type_emoji} *Trade Opened*
*Symbol:* {trade_data['symbol']}
*Type:* {trade_data['type']}
*Entry:* {trade_data['entry_price']}
*SL:* {trade_data.get('sl_price', 'N/A')} | *TP:* {trade_data.get('tp_price', 'N/A')}
*Risk:* ${trade_data.get('risk_amount', 0):.2f} ({trade_data.get('risk_pct', 0)*100:.1f}%)
*Volume:* {trade_data.get('volume', 0)} lots
{session_emoji} *Session:* {trade_data.get('session', 'unknown').upper()}
📊 *Confidence:* {trade_data.get('confidence', 0):.1f}%
🎯 *Quality:* {trade_data.get('quality', 'unknown').upper()}
⏰ {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} UTC
"""
self.send_message(message)
def notify_trade_exit(self, trade_data: Dict):
"""
Notify about trade exit
Args:
trade_data: Dictionary with trade and exit information
"""
profit = trade_data.get('net_profit', 0)
profit_emoji = "✅" if profit > 0 else "❌"
type_emoji = "🟢" if trade_data['type'] == 'BUY' else "🔴"
# Format profit/loss
profit_text = f"+${profit:.2f}" if profit > 0 else f"${profit:.2f}"
message = f"""
{profit_emoji} *Trade Closed* {type_emoji}
*Symbol:* {trade_data['symbol']}
*Type:* {trade_data['type']}
*Entry:* {trade_data['entry_price']}
*Exit:* {trade_data.get('exit_price', 'N/A')}
*Profit:* {profit_text}
*Duration:* {trade_data.get('duration_hours', 0):.1f}h
*Exit Reason:* {trade_data.get('exit_reason', 'unknown').upper()}
*R:R Ratio:* {trade_data.get('rr_ratio', 0):.2f}
⏰ {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} UTC
"""
self.send_message(message)
# ==========================================
# PERFORMANCE REPORTS
# ==========================================
def send_daily_report(self, stats: Dict):
"""
Send daily performance summary
Args:
stats: Dictionary with daily statistics
"""
win_rate = stats.get('win_rate', 0)
net_profit = stats.get('net_profit', 0)
# Emojis based on performance
profit_emoji = "💰" if net_profit > 0 else "📉"
wr_emoji = "🎯" if win_rate >= 50 else "⚠️" if win_rate >= 40 else "🔴"
message = f"""
📊 *Daily Trading Report*
📅 {datetime.now().strftime('%Y-%m-%d')}
━━━━━━━━━━━━━━━━━━━━
*Trades:* {stats.get('total_trades', 0)}
*Wins:* {stats.get('wins', 0)} | *Losses:* {stats.get('losses', 0)}
{wr_emoji} *Win Rate:* {win_rate:.1f}%
{profit_emoji} *Net Profit:* ${net_profit:.2f}
*Gross Profit:* ${stats.get('gross_profit', 0):.2f}
*Gross Loss:* ${stats.get('gross_loss', 0):.2f}
*Avg Trade:* ${stats.get('avg_trade', 0):.2f}
━━━━━━━━━━━━━━━━━━━━
✅ Bot Status: Running
"""
self.send_message(message)
def send_weekly_report(self, stats: Dict, session_perf: Dict = None):
"""
Send weekly performance summary
Args:
stats: Dictionary with weekly statistics
session_perf: Optional session performance breakdown
"""
win_rate = stats.get('win_rate', 0)
net_profit = stats.get('net_profit', 0)
profit_factor = stats.get('profit_factor', 0)
# Emojis
profit_emoji = "💰" if net_profit > 0 else "📉"
pf_emoji = "🟢" if profit_factor >= 1.5 else "🟡" if profit_factor >= 1.2 else "🔴"
message = f"""
📈 *Weekly Trading Report*
📅 {(datetime.now() - timedelta(days=7)).strftime('%Y-%m-%d')} to {datetime.now().strftime('%Y-%m-%d')}
━━━━━━━━━━━━━━━━━━━━
📊 *Overall Performance*
*Total Trades:* {stats.get('total_trades', 0)}
*Wins:* {stats.get('wins', 0)} | *Losses:* {stats.get('losses', 0)}
*Win Rate:* {win_rate:.1f}%
{profit_emoji} *Net Profit:* ${net_profit:.2f}
{pf_emoji} *Profit Factor:* {profit_factor:.2f}
*Avg Trade:* ${stats.get('avg_trade', 0):.2f}
━━━━━━━━━━━━━━━━━━━━
"""
# Add session breakdown if available
if session_perf:
message += "\n📍 *Session Performance*\n\n"
# Sort sessions by profit
sorted_sessions = sorted(
session_perf.items(),
key=lambda x: x[1].get('total_profit', 0),
reverse=True
)
for session, data in sorted_sessions:
session_emoji = self._get_session_emoji(session)
profit = data.get('total_profit', 0)
wr = data.get('win_rate', 0)
profit_text = f"+${profit:.2f}" if profit > 0 else f"${profit:.2f}"
status = "✅" if profit > 0 else "❌"
message += f"{session_emoji} *{session.upper()}:* {profit_text} ({wr:.1f}% WR) {status}\n"
message += "\n━━━━━━━━━━━━━━━━━━━━\n✅ Bot Status: Running"
self.send_message(message)
# ==========================================
# ALERTS & STATUS
# ==========================================
def send_error_alert(self, error_message: str, context: str = ""):
"""
Send error alert
Args:
error_message: Error description
context: Additional context
"""
message = f"""
🚨 *ERROR ALERT*
*Time:* {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} UTC
*Error:* {error_message}
{f'*Context:* {context}' if context else ''}
⚠️ Please check the bot!
"""
self.send_message(message)
def send_bot_started(self, config: Dict):
"""
Notify when bot starts
Args:
config: Bot configuration
"""
active_sessions = [s for s, enabled in config.get('enabled_sessions', {}).items() if enabled]
message = f"""
🚀 *TradingBot Started*
*Version:* {config.get('version', 'V1.8')}
*Time:* {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} UTC
⚙️ *Configuration:*
*Active Sessions:* {', '.join(s.upper() for s in active_sessions)}
*Confidence Threshold:* {config.get('base_confidence', 60)}%
*Max Risk/Trade:* {config.get('max_risk_per_trade', 0.01)*100:.1f}%
✅ Bot is now monitoring the market
"""
self.send_message(message)
def send_bot_stopped(self, reason: str = "Manual stop"):
"""
Notify when bot stops
Args:
reason: Stop reason
"""
message = f"""
⏸️ *TradingBot Stopped*
*Time:* {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} UTC
*Reason:* {reason}
ℹ️ Bot has stopped trading
"""
self.send_message(message)
def send_session_blocked(self, session: str, reason: str):
"""
Notify when a trading session is blocked
Args:
session: Session name
reason: Block reason
"""
session_emoji = self._get_session_emoji(session)
message = f"""
⏸️ *Trading Skipped*
{session_emoji} *Session:* {session.upper()}
*Reason:* {reason}
💡 Bot is waiting for allowed session
"""
# Only send if debug mode (optional - can be noisy)
# self.send_message(message)
# ==========================================
# BOT COMMANDS (Optional - for interactive use)
# ==========================================
def handle_command(self, command: str, db) -> str:
"""
Handle Telegram bot commands
Args:
command: Command string (e.g., '/status', '/report')
db: TradingDatabase instance
Returns:
Response message
"""
if command == '/status':
return self._cmd_status(db)
elif command == '/report':
return self._cmd_report(db)
elif command == '/today':
return self._cmd_today(db)
elif command == '/help':
return self._cmd_help()
else:
return "Unknown command. Use /help for available commands."
def _cmd_status(self, db) -> str:
"""Get bot status"""
open_positions = db.get_open_positions()
stats = db.get_overall_statistics(days=7)
return f"""
📊 *Bot Status*
*Open Positions:* {len(open_positions)}
*7-Day Win Rate:* {stats.get('win_rate', 0):.1f}%
*7-Day Profit:* ${stats.get('net_profit', 0):.2f}
✅ Bot is running
"""
def _cmd_report(self, db) -> str:
"""Get performance report"""
stats = db.get_overall_statistics(days=7)
self.send_weekly_report(stats)
return "Report sent!"
def _cmd_today(self, db) -> str:
"""Get today's summary"""
stats = db.get_daily_summary()
self.send_daily_report(stats)
return "Today's report sent!"
def _cmd_help(self) -> str:
"""Get help text"""
return """
📚 *Available Commands*
/status - Bot status & open positions
/report - Weekly performance report
/today - Today's summary
/help - Show this help
Bot will automatically send:
• Trade entry/exit notifications
• Daily reports (22:00 UTC)
• Error alerts
"""
# ==========================================
# HELPER FUNCTIONS
# ==========================================
def _get_session_emoji(self, session: str) -> str:
"""Get emoji for session"""
emojis = {
'asian': '🌙',
'london': '🇬🇧',
'overlap': '🔄',
'ny': '🇺🇸'
}
return emojis.get(session.lower(), '❓')
# ==========================================
# CONFIGURATION
# ==========================================
def load_telegram_config() -> Dict:
"""
Load Telegram configuration from file or environment
Returns:
Dictionary with bot_token and chat_id
"""
# Try to load from config file
config_file = "telegram_config.json"
if os.path.exists(config_file):
with open(config_file, 'r') as f:
return json.load(f)
# Try environment variables
bot_token = os.getenv('TELEGRAM_BOT_TOKEN')
chat_id = os.getenv('TELEGRAM_CHAT_ID')
if bot_token and chat_id:
return {
'bot_token': bot_token,
'chat_id': chat_id
}
# Return empty config if nothing found
return {}
def create_telegram_config_template():
"""Create template configuration file"""
template = {
"bot_token": "YOUR_BOT_TOKEN_HERE",
"chat_id": "YOUR_CHAT_ID_HERE",
"notifications": {
"trade_entry": True,
"trade_exit": True,
"daily_report": True,
"weekly_report": True,
"error_alerts": True
},
"daily_report_time": "22:00", # UTC
"weekly_report_day": "Sunday"
}
with open('telegram_config_template.json', 'w') as f:
json.dump(template, f, indent=2)
print("✅ Created telegram_config_template.json")
print("📝 Edit this file and rename to telegram_config.json")
# ==========================================
# USAGE EXAMPLE
# ==========================================
if __name__ == "__main__":
print("="*70)
print("📱 TELEGRAM NOTIFIER - Setup")
print("="*70)
# Create config template
create_telegram_config_template()
print("""
📋 Setup Instructions:
1. Create Telegram Bot:
- Open Telegram and search for @BotFather
- Send /newbot and follow instructions
- Copy the Bot Token
2. Get your Chat ID:
- Search for @userinfobot in Telegram
- Send /start
- Copy your User ID
3. Configure:
- Edit telegram_config_template.json
- Add your bot_token and chat_id
- Rename to telegram_config.json
4. Test:
- Run this script again to test connection
Example Usage:
```python
from telegram_notifier import TelegramNotifier
# Initialize
notifier = TelegramNotifier(
bot_token='YOUR_BOT_TOKEN',
chat_id='YOUR_CHAT_ID'
)
# Send trade notification
notifier.notify_trade_entry({
'symbol': 'XAUUSD',
'type': 'BUY',
'entry_price': 2650.00,
'sl_price': 2645.00,
'tp_price': 2660.00,
'session': 'ny',
'confidence': 75.5
})
```
""")
print("="*70)
+434
View File
@@ -0,0 +1,434 @@
[
{
"timestamp": "2025-10-31T00:43:54.044909",
"version": "V1.6_Adaptive_Complete",
"symbol": "XAUUSD",
"entry_signal": 1,
"confidence": 78.8,
"adaptive_threshold": 70,
"signal_quality": "good",
"market_regime": "ranging",
"regime_strength": 37.20677415534778,
"risk_adjusted_strength": 47620.067708887604,
"adaptive_interval": 15,
"session": "asian",
"relaxed_features": {
"pullback_entry_disabled": true,
"lower_confidence_threshold": true,
"lower_min_strength": true,
"fixed_tf_alignment": true
},
"adaptive_features": {
"adaptive_rhythm": true,
"session_aware": true,
"volatility_based": true
},
"position_control_active": true,
"order_result": "OrderSendResult(retcode=10009, deal=435070787, order=478265698, volume=0.07, price=4032.7, bid=0.0, ask=0.0, comment='Request executed', request_id=2258304401, retcode_external=0, request=TradeRequest(action=1, magic=234000, order=0, symbol='XAUUSD', volume=0.07, price=4032.81, stoplimit=0.0, sl=4025.0112621236303, tp=4051.676844690925, deviation=20, type=0, type_filling=1, type_time=0, expiration=0, comment='TradingBot_V1.6', position=0, position_by=0))"
},
{
"timestamp": "2025-10-31T02:00:00.811779",
"version": "V1.6_Adaptive_Complete",
"symbol": "XAUUSD",
"entry_signal": 1,
"confidence": 79.06,
"adaptive_threshold": 70,
"signal_quality": "good",
"market_regime": "ranging",
"regime_strength": 41.618593353525405,
"risk_adjusted_strength": 59305.554223185194,
"adaptive_interval": 15,
"session": "asian",
"relaxed_features": {
"pullback_entry_disabled": true,
"lower_confidence_threshold": true,
"lower_min_strength": true,
"fixed_tf_alignment": true
},
"adaptive_features": {
"adaptive_rhythm": true,
"session_aware": true,
"volatility_based": true
},
"position_control_active": true,
"order_result": "OrderSendResult(retcode=10009, deal=435184360, order=478391992, volume=0.09, price=4025.19, bid=0.0, ask=0.0, comment='Request executed', request_id=2258304402, retcode_external=0, request=TradeRequest(action=1, magic=234000, order=0, symbol='XAUUSD', volume=0.09, price=4025.32, stoplimit=0.0, sl=4018.93281627515, tp=4040.5879593121244, deviation=20, type=0, type_filling=1, type_time=0, expiration=0, comment='TradingBot_V1.6', position=0, position_by=0))"
},
{
"timestamp": "2025-10-31T03:00:09.446976",
"version": "V1.6_Adaptive_Complete",
"symbol": "XAUUSD",
"entry_signal": 1,
"confidence": 78.88,
"adaptive_threshold": 70,
"signal_quality": "good",
"market_regime": "ranging",
"regime_strength": 41.618593353525405,
"risk_adjusted_strength": 57477.635686851994,
"adaptive_interval": 15,
"session": "asian",
"relaxed_features": {
"pullback_entry_disabled": true,
"lower_confidence_threshold": true,
"lower_min_strength": true,
"fixed_tf_alignment": true
},
"adaptive_features": {
"adaptive_rhythm": true,
"session_aware": true,
"volatility_based": true
},
"position_control_active": true,
"order_result": "OrderSendResult(retcode=10009, deal=435297036, order=478512868, volume=0.08, price=4018.08, bid=0.0, ask=0.0, comment='Request executed', request_id=2258304403, retcode_external=0, request=TradeRequest(action=1, magic=234000, order=0, symbol='XAUUSD', volume=0.08, price=4018.54, stoplimit=0.0, sl=4011.338532716335, tp=4035.8786682091622, deviation=20, type=0, type_filling=1, type_time=0, expiration=0, comment='TradingBot_V1.6', position=0, position_by=0))"
},
{
"timestamp": "2025-10-31T03:15:02.774892",
"version": "V1.6_Adaptive_Complete",
"symbol": "XAUUSD",
"entry_signal": 1,
"confidence": 78.79,
"adaptive_threshold": 70,
"signal_quality": "good",
"market_regime": "ranging",
"regime_strength": 41.45021738059823,
"risk_adjusted_strength": 53917.67521737332,
"adaptive_interval": 15,
"session": "asian",
"relaxed_features": {
"pullback_entry_disabled": true,
"lower_confidence_threshold": true,
"lower_min_strength": true,
"fixed_tf_alignment": true
},
"adaptive_features": {
"adaptive_rhythm": true,
"session_aware": true,
"volatility_based": true
},
"position_control_active": true,
"order_result": "OrderSendResult(retcode=10009, deal=435327586, order=478545351, volume=0.07, price=4010.2, bid=0.0, ask=0.0, comment='Request executed', request_id=2258304404, retcode_external=0, request=TradeRequest(action=1, magic=234000, order=0, symbol='XAUUSD', volume=0.07, price=4009.78, stoplimit=0.0, sl=4001.7994756899197, tp=4029.066310775201, deviation=20, type=0, type_filling=1, type_time=0, expiration=0, comment='TradingBot_V1.6', position=0, position_by=0))"
},
{
"timestamp": "2025-10-31T03:45:01.683105",
"version": "V1.6_Adaptive_Complete",
"symbol": "XAUUSD",
"entry_signal": 1,
"confidence": 79.01,
"adaptive_threshold": 70,
"signal_quality": "good",
"market_regime": "ranging",
"regime_strength": 41.032624832763865,
"risk_adjusted_strength": 53691.96346378657,
"adaptive_interval": 15,
"session": "asian",
"relaxed_features": {
"pullback_entry_disabled": true,
"lower_confidence_threshold": true,
"lower_min_strength": true,
"fixed_tf_alignment": true
},
"adaptive_features": {
"adaptive_rhythm": true,
"session_aware": true,
"volatility_based": true
},
"position_control_active": true,
"order_result": "OrderSendResult(retcode=10009, deal=435380939, order=478603436, volume=0.07, price=4003.22, bid=0.0, ask=0.0, comment='Request executed', request_id=2258304405, retcode_external=0, request=TradeRequest(action=1, magic=234000, order=0, symbol='XAUUSD', volume=0.07, price=4003.27, stoplimit=0.0, sl=3995.6045659482984, tp=4021.8035851292548, deviation=20, type=0, type_filling=1, type_time=0, expiration=0, comment='TradingBot_V1.6', position=0, position_by=0))"
},
{
"timestamp": "2025-10-31T04:15:03.001188",
"version": "V1.6_Adaptive_Complete",
"symbol": "XAUUSD",
"entry_signal": 1,
"confidence": 77.88,
"adaptive_threshold": 70,
"signal_quality": "good",
"market_regime": "ranging",
"regime_strength": 40.5114037003187,
"risk_adjusted_strength": 47986.54160593859,
"adaptive_interval": 15,
"session": "asian",
"relaxed_features": {
"pullback_entry_disabled": true,
"lower_confidence_threshold": true,
"lower_min_strength": true,
"fixed_tf_alignment": true
},
"adaptive_features": {
"adaptive_rhythm": true,
"session_aware": true,
"volatility_based": true
},
"position_control_active": true,
"order_result": "OrderSendResult(retcode=10009, deal=435442265, order=478669515, volume=0.06, price=3994.46, bid=0.0, ask=0.0, comment='Request executed', request_id=2258304406, retcode_external=0, request=TradeRequest(action=1, magic=234000, order=0, symbol='XAUUSD', volume=0.06, price=3994.44, stoplimit=0.0, sl=3985.343350297011, tp=4016.551624257473, deviation=20, type=0, type_filling=1, type_time=0, expiration=0, comment='TradingBot_V1.6', position=0, position_by=0))"
},
{
"timestamp": "2025-10-31T09:30:07.126969",
"version": "V1.6_Adaptive_Complete",
"symbol": "XAUUSD",
"entry_signal": 1,
"confidence": 74.56,
"adaptive_threshold": 70,
"signal_quality": "good",
"market_regime": "ranging",
"regime_strength": 43.85449385178111,
"risk_adjusted_strength": 57906.72497045316,
"adaptive_interval": 5,
"session": "london",
"relaxed_features": {
"pullback_entry_disabled": true,
"lower_confidence_threshold": true,
"lower_min_strength": true,
"fixed_tf_alignment": true
},
"adaptive_features": {
"adaptive_rhythm": true,
"session_aware": true,
"volatility_based": true
},
"position_control_active": true,
"order_result": "OrderSendResult(retcode=10009, deal=435954475, order=479237652, volume=0.09, price=4021.64, bid=0.0, ask=0.0, comment='Request executed', request_id=2258304407, retcode_external=0, request=TradeRequest(action=1, magic=234000, order=0, symbol='XAUUSD', volume=0.09, price=4021.64, stoplimit=0.0, sl=4015.2733652001793, tp=4036.891586999551, deviation=20, type=0, type_filling=1, type_time=0, expiration=0, comment='TradingBot_V1.6', position=0, position_by=0))"
},
{
"timestamp": "2025-10-31T09:55:08.099010",
"version": "V1.6_Adaptive_Complete",
"symbol": "XAUUSD",
"entry_signal": 1,
"confidence": 75.03,
"adaptive_threshold": 70,
"signal_quality": "good",
"market_regime": "ranging",
"regime_strength": 43.85449385178111,
"risk_adjusted_strength": 55011.82846332111,
"adaptive_interval": 5,
"session": "london",
"relaxed_features": {
"pullback_entry_disabled": true,
"lower_confidence_threshold": true,
"lower_min_strength": true,
"fixed_tf_alignment": true
},
"adaptive_features": {
"adaptive_rhythm": true,
"session_aware": true,
"volatility_based": true
},
"position_control_active": true,
"order_result": "OrderSendResult(retcode=10009, deal=436007194, order=479294203, volume=0.08, price=4007.97, bid=0.0, ask=0.0, comment='Request executed', request_id=2258304408, retcode_external=0, request=TradeRequest(action=1, magic=234000, order=0, symbol='XAUUSD', volume=0.08, price=4007.98, stoplimit=0.0, sl=4001.0490658068666, tp=4024.6423354828335, deviation=20, type=0, type_filling=1, type_time=0, expiration=0, comment='TradingBot_V1.6', position=0, position_by=0))"
},
{
"timestamp": "2025-10-31T10:25:03.665172",
"version": "V1.6_Adaptive_Complete",
"symbol": "XAUUSD",
"entry_signal": 1,
"confidence": 74.87,
"adaptive_threshold": 70,
"signal_quality": "good",
"market_regime": "ranging",
"regime_strength": 49.645629122983934,
"risk_adjusted_strength": 55765.179992689635,
"adaptive_interval": 5,
"session": "london",
"relaxed_features": {
"pullback_entry_disabled": true,
"lower_confidence_threshold": true,
"lower_min_strength": true,
"fixed_tf_alignment": true
},
"adaptive_features": {
"adaptive_rhythm": true,
"session_aware": true,
"volatility_based": true
},
"position_control_active": true,
"order_result": "OrderSendResult(retcode=10009, deal=436077538, order=479369590, volume=0.08, price=4002.99, bid=0.0, ask=0.0, comment='Request executed', request_id=2258304409, retcode_external=0, request=TradeRequest(action=1, magic=234000, order=0, symbol='XAUUSD', volume=0.08, price=4002.95, stoplimit=0.0, sl=3996.285330737533, tp=4018.981673156167, deviation=20, type=0, type_filling=1, type_time=0, expiration=0, comment='TradingBot_V1.6', position=0, position_by=0))"
},
{
"timestamp": "2025-10-31T13:25:09.566295",
"version": "V1.6_Adaptive_Complete",
"symbol": "XAUUSD",
"entry_signal": 1,
"confidence": 76.38,
"adaptive_threshold": 70,
"signal_quality": "good",
"market_regime": "ranging",
"regime_strength": 49.645629122983934,
"risk_adjusted_strength": 61390.996940352314,
"adaptive_interval": 5,
"session": "london",
"relaxed_features": {
"pullback_entry_disabled": true,
"lower_confidence_threshold": true,
"lower_min_strength": true,
"fixed_tf_alignment": true
},
"adaptive_features": {
"adaptive_rhythm": true,
"session_aware": true,
"volatility_based": true
},
"position_control_active": true,
"order_result": "OrderSendResult(retcode=10009, deal=436431428, order=479741402, volume=0.1, price=4024.85, bid=0.0, ask=0.0, comment='Request executed', request_id=2258304412, retcode_external=0, request=TradeRequest(action=1, magic=234000, order=0, symbol='XAUUSD', volume=0.1, price=4024.84, stoplimit=0.0, sl=4019.39135552923, tp=4038.0066111769247, deviation=20, type=0, type_filling=1, type_time=0, expiration=0, comment='TradingBot_V1.6', position=0, position_by=0))"
},
{
"timestamp": "2025-10-31T13:35:04.695750",
"version": "V1.6_Adaptive_Complete",
"symbol": "XAUUSD",
"entry_signal": 1,
"confidence": 76.87,
"adaptive_threshold": 70,
"signal_quality": "good",
"market_regime": "ranging",
"regime_strength": 49.645629122983934,
"risk_adjusted_strength": 63095.103958100415,
"adaptive_interval": 5,
"session": "london",
"relaxed_features": {
"pullback_entry_disabled": true,
"lower_confidence_threshold": true,
"lower_min_strength": true,
"fixed_tf_alignment": true
},
"adaptive_features": {
"adaptive_rhythm": true,
"session_aware": true,
"volatility_based": true
},
"position_control_active": true,
"order_result": "OrderSendResult(retcode=10009, deal=436458488, order=479770105, volume=0.09, price=4018.09, bid=0.0, ask=0.0, comment='Request executed', request_id=2258304413, retcode_external=0, request=TradeRequest(action=1, magic=234000, order=0, symbol='XAUUSD', volume=0.09, price=4018.2, stoplimit=0.0, sl=4012.2888857464714, tp=4032.347785633822, deviation=20, type=0, type_filling=1, type_time=0, expiration=0, comment='TradingBot_V1.6', position=0, position_by=0))"
},
{
"timestamp": "2025-10-31T13:45:08.946579",
"version": "V1.6_Adaptive_Complete",
"symbol": "XAUUSD",
"entry_signal": 1,
"confidence": 77.54,
"adaptive_threshold": 70,
"signal_quality": "good",
"market_regime": "ranging",
"regime_strength": 50.1048143639056,
"risk_adjusted_strength": 60070.495350632635,
"adaptive_interval": 5,
"session": "london",
"relaxed_features": {
"pullback_entry_disabled": true,
"lower_confidence_threshold": true,
"lower_min_strength": true,
"fixed_tf_alignment": true
},
"adaptive_features": {
"adaptive_rhythm": true,
"session_aware": true,
"volatility_based": true
},
"position_control_active": true,
"order_result": "OrderSendResult(retcode=10009, deal=436498442, order=479811302, volume=0.09, price=4029.77, bid=0.0, ask=0.0, comment='Request executed', request_id=2258304415, retcode_external=0, request=TradeRequest(action=1, magic=234000, order=0, symbol='XAUUSD', volume=0.09, price=4029.77, stoplimit=0.0, sl=4022.964230861388, tp=4046.11942284653, deviation=20, type=0, type_filling=1, type_time=0, expiration=0, comment='TradingBot_V1.6', position=0, position_by=0))"
},
{
"timestamp": "2025-10-31T14:00:07.002828",
"version": "V1.6_Adaptive_Complete",
"symbol": "XAUUSD",
"entry_signal": 1,
"confidence": 78.19,
"adaptive_threshold": 70,
"signal_quality": "good",
"market_regime": "ranging",
"regime_strength": 50.31329270330242,
"risk_adjusted_strength": 58987.81185063584,
"adaptive_interval": 5,
"session": "overlap",
"relaxed_features": {
"pullback_entry_disabled": true,
"lower_confidence_threshold": true,
"lower_min_strength": true,
"fixed_tf_alignment": true
},
"adaptive_features": {
"adaptive_rhythm": true,
"session_aware": true,
"volatility_based": true
},
"position_control_active": true,
"order_result": "OrderSendResult(retcode=10009, deal=436546489, order=479862422, volume=0.08, price=4022.61, bid=0.0, ask=0.0, comment='Request executed', request_id=2258304416, retcode_external=0, request=TradeRequest(action=1, magic=234000, order=0, symbol='XAUUSD', volume=0.08, price=4023.26, stoplimit=0.0, sl=4015.987346052467, tp=4040.811634868833, deviation=20, type=0, type_filling=1, type_time=0, expiration=0, comment='TradingBot_V1.6', position=0, position_by=0))"
},
{
"timestamp": "2025-10-31T14:45:00.935511",
"version": "V1.6_Adaptive_Complete",
"symbol": "XAUUSD",
"entry_signal": 1,
"confidence": 79.08,
"adaptive_threshold": 70,
"signal_quality": "good",
"market_regime": "ranging",
"regime_strength": 54.46759901144059,
"risk_adjusted_strength": 61375.73055368705,
"adaptive_interval": 5,
"session": "overlap",
"relaxed_features": {
"pullback_entry_disabled": true,
"lower_confidence_threshold": true,
"lower_min_strength": true,
"fixed_tf_alignment": true
},
"adaptive_features": {
"adaptive_rhythm": true,
"session_aware": true,
"volatility_based": true
},
"position_control_active": true,
"order_result": "OrderSendResult(retcode=10009, deal=436672932, order=479998013, volume=0.07, price=4016.02, bid=0.0, ask=0.0, comment='Request executed', request_id=2258304417, retcode_external=0, request=TradeRequest(action=1, magic=234000, order=0, symbol='XAUUSD', volume=0.07, price=4016.14, stoplimit=0.0, sl=4008.59042168871, tp=4034.3839457782246, deviation=20, type=0, type_filling=1, type_time=0, expiration=0, comment='TradingBot_V1.6', position=0, position_by=0))"
},
{
"timestamp": "2025-10-31T17:05:00.448576",
"version": "V1.6_Adaptive_Complete",
"symbol": "XAUUSD",
"entry_signal": 1,
"confidence": 78.3,
"adaptive_threshold": 70,
"signal_quality": "good",
"market_regime": "ranging",
"regime_strength": 54.46759901144059,
"risk_adjusted_strength": 58060.1480517347,
"adaptive_interval": 5,
"session": "ny",
"relaxed_features": {
"pullback_entry_disabled": true,
"lower_confidence_threshold": true,
"lower_min_strength": true,
"fixed_tf_alignment": true
},
"adaptive_features": {
"adaptive_rhythm": true,
"session_aware": true,
"volatility_based": true
},
"position_control_active": true,
"order_result": "OrderSendResult(retcode=10009, deal=437021574, order=480364066, volume=0.07, price=4005.6, bid=0.0, ask=0.0, comment='Request executed', request_id=2258304418, retcode_external=0, request=TradeRequest(action=1, magic=234000, order=0, symbol='XAUUSD', volume=0.07, price=4005.72, stoplimit=0.0, sl=3997.1606557485698, tp=4026.4533606285763, deviation=20, type=0, type_filling=1, type_time=0, expiration=0, comment='TradingBot_V1.6', position=0, position_by=0))"
},
{
"timestamp": "2025-10-31T17:15:00.366177",
"version": "V1.6_Adaptive_Complete",
"symbol": "XAUUSD",
"entry_signal": 1,
"confidence": 78.66,
"adaptive_threshold": 70,
"signal_quality": "good",
"market_regime": "ranging",
"regime_strength": 53.312778054728234,
"risk_adjusted_strength": 52154.36881322381,
"adaptive_interval": 5,
"session": "ny",
"relaxed_features": {
"pullback_entry_disabled": true,
"lower_confidence_threshold": true,
"lower_min_strength": true,
"fixed_tf_alignment": true
},
"adaptive_features": {
"adaptive_rhythm": true,
"session_aware": true,
"volatility_based": true
},
"position_control_active": true,
"order_result": "OrderSendResult(retcode=10009, deal=437066084, order=480409859, volume=0.05, price=3979.04, bid=0.0, ask=0.0, comment='Request executed', request_id=2258304419, retcode_external=0, request=TradeRequest(action=1, magic=234000, order=0, symbol='XAUUSD', volume=0.05, price=3979.26, stoplimit=0.0, sl=3969.2344213705546, tp=4003.6589465736133, deviation=20, type=0, type_filling=1, type_time=0, expiration=0, comment='TradingBot_V1.6', position=0, position_by=0))"
}
]
File diff suppressed because it is too large. Load diff
+418
View File
@@ -0,0 +1,418 @@
#!/usr/bin/env python3
"""
📊 Trading Bot Dashboard - Streamlit
Real-time monitoring für V1.8 Trading Bot
"""
import streamlit as st
import sqlite3
import pandas as pd
from datetime import datetime, timedelta
import plotly.express as px
import plotly.graph_objects as go
# ==========================================
# PAGE CONFIG
# ==========================================
st.set_page_config(
page_title="Trading Bot Dashboard",
page_icon="📊",
layout="wide"
)
# ==========================================
# DATABASE CONNECTION
# ==========================================
@st.cache_resource
def get_connection():
return sqlite3.connect("trading_bot.db", check_same_thread=False)
conn = get_connection()
# ==========================================
# HEADER
# ==========================================
st.title("📊 Trading Bot Dashboard V1.8")
st.markdown("---")
# Refresh button
col1, col2, col3 = st.columns([1, 1, 4])
with col1:
if st.button("🔄 Refresh Data"):
st.cache_data.clear()
st.experimental_rerun()
with col2:
auto_refresh = st.checkbox("Auto-refresh (30s)")
if auto_refresh:
st.markdown("*Auto-refreshing every 30 seconds...*")
import time
time.sleep(30)
st.experimental_rerun()
# ==========================================
# LOAD DATA
# ==========================================
@st.cache_data(ttl=30)
def load_all_trades():
query = """
SELECT
ticket,
position_id,
symbol,
strategy_name,
type,
volume,
entry_price,
sl_price,
tp_price,
entry_time,
exit_time,
session,
regime,
quality,
confidence,
timeframe_alignment,
risk_amount,
risk_pct,
net_profit,
profit_pct,
rr_ratio,
status,
exit_reason
FROM trades
ORDER BY entry_time DESC
"""
return pd.read_sql_query(query, conn)
@st.cache_data(ttl=30)
def load_bot_status():
query = "SELECT * FROM bot_status ORDER BY timestamp DESC LIMIT 1"
return pd.read_sql_query(query, conn)
# Load data
df_trades = load_all_trades()
df_status = load_bot_status()
# ==========================================
# TOP METRICS
# ==========================================
st.subheader("📈 Key Metrics")
col1, col2, col3, col4, col5 = st.columns(5)
total_trades = len(df_trades)
closed_trades = len(df_trades[df_trades['status'] == 'closed'])
open_trades = len(df_trades[df_trades['status'] == 'open'])
if closed_trades > 0:
winning_trades = len(df_trades[(df_trades['status'] == 'closed') & (df_trades['net_profit'] > 0)])
win_rate = (winning_trades / closed_trades) * 100
total_profit = df_trades[df_trades['status'] == 'closed']['net_profit'].sum()
else:
win_rate = 0
total_profit = 0
with col1:
st.metric("Total Trades", total_trades)
with col2:
st.metric("Open Positions", open_trades)
with col3:
st.metric("Win Rate", f"{win_rate:.1f}%")
with col4:
profit_color = "normal" if total_profit >= 0 else "inverse"
st.metric("Total Profit", f"${total_profit:.2f}", delta=None)
with col5:
if closed_trades > 0:
avg_profit = total_profit / closed_trades
st.metric("Avg Profit/Trade", f"${avg_profit:.2f}")
else:
st.metric("Avg Profit/Trade", "N/A")
st.markdown("---")
# ==========================================
# SESSION FILTER CHECK
# ==========================================
st.subheader("🎯 Session Filter Status")
# Calculate session distribution
session_counts = df_trades['session'].value_counts()
col1, col2 = st.columns([1, 2])
with col1:
st.markdown("#### Session Distribution")
for session in ['ny', 'london', 'asian', 'overlap']:
count = session_counts.get(session, 0)
pct = (count / total_trades * 100) if total_trades > 0 else 0
if session == 'ny':
if count == total_trades:
st.success(f"✅ NY: {count} ({pct:.1f}%) - PERFECT!")
else:
st.warning(f"⚠️ NY: {count} ({pct:.1f}%)")
else:
if count > 0:
st.error(f"❌ {session.upper()}: {count} ({pct:.1f}%) - VIOLATION!")
else:
st.success(f"✅ {session.upper()}: {count} (0%) - Blocked")
with col2:
st.markdown("#### Verdict")
ny_count = session_counts.get('ny', 0)
violation_count = total_trades - ny_count
if total_trades == 0:
st.info("ℹ️ No trades yet - waiting for data...")
elif violation_count == 0:
st.success("✅ **SESSION FILTER WORKING PERFECTLY!**")
st.markdown("All trades are in NY session (13:00-21:00 UTC)")
else:
st.error(f"❌ **SESSION FILTER NOT WORKING!**")
st.markdown(f"**{violation_count} trades** ({violation_count/total_trades*100:.1f}%) outside NY session!")
st.markdown("**Action Required:** See FIX_DUPLICATE_SCHEDULER.md")
st.markdown("---")
# ==========================================
# HOURLY DISTRIBUTION
# ==========================================
st.subheader("⏰ Trades by Hour (UTC)")
if not df_trades.empty:
# Extract hour from entry_time
df_trades['hour_utc'] = pd.to_datetime(df_trades['entry_time']).dt.hour
# Count trades by hour
hourly_dist = df_trades.groupby('hour_utc').size().reset_index(name='count')
# Create visualization
fig = go.Figure()
# Add bars
colors = ['red' if (h < 13 or h >= 21) else 'green' for h in hourly_dist['hour_utc']]
fig.add_trace(go.Bar(
x=hourly_dist['hour_utc'],
y=hourly_dist['count'],
marker_color=colors,
text=hourly_dist['count'],
textposition='outside'
))
# Add NY session marker
fig.add_vrect(x0=13, x1=21, fillcolor="green", opacity=0.1, layer="below", line_width=0)
fig.add_annotation(x=17, y=hourly_dist['count'].max(), text="NY Session (13-21 UTC)", showarrow=False)
fig.update_layout(
xaxis_title="Hour (UTC)",
yaxis_title="Number of Trades",
height=400,
showlegend=False,
xaxis=dict(dtick=1, range=[-0.5, 23.5])
)
st.plotly_chart(fig, use_container_width=True)
# Check for violations
violations = df_trades[(df_trades['hour_utc'] < 13) | (df_trades['hour_utc'] >= 21)]
if not violations.empty:
st.error(f"⚠️ **{len(violations)} trades outside NY hours detected!**")
with st.expander("Show violation details"):
st.dataframe(violations[['ticket', 'session', 'entry_time', 'hour_utc', 'type', 'net_profit']])
else:
st.info("No trades to display")
st.markdown("---")
# ==========================================
# SESSION PERFORMANCE
# ==========================================
st.subheader("📊 Performance by Session")
if closed_trades > 0:
session_perf = df_trades[df_trades['status'] == 'closed'].groupby('session').agg({
'ticket': 'count',
'net_profit': ['sum', 'mean']
}).round(2)
session_perf.columns = ['Trades', 'Total Profit', 'Avg Profit']
# Calculate win rate per session
win_rates = []
for session in session_perf.index:
session_trades = df_trades[(df_trades['status'] == 'closed') & (df_trades['session'] == session)]
wins = len(session_trades[session_trades['net_profit'] > 0])
wr = (wins / len(session_trades) * 100) if len(session_trades) > 0 else 0
win_rates.append(wr)
session_perf['Win Rate %'] = win_rates
# Color code
def color_sessions(row):
if row.name == 'ny':
return ['background-color: #90EE90'] * len(row) # Light green
else:
return ['background-color: #FFB6C6'] * len(row) # Light red
st.dataframe(session_perf.style.apply(color_sessions, axis=1), use_container_width=True)
else:
st.info("No closed trades yet")
st.markdown("---")
# ==========================================
# RECENT TRADES
# ==========================================
st.subheader("📋 Recent Trades (Last 20)")
if not df_trades.empty:
recent = df_trades.head(20).copy()
# Color code session
def highlight_session(row):
if row['session'] == 'ny':
return ['background-color: #90EE90'] * len(row)
else:
return ['background-color: #FFB6C6'] * len(row)
# Select columns
display_cols = ['ticket', 'type', 'session', 'entry_time', 'confidence', 'quality', 'regime', 'status', 'net_profit']
recent_display = recent[display_cols]
st.dataframe(
recent_display.style.apply(highlight_session, axis=1),
use_container_width=True,
height=400
)
else:
st.info("No trades yet")
st.markdown("---")
# ==========================================
# PROFIT OVER TIME
# ==========================================
st.subheader("💰 Cumulative Profit Over Time")
if closed_trades > 0:
profit_timeline = df_trades[df_trades['status'] == 'closed'].copy()
profit_timeline['exit_time'] = pd.to_datetime(profit_timeline['exit_time'])
profit_timeline = profit_timeline.sort_values('exit_time')
profit_timeline['cumulative_profit'] = profit_timeline['net_profit'].cumsum()
fig = px.line(
profit_timeline,
x='exit_time',
y='cumulative_profit',
title='Cumulative Profit',
labels={'exit_time': 'Date', 'cumulative_profit': 'Profit ($)'}
)
fig.update_traces(line_color='green' if profit_timeline['cumulative_profit'].iloc[-1] > 0 else 'red')
fig.add_hline(y=0, line_dash="dash", line_color="gray")
st.plotly_chart(fig, use_container_width=True)
else:
st.info("No closed trades yet")
st.markdown("---")
# ==========================================
# CONFIDENCE & QUALITY ANALYSIS
# ==========================================
st.subheader("🎯 Signal Quality Analysis")
col1, col2 = st.columns(2)
with col1:
st.markdown("#### Confidence Distribution")
if not df_trades.empty:
fig = px.histogram(
df_trades,
x='confidence',
nbins=20,
title='Trade Confidence Distribution'
)
st.plotly_chart(fig, use_container_width=True)
else:
st.info("No data")
with col2:
st.markdown("#### Quality Breakdown")
if not df_trades.empty:
quality_counts = df_trades['quality'].value_counts()
fig = px.pie(
values=quality_counts.values,
names=quality_counts.index,
title='Signal Quality Distribution'
)
st.plotly_chart(fig, use_container_width=True)
else:
st.info("No data")
st.markdown("---")
# ==========================================
# BOT STATUS
# ==========================================
st.subheader("🤖 Bot Status")
if not df_status.empty:
status = df_status.iloc[0]
col1, col2, col3 = st.columns(3)
with col1:
st.markdown("**Version:**")
st.code(status.get('version', 'N/A'))
with col2:
st.markdown("**Status:**")
bot_status = status.get('status', 'unknown')
if bot_status == 'running':
st.success("🟢 Running")
elif bot_status == 'stopped':
st.error("🔴 Stopped")
else:
st.warning("⚠️ Unknown")
with col3:
st.markdown("**Last Update:**")
st.code(status.get('timestamp', 'N/A'))
if 'config' in status and status['config']:
with st.expander("Show Configuration"):
st.json(status['config'])
else:
st.warning("No bot status available")
st.markdown("---")
# ==========================================
# FOOTER
# ==========================================
st.markdown("---")
st.caption(f"Dashboard last updated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
st.caption("📊 Trading Bot V1.8 - Aggressive Mode (NY Only)")
+630
View File
@@ -0,0 +1,630 @@
"""
🗄️ TRADING DATABASE MODULE - SQLite Integration
Ersetzt JSON Logging mit strukturierter Datenbank
FEATURES:
- Trade History Tracking
- Performance Analytics
- Session-based Queries
- Confidence-based Analysis
- Easy Migration von JSON
"""
import sqlite3
import json
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Tuple
import os
class TradingDatabase:
"""
SQLite Database für Trading Bot Performance Tracking
"""
def __init__(self, db_path: str = "trading_bot.db"):
"""
Initialize Database Connection
Args:
db_path: Path to SQLite database file
"""
self.db_path = db_path
self.conn = None
self.cursor = None
self._connect()
self._create_tables()
def _connect(self):
"""Establish database connection"""
self.conn = sqlite3.connect(self.db_path, check_same_thread=False)
self.conn.row_factory = sqlite3.Row # Enable column access by name
self.cursor = self.conn.cursor()
def _create_tables(self):
"""Create all necessary tables"""
# Trades Table - Main trade history
self.cursor.execute("""
CREATE TABLE IF NOT EXISTS trades (
id INTEGER PRIMARY KEY AUTOINCREMENT,
ticket INTEGER UNIQUE,
position_id INTEGER,
symbol TEXT NOT NULL,
strategy_name TEXT NOT NULL,
-- Trade Details
type TEXT NOT NULL, -- 'BUY' or 'SELL'
volume REAL NOT NULL,
entry_price REAL NOT NULL,
exit_price REAL,
-- Stops
sl_price REAL,
tp_price REAL,
-- Timing
entry_time DATETIME NOT NULL,
exit_time DATETIME,
duration_hours REAL,
-- Session Info
session TEXT NOT NULL, -- 'asian', 'london', 'overlap', 'ny'
regime TEXT, -- 'trending', 'ranging'
quality TEXT, -- 'excellent', 'good', 'medium', 'poor'
-- Signal Quality
confidence REAL,
timeframe_alignment INTEGER, -- How many timeframes aligned
-- Performance
profit REAL,
commission REAL DEFAULT 0,
swap REAL DEFAULT 0,
net_profit REAL,
profit_pct REAL,
-- Risk Management
risk_amount REAL,
risk_pct REAL,
rr_ratio REAL, -- Risk/Reward ratio
-- Status
status TEXT DEFAULT 'open', -- 'open', 'closed', 'cancelled'
exit_reason TEXT, -- 'tp', 'sl', 'manual', 'timeout'
-- Metadata
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
""")
# Performance Summary Table - Daily/Weekly aggregates
self.cursor.execute("""
CREATE TABLE IF NOT EXISTS performance_summary (
id INTEGER PRIMARY KEY AUTOINCREMENT,
date DATE NOT NULL UNIQUE,
-- Trade Counts
total_trades INTEGER DEFAULT 0,
wins INTEGER DEFAULT 0,
losses INTEGER DEFAULT 0,
win_rate REAL DEFAULT 0,
-- Profit
gross_profit REAL DEFAULT 0,
gross_loss REAL DEFAULT 0,
net_profit REAL DEFAULT 0,
profit_factor REAL DEFAULT 0,
-- Session Breakdown
asian_trades INTEGER DEFAULT 0,
london_trades INTEGER DEFAULT 0,
overlap_trades INTEGER DEFAULT 0,
ny_trades INTEGER DEFAULT 0,
asian_profit REAL DEFAULT 0,
london_profit REAL DEFAULT 0,
overlap_profit REAL DEFAULT 0,
ny_profit REAL DEFAULT 0,
-- Risk Metrics
max_drawdown REAL DEFAULT 0,
avg_trade REAL DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
""")
# Bot Status Table - Health monitoring
self.cursor.execute("""
CREATE TABLE IF NOT EXISTS bot_status (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
status TEXT NOT NULL, -- 'running', 'stopped', 'error'
version TEXT,
active_sessions TEXT, -- JSON array of enabled sessions
confidence_threshold REAL,
-- Health Metrics
uptime_hours REAL,
last_trade_time DATETIME,
total_positions INTEGER DEFAULT 0,
error_message TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
""")
# Create indexes for common queries
self.cursor.execute("""
CREATE INDEX IF NOT EXISTS idx_trades_entry_time
ON trades(entry_time)
""")
self.cursor.execute("""
CREATE INDEX IF NOT EXISTS idx_trades_session
ON trades(session)
""")
self.cursor.execute("""
CREATE INDEX IF NOT EXISTS idx_trades_status
ON trades(status)
""")
self.cursor.execute("""
CREATE INDEX IF NOT EXISTS idx_trades_confidence
ON trades(confidence)
""")
self.conn.commit()
# ==========================================
# INSERT OPERATIONS
# ==========================================
def log_trade_entry(self, trade_data: Dict) -> int:
"""
Log a new trade entry
Args:
trade_data: Dictionary with trade information
Returns:
trade_id: Database ID of inserted trade
"""
query = """
INSERT INTO trades (
ticket, position_id, symbol, strategy_name,
type, volume, entry_price, sl_price, tp_price,
entry_time, session, regime, quality,
confidence, timeframe_alignment,
risk_amount, risk_pct,
status
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
"""
values = (
trade_data.get('ticket'),
trade_data.get('position_id'),
trade_data.get('symbol'),
trade_data.get('strategy_name'),
trade_data.get('type'),
trade_data.get('volume'),
trade_data.get('entry_price'),
trade_data.get('sl_price'),
trade_data.get('tp_price'),
trade_data.get('entry_time'),
trade_data.get('session'),
trade_data.get('regime'),
trade_data.get('quality'),
trade_data.get('confidence'),
trade_data.get('timeframe_alignment'),
trade_data.get('risk_amount'),
trade_data.get('risk_pct'),
'open'
)
self.cursor.execute(query, values)
self.conn.commit()
return self.cursor.lastrowid
def update_trade_exit(self, ticket: int, exit_data: Dict):
"""
Update trade with exit information
Args:
ticket: MT5 ticket number
exit_data: Dictionary with exit information
"""
query = """
UPDATE trades SET
exit_price = ?,
exit_time = ?,
duration_hours = ?,
profit = ?,
commission = ?,
swap = ?,
net_profit = ?,
profit_pct = ?,
rr_ratio = ?,
status = 'closed',
exit_reason = ?,
updated_at = CURRENT_TIMESTAMP
WHERE ticket = ?
"""
values = (
exit_data.get('exit_price'),
exit_data.get('exit_time'),
exit_data.get('duration_hours'),
exit_data.get('profit'),
exit_data.get('commission', 0),
exit_data.get('swap', 0),
exit_data.get('net_profit'),
exit_data.get('profit_pct'),
exit_data.get('rr_ratio'),
exit_data.get('exit_reason'),
ticket
)
self.cursor.execute(query, values)
self.conn.commit()
def log_bot_status(self, status_data: Dict):
"""
Log bot status for health monitoring
Args:
status_data: Dictionary with bot status information
"""
query = """
INSERT INTO bot_status (
status, version, active_sessions, confidence_threshold,
uptime_hours, last_trade_time, total_positions, error_message
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
"""
values = (
status_data.get('status', 'running'),
status_data.get('version'),
json.dumps(status_data.get('active_sessions', [])),
status_data.get('confidence_threshold'),
status_data.get('uptime_hours'),
status_data.get('last_trade_time'),
status_data.get('total_positions', 0),
status_data.get('error_message')
)
self.cursor.execute(query, values)
self.conn.commit()
# ==========================================
# QUERY OPERATIONS
# ==========================================
def get_recent_trades(self, limit: int = 50) -> List[Dict]:
"""Get most recent trades"""
query = """
SELECT * FROM trades
ORDER BY entry_time DESC
LIMIT ?
"""
self.cursor.execute(query, (limit,))
return [dict(row) for row in self.cursor.fetchall()]
def get_open_positions(self) -> List[Dict]:
"""Get all currently open positions"""
query = """
SELECT * FROM trades
WHERE status = 'open'
ORDER BY entry_time DESC
"""
self.cursor.execute(query)
return [dict(row) for row in self.cursor.fetchall()]
def get_session_performance(self, days: int = 30) -> Dict:
"""
Get performance breakdown by session
Args:
days: Number of days to analyze
Returns:
Dictionary with session statistics
"""
query = """
SELECT
session,
COUNT(*) as trade_count,
SUM(CASE WHEN net_profit > 0 THEN 1 ELSE 0 END) as wins,
SUM(CASE WHEN net_profit < 0 THEN 1 ELSE 0 END) as losses,
ROUND(AVG(CASE WHEN net_profit > 0 THEN 1.0 ELSE 0.0 END) * 100, 2) as win_rate,
ROUND(SUM(net_profit), 2) as total_profit,
ROUND(AVG(net_profit), 2) as avg_profit
FROM trades
WHERE status = 'closed'
AND entry_time >= datetime('now', '-' || ? || ' days')
GROUP BY session
ORDER BY total_profit DESC
"""
self.cursor.execute(query, (days,))
results = {}
for row in self.cursor.fetchall():
results[row['session']] = {
'count': row['trade_count'],
'wins': row['wins'],
'losses': row['losses'],
'win_rate': row['win_rate'],
'total_profit': row['total_profit'],
'avg_profit': row['avg_profit']
}
return results
def get_confidence_analysis(self, days: int = 30) -> Dict:
"""
Analyze performance by confidence levels
Args:
days: Number of days to analyze
Returns:
Dictionary with confidence-based statistics
"""
query = """
SELECT
CASE
WHEN confidence >= 80 THEN '80-100'
WHEN confidence >= 70 THEN '70-79'
WHEN confidence >= 60 THEN '60-69'
ELSE '<60'
END as confidence_range,
COUNT(*) as trade_count,
SUM(CASE WHEN net_profit > 0 THEN 1 ELSE 0 END) as wins,
ROUND(AVG(CASE WHEN net_profit > 0 THEN 1.0 ELSE 0.0 END) * 100, 2) as win_rate,
ROUND(SUM(net_profit), 2) as total_profit,
ROUND(AVG(net_profit), 2) as avg_profit
FROM trades
WHERE status = 'closed'
AND confidence IS NOT NULL
AND entry_time >= datetime('now', '-' || ? || ' days')
GROUP BY confidence_range
ORDER BY confidence_range DESC
"""
self.cursor.execute(query, (days,))
results = {}
for row in self.cursor.fetchall():
results[row['confidence_range']] = {
'count': row['trade_count'],
'wins': row['wins'],
'win_rate': row['win_rate'],
'total_profit': row['total_profit'],
'avg_profit': row['avg_profit']
}
return results
def get_daily_summary(self, date: str = None) -> Dict:
"""
Get daily performance summary
Args:
date: Date string (YYYY-MM-DD), defaults to today
Returns:
Dictionary with daily statistics
"""
if date is None:
date = datetime.now().strftime('%Y-%m-%d')
query = """
SELECT
COUNT(*) as total_trades,
SUM(CASE WHEN net_profit > 0 THEN 1 ELSE 0 END) as wins,
SUM(CASE WHEN net_profit < 0 THEN 1 ELSE 0 END) as losses,
ROUND(AVG(CASE WHEN net_profit > 0 THEN 1.0 ELSE 0.0 END) * 100, 2) as win_rate,
ROUND(SUM(CASE WHEN net_profit > 0 THEN net_profit ELSE 0 END), 2) as gross_profit,
ROUND(SUM(CASE WHEN net_profit < 0 THEN net_profit ELSE 0 END), 2) as gross_loss,
ROUND(SUM(net_profit), 2) as net_profit,
ROUND(AVG(net_profit), 2) as avg_trade
FROM trades
WHERE status = 'closed'
AND DATE(entry_time) = ?
"""
self.cursor.execute(query, (date,))
row = self.cursor.fetchone()
if row and row['total_trades'] > 0:
return dict(row)
else:
return {
'total_trades': 0,
'wins': 0,
'losses': 0,
'win_rate': 0,
'gross_profit': 0,
'gross_loss': 0,
'net_profit': 0,
'avg_trade': 0
}
def get_overall_statistics(self, days: int = None) -> Dict:
"""
Get overall performance statistics
Args:
days: Number of days to analyze (None = all time)
Returns:
Dictionary with comprehensive statistics
"""
date_filter = ""
params = []
if days:
date_filter = "AND entry_time >= datetime('now', '-' || ? || ' days')"
params.append(days)
query = f"""
SELECT
COUNT(*) as total_trades,
SUM(CASE WHEN net_profit > 0 THEN 1 ELSE 0 END) as wins,
SUM(CASE WHEN net_profit < 0 THEN 1 ELSE 0 END) as losses,
ROUND(AVG(CASE WHEN net_profit > 0 THEN 1.0 ELSE 0.0 END) * 100, 2) as win_rate,
ROUND(SUM(CASE WHEN net_profit > 0 THEN net_profit ELSE 0 END), 2) as gross_profit,
ROUND(SUM(CASE WHEN net_profit < 0 THEN net_profit ELSE 0 END), 2) as gross_loss,
ROUND(SUM(net_profit), 2) as net_profit,
ROUND(AVG(net_profit), 2) as avg_trade,
ROUND(SUM(commission), 2) as total_commission,
ROUND(SUM(swap), 2) as total_swap,
ROUND(AVG(confidence), 2) as avg_confidence,
ROUND(AVG(duration_hours), 2) as avg_duration
FROM trades
WHERE status = 'closed'
{date_filter}
"""
self.cursor.execute(query, params)
row = self.cursor.fetchone()
stats = dict(row) if row else {}
# Calculate profit factor
gross_profit = stats.get('gross_profit') or 0
gross_loss = stats.get('gross_loss') or 0
if gross_loss != 0:
stats['profit_factor'] = round(
abs(gross_profit / gross_loss),
2
)
else:
stats['profit_factor'] = 0
return stats
# ==========================================
# UTILITY FUNCTIONS
# ==========================================
def migrate_from_json(self, json_file: str):
"""
Migrate existing JSON trade data to SQLite
Args:
json_file: Path to JSON performance file
"""
if not os.path.exists(json_file):
print(f"❌ JSON file not found: {json_file}")
return
with open(json_file, 'r') as f:
data = json.load(f)
# Extract trades from JSON structure
trades = data.get('trades', [])
migrated = 0
skipped = 0
for trade in trades:
try:
# Check if trade already exists
self.cursor.execute(
"SELECT id FROM trades WHERE ticket = ?",
(trade.get('ticket'),)
)
if self.cursor.fetchone():
skipped += 1
continue
# Insert trade
self.log_trade_entry(trade)
# If trade is closed, update exit data
if trade.get('exit_time'):
self.update_trade_exit(
trade['ticket'],
trade
)
migrated += 1
except Exception as e:
print(f"⚠️ Error migrating trade {trade.get('ticket')}: {e}")
print(f"✅ Migration complete: {migrated} trades migrated, {skipped} skipped")
def close(self):
"""Close database connection"""
if self.conn:
self.conn.close()
def __enter__(self):
"""Context manager entry"""
return self
def __exit__(self, exc_type, exc_val, exc_tb):
"""Context manager exit"""
self.close()
# ==========================================
# USAGE EXAMPLE
# ==========================================
if __name__ == "__main__":
# Initialize database
db = TradingDatabase("trading_bot.db")
print("="*70)
print("🗄️ TRADING DATABASE - System Check")
print("="*70)
# Check tables
db.cursor.execute("""
SELECT name FROM sqlite_master
WHERE type='table'
ORDER BY name
""")
tables = db.cursor.fetchall()
print(f"\n📊 Tables created: {len(tables)}")
for table in tables:
print(f" ✅ {table['name']}")
# Get overall stats
stats = db.get_overall_statistics()
print(f"\n📈 Overall Statistics:")
print(f" Total Trades: {stats.get('total_trades', 0)}")
print(f" Win Rate: {stats.get('win_rate', 0)}%")
print(f" Net Profit: ${stats.get('net_profit', 0)}")
db.close()
print("\n" + "="*70)
print("✅ Database ready!")
print("="*70)