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:
1 parent
b61cb9b8f9
commit
596718e30b
64 files changed
+9944
-78909
No files matched your search
+61
@@ -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/
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
@@ -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()
|
||||
@@ -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! 🎉
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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
@@ -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+
|
||||
@@ -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! 💪
|
||||
@@ -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)
|
||||
@@ -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
File diff suppressed because it is too large.
Load diff
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
File diff suppressed because it is too large.
Load diff
@@ -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
@@ -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()
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
@@ -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
File diff suppressed because it is too large.
Load diff
@@ -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}
|
||||
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -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!
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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": "iVBORw0KGgoAAAANSUhEUgAAAjEAAAG6CAYAAAD58BdyAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAABv9klEQVR4nO3deXiU5b038O8zM1kmy0w2QgIJJBAgEAVEUIKtFRcqLtDWpVZLfftWWu3pctDWo7Z961IutO1xaTnQqhzrqRzxOiqttTUtdStWQRQia0BWCSQhG1kmmZnMzP3+kfPcPs8syUwy2zP5fq6LyyQzSX4Tk3m+87s3RQghQERERGQwpkQXQERERDQSDDFERERkSAwxREREZEgMMURERGRIDDFERERkSAwxREREZEgMMURERGRIlkQXECs+nw+nT59Gbm4uFEVJdDlEREQUBiEEenp6MGHCBJhMQ/daUjbEnD59GuXl5Ykug4iIiEbg5MmTKCsrG/I+KRticnNzAQz+EGw2W4KrISIionB0d3ejvLxcXseHkrIhRh1CstlsDDFEREQGE85UEE7sJSIiIkNiiCEiIiJDYoghIiIiQ2KIISIiIkNiiCEiIiJDYoghIiIiQ2KIISIiIkNiiCEiIiJDYoghIiIiQ2KIISIiIkNiiCEiIiJDYoghIiIiQ2KIIUoiXq8Xvb29EEIkuhQioqSXsqdYExmNEAK7du1Cb28vpkyZgkmTJiW6JCKipMZODFGScLvd6O3tBQB0dHQkuBoiouTHEEOUJFwul3zb4/EksBIiImNgiCFKEm63W749MDCQwEqIiIyBIYYoSbATQ0QUmYhCzPr16zF79mzYbDbYbDbU1tbitddek7fff//9qK6uRnZ2NvLz83H55Zdj+/btuq9xySWXQFEU3b+bbrpJd5+KioqA+9xzzz2jeJhEyU8bYrxeL1coERENI6LVSWVlZXj44YdRVVUFAHj22WexfPly7Nq1CzU1NZg+fTrWrl2LKVOmoL+/H4899hiWLFmCw4cPY9y4cfLrrFy5Eg8++KB832q1BnyvBx98ECtXrpTv5+TkRPzgiIxEO5wEDHZj0tLSElQNEVHyiyjEXHvttbr3V69ejfXr12Pbtm2oqanBzTffrLv90UcfxYYNG7B7925cdtll8uNZWVkoKSkZ8nvl5uYOex+iVKLtxAAMMUREwxnxnBiv14tNmzbB4XCgtrY24Ha3240nn3wSdrsdc+bM0d22ceNGFBUVoaamBj/4wQ/Q09MT8PmPPPIICgsLMXfuXKxevTrgVao/l8uF7u5u3T8iIwkWYoiIKLSIN7vbs2cPamtr4XQ6kZOTg82bN2PWrFny9ldffRU33XQT+vr6UFpaii1btqCoqEjefsstt6CyshIlJSXYu3cv7r33Xnz00UfYsmWLvM/3v/99zJs3D/n5+Xj//fdx77334tixY3j66adD1rVmzRo88MADkT4coqQRbDiJiIhCU0SEswfdbjc++eQTnD17Fi+99BKefvppvP322zLIOBwONDU1oa2tDU899RTeeOMNbN++HcXFxUG/3ocffoj58+fjww8/xLx584Le56WXXsL111+PtrY2FBYWBr2Py+XSvZLt7u5GeXk5urq6YLPZInmIRHHn9XqxdetW3cdqamp0c8mIiMaC7u5u2O32sK7fEQ8npaeno6qqCvPnz8eaNWswZ84cPPHEE/L27OxsVFVVYeHChdiwYQMsFgs2bNgQ8uvNmzcPaWlp+Pjjj0PeZ+HChQCAw4cPh7xPRkaGXDWl/iMyCv+hJICdGCKi4Yx6nxghRNAn4HBv37dvHwYGBlBaWhryPrt27QKAIe9DZGTB5nxxwzsioqFFNCfmvvvuw9KlS1FeXo6enh5s2rQJb731Furq6uBwOLB69WosW7YMpaWlaG9vx7p169DY2IgbbrgBAHDkyBFs3LgRV111FYqKirB//37cddddOO+883DRRRcBAN577z1s27YNixcvht1ux44dO7Bq1SosW7aMB+JRymInhogochGFmJaWFqxYsQJNTU2w2+2YPXs26urqcMUVV8DpdKKhoQHPPvusnLuyYMECbN26FTU1NQAGh6Jef/11PPHEE+jt7UV5eTmuvvpq/PSnP4XZbAYwOCz0wgsv4IEHHoDL5cLkyZOxcuVK3H333dF/9ERJgiGGiChyEU/sNYpIJgYRJdrhw4fR2Nio+1hxcbFu5R8R0VgQ04m9RBR97MQQEUWOIYYoCQSb2MsQQ0Q0NIYYoiSgdmLS0tLk/DCGGCKioTHEECWYdhuC9PR0WCyD8+0ZYoiIhsYQQ5RgHo8H6vz6jIwMeegjQwwR0dAYYogSTDupNyMjQ3ZifD4fvF5vosoiIkp6DDFECaYNMdrhJIDdGCKioTDEECWYdmWSthMDMMQQEQ2FIYYowdiJISIaGYYYogQLNScGYIghIhoKQwxRgnE4iYhoZBhiiBJM7cQoioK0tDSGGCKiMDHEECWYdqM7RVEYYoiIwsQQQ5RAPp8PAwMDAAaHkgDIze4AyNuIiCgQQwxRAmnnw6SnpwMAOzFERGFiiCFKIP+VSQBDDBFRuBhiiBLIf2USwBBDRBQuhhiiBPLf6A4ATCYTFEUBwBBDRDQUhhiiBArWidGuUGKIISIKjSGGKIGCzYkBwBBDRBQGy/B3IaJoc7vdOHv2LLq7u+XH1OEkQB9ihBByeImIiD7FEEMUR729vWhoaEBvb6/u4xaLRTehV/u21+vVvU9ERIM4nEQUR42NjQEBRlEUTJo0SfcxbnhHRDQ8vrwjiiOn0ynfnjRpEvLy8mCz2QI6LVxmTUQ0PIYYojhSJ/KazWZMmTIl5P0YYoiIhsfhJKI4EULIEKNdiRQMQwwR0fAYYojixOv1wufzAWCIISKKBoYYojgJtjtvKAwxRETDY4ghipNQG9sFwxBDRDQ8hhiiOGGIISKKLoYYojgJdk5SKNwnhohoeAwxRHHCOTFERNHFEEMUJ5EMJ5nNZvk2QwwRUXAMMURxooYYRVGG7cSYTCYZZBhiiIiCY4ghihN1Tkx6enpYp1JrT7ImIqJADDFEceDz+XQhJhwMMUREQ2OIIYqDSFYmqdQQ4/P55E6/RET0KYYYojiIZFKviiuUiIiGxhBDFAej6cQADDFERMEwxBDFQSR7xKi44R0R0dAYYojigMNJRETRxxBDFAcMMURE0ccQQxQHnBNDRBR9DDFEcaB2Ysxms+5IgaEwxBARDY0hhijGhBAyxITbhQE4sZeIaDgMMUQx5vF45GZ1kYQY7Som7XAUERENYoghirGRzIcB9J0YhhgiokAMMUQxNpI9YoDB+TMm0+CfKENM9DU2NmLPnj3o6+tLdClENEIMMUQxNpLl1QCgKIoMPQwx0eV0OnH48GG0t7fj+PHjiS6HiEaIIYYoxkYaYoBPOzfaeTU0er29vUHfJiJjYYghirGRzokB9MNPXKEUPdrg0t/fz4BIZFAMMUQxNtI5Mf7355BS9GhDjBAC/f39CayGiEaKIYYoxtQQo53jEi6GmNjwH0JyOBwJqoSIRoMhhijG1BCTnp4ORVEi+lyGmOjzeDxwOp26j3GFEpExMcQQxZDP55NzWSKdDwNwr5hYCDaRl50YImNiiCGKIW3wiHQoyf9zGGKigyGGKHVEFGLWr1+P2bNnw2azwWazoba2Fq+99pq8/f7770d1dTWys7ORn5+Pyy+/HNu3b9d9jUsuuQSKouj+3XTTTbr7dHZ2YsWKFbDb7bDb7VixYgXOnj078kdJlCCjWV4NMMTEgjawqMN7XKFEZEwRhZiysjI8/PDD+OCDD/DBBx/g0ksvxfLly7Fv3z4AwPTp07F27Vrs2bMH77zzDioqKrBkyRK0trbqvs7KlSvR1NQk//32t7/V3X7zzTejvr4edXV1qKurQ319PVasWDHKh0oUf9EMMVxiHR3aTkxBQQEArlAiMipLJHe+9tprde+vXr0a69evx7Zt21BTU4Obb75Zd/ujjz6KDRs2YPfu3bjsssvkx7OyslBSUhL0exw4cAB1dXXYtm0bLrzwQgDAU089hdraWhw8eBAzZsyIpGSihBptiDGbzTCbzfB6vezERIEQQnZirFYrbDYb2tvbAQx2aLKzsxNZHhFFaMRzYrxeLzZt2gSHw4Ha2tqA291uN5588knY7XbMmTNHd9vGjRtRVFSEmpoa/OAHP0BPT4+87b333oPdbpcBBgAWLlwIu92Od999N2Q9LpcL3d3dun9EiaZ9dZ+ZmTmir8GjB6Knr69PDhvl5OQgKytLdxsRGUtEnRgA2LNnD2pra+F0OpGTk4PNmzdj1qxZ8vZXX30VN910E/r6+lBaWootW7agqKhI3n7LLbegsrISJSUl2Lt3L+6991589NFH2LJlCwCgubkZxcXFAd+3uLgYzc3NIetas2YNHnjggUgfDlFMaUOM1Wod0ddIT09Hf3+/PHpAPRSSIqcdSsrJydF1Xvwn93Z0dCA9PR05OTlxq4+IIhNxiJkxYwbq6+tx9uxZvPTSS7j11lvx9ttvyyCzePFi1NfXo62tDU899RRuvPFGbN++XQaTlStXyq91zjnnYNq0aZg/fz527tyJefPmAUDQvTSEEEPusXHvvffizjvvlO93d3ejvLw80odHFFVqiDGbzbrl0pHwn9w70o4OBYYYq9UKRVF0w0wAcOrUKXz88ccwm82YP3/+iAMoEcVWxC/p0tPTUVVVhfnz52PNmjWYM2cOnnjiCXl7dnY2qqqqsHDhQmzYsAEWiwUbNmwI+fXmzZuHtLQ0fPzxxwCAkpIStLS0BNyvtbUV48ePD/l1MjIy5Kop9R9RIvl8PjknRr1YjgT3iokebVDJycmBoihySEldoSSEwMmTJwEMDpsHez4iouQw6r60EEI3eTHS2/ft24eBgQGUlpYCAGpra9HV1YX3339f3mf79u3o6urCokWLRlsuUdyLine 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": "iVBORw0KGgoAAAANSUhEUgAAAjEAAAG6CAYAAAD58BdyAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAABoAklEQVR4nO3de3yT9aE/8M+TpE0vadJ7aWmhQGmRQosISnFzItCBF5gXlOFhnv02HG7TjePPHXHbEXQMPXOiGwfmpTo2nfibyJljs8rGcCC0wLSAhSJXodCW3i9pk7TJ9/dHyJN7adK0ufTz3isv0ud58uSb74L98L1KQggBIiIiojCjCHYBiIiIiPzBEENERERhiSGGiIiIwhJDDBEREYUlhhgiIiIKSwwxREREFJYYYoiIiCgsqYJdgKFisVhw6dIlJCQkQJKkYBeHiIiIBkAIgc7OTmRlZUGh6L+tJWJDzKVLl5CTkxPsYhAREZEfLly4gOzs7H6vidgQk5CQAMBaCVqtNsilISIiooHo6OhATk6O/Hu8PxEbYmxdSFqtliGGiIgozAxkKAgH9hIREVFYYoghIiKisMQQQ0RERGGJIYaIiIjCEkMMERERhSWGGCIiIgpLDDFEREQUlhhiiIiIKCwxxBAREVFYYoghIiKisBSx2w4EjRBAczPQ1QVoNEBKCsBdtImIiAKOLTGB0tYGvPgiMHEikJYGjBtn/XPiROvxtrZgl5CIiCiiMMQEwgcfANnZwKpVwJkzTqfEmTPW49nZ1uuIiIgoIBhiBqGlpQUnfvUriFtvBXp6rF1JQjhdI105Jnp6IG69FW1vvx2k0hIREUUWhphBOLZvH/L+8z+twcVi6fdayWIBhEDCv/87u5aIiIgCwKcQs3nzZhQVFUGr1UKr1aKkpATvv/++fH7NmjWYNGkS4uPjkZSUhHnz5qGystLtPvv378ctt9yC+Ph4JCYm4uabb0ZPT498Pjc3F5IkOT0ef/zxQXzMoZFRXg6F0WhtbRkASQgojEaILVuGuGRERESRz6cQk52djWeeeQaHDh3CoUOHcMstt2Dx4sWorq4GAOTn52Pjxo04evQo9u7di9zcXJSWlqKxsVG+x/79+7FgwQKUlpbiwIEDOHjwIL7//e9DoXAuylNPPYW6ujr58ZOf/CQAHzeAhMDo7dvduo8G5Ne/9u91REREJJOEGNxv0+TkZPziF7/At771LbdzHR0d0Ol0+Nvf/oa5c+cCAGbNmoX58+fj6aef9nrP3Nxc/PCHP8QPf/hDv8tle+/29nZotVq/7+NVU5N19pGfus6dg2bs2AAWiIiIKPz58vvb7zExZrMZW7duhV6vR0lJidt5k8mEl19+GTqdDsXFxQCAy5cvo7KyEunp6Zg9ezYyMjLwla98BXv37nV7/bPPPouUlBRMmzYN69atg8lk6rc8RqMRHR0dTo8h1dU1qJef/OSTABWEiIhoZPJ5sbujR4+ipKQEBoMBGo0G27dvx+TJk+XzO3bswNKlS9Hd3Y3MzEzs3LkTqampAIAzV6Yfr1mzBs899xymTZuG3/3ud5g7dy4+++wzTJw4EQDwgx/8ANOnT0dSUhIOHDiA1atX4+zZs3j11Ve9lmv9+vVYu3atrx/HfxrNoF6uV3BMNRER0WD43J1kMplw/vx5tLW1Ydu2bXj11Vfx0UcfyUFGr9ejrq4OTU1NeOWVV7Br1y659WXfvn248cYbsXr1avz85z+X71lUVITbbrsN69ev9/ie27Ztwz333IOmpiakpKR4vMZoNMJoNMo/d3R0ICcnZ+i6k4RAT04OYi5dGvDAXgAQkoSezEwceOMN3DxnTuDLRUREFMaGtDspOjoaeXl5mDFjBtavX4/i4mK8+OKL8vn4+Hjk5eVh1qxZKCsrg0qlQllZGQAgMzMTAJxabgDgmmuuwfnz572+56xZswAAp06d8nqNWq2WZ03ZHkNKknDxrrv8eunFu+7iVgRERESDNOg+DSGEUwtIf+dzc3ORlZWFEydOOF3z+eefY2w/g1w//fRTAPYQFCrqS0thUashBhhIhCTBolaj4atfHeKSERERRT6fxsQ88cQTWLhwIXJyctDZ2YmtW7di9+7dKC8vh16vx7p167Bo0SJkZmaiubkZmzZtQm1tLZYsWQIAkCQJjz32GJ588kkUFxdj2rRp2LJlC2pqavDOO+8AsE7BrqiowJw5c6DT6XDw4EGsWrUKixYtwpgxYwJfA34SQqBPo8Fna9di6uOrYYEEJbwveGeBApIEfPbUU+gb5HgaIiIi8jHENDQ0YPny5airq4NOp0NRURHKy8sxf/58GAwG1NTUYMuWLfLYlZkzZ2LPnj0oLCyU7/HDH/4QBoMBq1atQktLC4qLi7Fz505MmDABgLVb6O2338batWthNBoxduxYrFixAj/60Y8C+8kHyXJlhd7W66/Hf3/ldXx/93cRh24AgAL2MTIWWFtpuhGLEz9bi86Z18nnent7ERUVNYylJiIiihyDXicmVA31OjG9vb34+OOPAQCPPlqM059I+AZ+h59n/Dc0DRfl6y7F5uKZnlXYggfwn+vOY/bsZvlcamoqpkyZEvCyERERhStffn/7PMWarGwtMRYLcOJEAvRQ4Q8p38Gdf5iKqM4OzJw0CerUVGz9bTN+/X/zAQAff5zqFGKampqCUnYiIqJIwMVK/GRrwGpsVEOvt2bBiRO7ICkk9Ol0UIwfD6SkoGR2N2JizACAfftSYDYHrchEREQRhSHGT7aWmPPn4+RjY8fq5ecqlTXYxMcrMHNmCwCgrS0ax47Zm8Y4HoaIiMh/DDF+8hRixoy5MrBXoYB0Zdq1QqHAjTfau42qquxTyW1Bh4iIiHzHEOOn/kKMYzhRKpWYNasZCoW1+2n3bg2io6Od7kFERES+Y4jxk21MjKcQo1Qq5WNKpRI6XR8mTuwEAJw9G43eXqXTPYiIiMh3DDF+cm2JSUoyQavtA+AeYgB7wBFCwoULsU73ICIiIt8xxPjJYrGgq0uFlhY1ACAnp1s+59qdBNhDDAB88UU8ALbEEBERDQZDjJ8sFgtqa2Pln8eM6ZGfe2qJyc21h5j330+R70FERET+YYjxkxACDQ1q+eesLJP8XHLYENIWYq67rgWpqdaNMD/+OBGXLsVACMHWGCIiIj8xxPhJCIHLl2Pkn7Oz++Tnvb298nNbiImNteBrX7NvR7BpUx727k1BSwtDDBERkT8YYvxkDTGOLTH2pXj7+uyBxrFr6ctfboIkWUPLxx+n4qc/nYqiIgknTw5DgYmIiCIMQ4yfrN1J9paYsWPtXUieupMA6+Den/60zek+ly5JuPdegL1KREREvmGI8ZNjS4xCIXD99dlyeMnLy5OvUyicq/jBB7vx7LPnMXq0faBvVRXw+edDX2YiIqJIwhDjJ4vFIo+JGTXKAq02Ftdffz1mzpyJxMRE+TrHlhjA2kpz222deOONA/jWt87Ixysrh6XYREREEYMhxk89PUBrq3X7gNGjreNhYmNjER8f73SdpxBja7G55poO+fiBA0NZWiIiosjDEOOnS5fsVZed7X29F08hxtbFlJ/fJR+vrg5wAYmIiCIcQ4yfLl60hxNfQ4ytJSYhoQ9padbXnjgxBIUkIiKKYAwxfqqrs1ddVpb3qUUKhQIJCQnyz/Hx8U6DfbOyOq/cD2hvH4KCEhERRSiGGD81NtpbWEaN8t4SI0kSpk2bhsmTJ2P69OnQaDROU7Czs/Xy808/HZqyEhERRSKGGD81NtqrLiOj/0VelEol0tPTodVq3c4VF9ubX3bsCFz5iIiIIh1DjJ8cW2IyMqR+rnTnuC3BDTc0Q6GwhqBduwJTNiIiopGAIcZPTU2OIca35XYdQ4xW24cJE6zdUceOCXR29nh7GRERETlgiPGTrSUmJsaMhATfWmJMJpPTzwUF1lBjNEr44INTgSkgERFRhGOI8VNjowoAkJxsgkLhW4hJSUlx+jk/3yA/r6727V5EREQjFUOMH4xGoL3d2hKTlGRymm00EDk5OYiKinL42R5i6upiYbF4n+1EREREVgwxfrh82f48Odn3EKNSqVBUVCT/nJpqX7m3vj4G//znP9Ha2jrochIREUUyhhg/1Nfbn/sTYgBrkLGJi2twuLd1U8mjR4/6X0AiIqIRgCHGD4EOMUlJvYiONl+5tzXEsEuJiIiofwwxfghEiHHcU0mSgIwMIwCgoSFm0OUjIiIaCRhi/NBg7/3xa2AvYN1TyXEPpZQUa4gxGJTo7lZ6exkRERFdwRDjh6Ym+/PExF6nMOILxy6l5GT72jHNzdF+l42IiGikYIjxg2OI0el6/WqJAZxDTGqqc4hxPEdERETufAoxmzdvRlFREbRaLbRaLUpKSvD+++/L59esWYNJkyYhPj4eSUlJmDdvHiorK93us3//ftxyyy2Ij49HYmIibr75ZvT02Jfbb21txfLly6HT6aDT6bB8+XK0tbX5/ykDbChCjK07CQBaWtRO68gQERGRO59CTHZ2Np555hkcOnQIhw4dwi233ILFixejuroaAJCfn4+NGzfi6NGj2Lt3L3Jzc1FaWorGxkb5Hvv378eCBQtQWlqKAwcO4ODBg/j+97/v1CWzbNkyVFVVoby8HOXl5aiqqsLy5csD9JEHzxZiFAqB+Pi+gIQY1+4kIXzbj4mIiGik8anP4o477nD6ed26ddi8eTMqKipQWFiIZcuWOZ1//vnnUVZWhiNHjmDu3LkAgFWrVuGRRx7B448/Ll83ceJE+fnx48dRXl6OiooK3HDDDQCAV155BSUlJThx4gQKCgo8ls1oNMJotLdmdHR0+PLRfHL5shmAEjpdL/wcDgMAiImxz0RKSXEOMZxiTURE1D+/fwWbzWZs3boVer0eJSUlbudNJhNefvll6HQ6FBcXAwAuX76MyspKpKenY/bs2cjIyMBXvvIV7N27V37d/v37odPp5AADALNLine 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
|
||||
@@ -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()
|
||||
@@ -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
File diff suppressed because it is too large.
Load diff
@@ -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
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
======================================================================
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -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%)")
|
||||
@@ -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"
|
||||
}
|
||||
@@ -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)
|
||||
@@ -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
@@ -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)")
|
||||
@@ -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)
|
||||
Reference in new issue
Block a user