feat: Add P&L Tracking with automatic MT5 history import (V1.9)
Added comprehensive P&L tracking system with automatic MT5 history import: New Features: - Automatic MT5 history sync (hourly) - Entry+Exit deal matching for complete positions - Real P&L calculation (profit + commission + swap) - Real Win Rate from closed MT5 trades - Multi-period analysis (Today, Week, Month, All-Time) - Live performance dashboard - Performance metrics (Profit Factor, Max Drawdown, Win/Loss Ratio) - Recent trades display Files Added: - mt5_pnl_tracker.py: Core P&L tracking module (950 lines) - integrate_pnl_tracker.py: Notebook integration script - PNL_TRACKER_GUIDE.md: Complete documentation - PNL_QUICK_START.md: 3-step quick start guide - BOT_IMPROVEMENTS_SUMMARY.md: Complete improvements timeline Notebook Changes: - Added Cells 85-90 (6 new cells for P&L tracking) - Cell 85: Section header (Markdown) - Cell 86: Setup P&L tracker - Cell 87: Initial MT5 history sync - Cell 88: Add P&L sync to scheduler - Cell 89: Usage instructions (Markdown) - Cell 90: Live dashboard display Scheduler: - Added pnl_sync job (every 1 hour) - Automatically imports last 7 days from MT5 - Matches Entry/Exit deals - Calculates real P&L Database: - mt5_deals table: Raw MT5 deals - matched_positions table: Complete trades (Entry+Exit) - pnl_summary table: Aggregated metrics Benefits: - Know real Win Rate (not estimates) - Track actual profit/loss accurately - Validate strategy performance - Data-driven threshold optimization - Performance trend analysis Total Cells: 85 → 91 Version: V1.6 → V1.9 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
0a1ff55857
commit
4f47b8e2fe
8 files changed
+3157
-2
No files matched your search
@@ -3187,7 +3187,17 @@
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"2026-01-21 09:54:33,170 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||
"2026-01-21 09:54:43,189 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||
"2026-01-21 09:54:53,232 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# ==========================================\n",
|
||||
"# TEST: Enhanced Trailing Stop Status\n",
|
||||
@@ -3255,6 +3265,238 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "15a89cf8",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# 💰 P&L TRACKING & PERFORMANCE ANALYTICS (V1.9)\n",
|
||||
"\n",
|
||||
"**Automatic MT5 History Import & Real-Time P&L Dashboard**\n",
|
||||
"\n",
|
||||
"Features:\n",
|
||||
"- 📥 **Automatic MT5 History Import** - Syncs closed trades from MT5\n",
|
||||
"- 💰 **Real P&L Calculation** - Matches Entry+Exit deals for accurate P&L\n",
|
||||
"- 📊 **Win Rate Analysis** - Real Win Rate from closed MT5 trades\n",
|
||||
"- 📈 **Performance Metrics** - Profit Factor, Max Drawdown, Avg Win/Loss\n",
|
||||
"- 🎯 **Session Analysis** - Compare Asian vs NY performance\n",
|
||||
"- 📅 **Time-based Reports** - Today, Week, Month, All-Time\n",
|
||||
"- 🔄 **Automatic Sync** - Scheduled hourly updates\n",
|
||||
"\n",
|
||||
"**Status:** ✅ READY TO USE\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "5d2044d5",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# ==========================================\n",
|
||||
"# SETUP P&L TRACKER\n",
|
||||
"# ==========================================\n",
|
||||
"\n",
|
||||
"from mt5_pnl_tracker import MT5PnLTracker, scheduled_pnl_sync\n",
|
||||
"\n",
|
||||
"print(\"=\" * 80)\n",
|
||||
"print(\"🚀 INITIALIZING P&L TRACKER...\")\n",
|
||||
"print(\"=\" * 80)\n",
|
||||
"\n",
|
||||
"# Initialize tracker\n",
|
||||
"pnl_tracker = MT5PnLTracker(\n",
|
||||
" db_path=\"trading_bot.db\",\n",
|
||||
" magic_number=None # None = all trades, or specify your EA magic number\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"# Connect to database\n",
|
||||
"pnl_tracker.connect_db()\n",
|
||||
"\n",
|
||||
"print(\"\\n✅ P&L Tracker initialized successfully!\")\n",
|
||||
"print(\" Database: trading_bot.db\")\n",
|
||||
"print(\" Tables: mt5_deals, matched_positions, pnl_summary\")\n",
|
||||
"print(\"=\" * 80)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "b3de5cd8",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# ==========================================\n",
|
||||
"# INITIAL SYNC: IMPORT MT5 HISTORY\n",
|
||||
"# ==========================================\n",
|
||||
"\n",
|
||||
"print(\"\\n📥 Importing MT5 history...\")\n",
|
||||
"print(\" This will import last 30 days of trades from MT5\")\n",
|
||||
"print(\" Please wait...\\n\")\n",
|
||||
"\n",
|
||||
"# Perform initial sync\n",
|
||||
"sync_results = pnl_tracker.sync_and_update(days_back=30)\n",
|
||||
"\n",
|
||||
"if sync_results['success']:\n",
|
||||
" summary = sync_results['summary']\n",
|
||||
"\n",
|
||||
" print(\"=\" * 80)\n",
|
||||
" print(\"✅ SYNC SUCCESSFUL!\")\n",
|
||||
" print(\"=\" * 80)\n",
|
||||
" print(f\"\\n📥 Import Results:\")\n",
|
||||
" print(f\" New Deals: {summary['new_deals']}\")\n",
|
||||
" print(f\" Matched Positions: {summary['matched_positions']}\")\n",
|
||||
" print(f\"\\n📊 Current Performance:\")\n",
|
||||
" print(f\" Total Trades: {summary['total_trades']}\")\n",
|
||||
" print(f\" Win Rate: {summary['win_rate']:.1f}%\")\n",
|
||||
" print(f\" Net P&L: ${summary['net_profit']:.2f}\")\n",
|
||||
" print(\"=\" * 80)\n",
|
||||
"\n",
|
||||
" if summary['new_deals'] == 0:\n",
|
||||
" print(\"\\n💡 No new deals found. This means:\")\n",
|
||||
" print(\" • History already imported, OR\")\n",
|
||||
" print(\" • No trades in last 30 days\")\n",
|
||||
"else:\n",
|
||||
" print(\"=\" * 80)\n",
|
||||
" print(\"❌ SYNC FAILED\")\n",
|
||||
" print(\"=\" * 80)\n",
|
||||
" print(f\"Error: {sync_results.get('error', 'Unknown error')}\")\n",
|
||||
" print(\"\\n💡 Troubleshooting:\")\n",
|
||||
" print(\" • Check MT5 is running\")\n",
|
||||
" print(\" • Verify MT5 connection\")\n",
|
||||
" print(\" • Check trading history exists\")\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "b488bf8b",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# ==========================================\n",
|
||||
"# ADD P&L SYNC TO SCHEDULER\n",
|
||||
"# ==========================================\n",
|
||||
"\n",
|
||||
"from apscheduler.triggers.interval import IntervalTrigger\n",
|
||||
"\n",
|
||||
"print(\"\\n🔄 Adding P&L sync to scheduler...\")\n",
|
||||
"\n",
|
||||
"# Remove old job if exists\n",
|
||||
"try:\n",
|
||||
" scheduler.remove_job('pnl_sync')\n",
|
||||
" print(\" Removed old P&L sync job\")\n",
|
||||
"except:\n",
|
||||
" pass\n",
|
||||
"\n",
|
||||
"# Add hourly P&L sync\n",
|
||||
"scheduler.add_job(\n",
|
||||
" scheduled_pnl_sync,\n",
|
||||
" trigger=IntervalTrigger(hours=1),\n",
|
||||
" args=[pnl_tracker, 7], # Sync last 7 days\n",
|
||||
" id='pnl_sync',\n",
|
||||
" name='P&L Sync',\n",
|
||||
" replace_existing=True,\n",
|
||||
" max_instances=1\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"print(\"✅ P&L sync scheduled (every 1 hour)\")\n",
|
||||
"print(\" Syncs last 7 days from MT5\")\n",
|
||||
"\n",
|
||||
"# Show all scheduler jobs\n",
|
||||
"print(\"\\n📋 Active Scheduler Jobs:\")\n",
|
||||
"for job in scheduler.get_jobs():\n",
|
||||
" print(f\" • {job.id}: {job.trigger}\")\n",
|
||||
"\n",
|
||||
"print(\"\\n✅ Scheduler updated successfully!\")\n",
|
||||
"print(\"=\" * 80)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "00edde6a",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 📖 How to Use P&L Tracker\n",
|
||||
"\n",
|
||||
"### 📊 View Dashboard\n",
|
||||
"Run the dashboard cell to see:\n",
|
||||
"- All-time performance\n",
|
||||
"- Monthly performance\n",
|
||||
"- Weekly performance\n",
|
||||
"- Today's performance\n",
|
||||
"\n",
|
||||
"### 📜 View Recent Trades\n",
|
||||
"See last 10 closed trades with:\n",
|
||||
"- Entry/Exit prices\n",
|
||||
"- P&L per trade\n",
|
||||
"- Duration\n",
|
||||
"- Win/Loss status\n",
|
||||
"\n",
|
||||
"### 🔄 Manual Sync\n",
|
||||
"If you want to manually sync MT5 history:\n",
|
||||
"```python\n",
|
||||
"sync_results = pnl_tracker.sync_and_update(days_back=30)\n",
|
||||
"print(sync_results)\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"### 📊 Get Specific Period Metrics\n",
|
||||
"```python\n",
|
||||
"# Get metrics for specific period\n",
|
||||
"all_time = pnl_tracker.calculate_pnl_metrics('all')\n",
|
||||
"month = pnl_tracker.calculate_pnl_metrics('month')\n",
|
||||
"week = pnl_tracker.calculate_pnl_metrics('week')\n",
|
||||
"today = pnl_tracker.calculate_pnl_metrics('today')\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"### 🎯 Integration with Dynamic Thresholds\n",
|
||||
"The P&L tracker data can be used by the Dynamic Threshold Optimizer to better calibrate optimal confidence thresholds based on real MT5 performance!\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cf605503",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# ==========================================\n",
|
||||
"# 💰 P&L PERFORMANCE DASHBOARD\n",
|
||||
"# ==========================================\n",
|
||||
"\n",
|
||||
"# Generate and display dashboard\n",
|
||||
"dashboard = pnl_tracker.generate_dashboard()\n",
|
||||
"print(dashboard)\n",
|
||||
"\n",
|
||||
"# Show recent trades\n",
|
||||
"print(\"\\n\" + \"=\" * 80)\n",
|
||||
"print(\"📜 RECENT TRADES (Last 10)\")\n",
|
||||
"print(\"=\" * 80)\n",
|
||||
"\n",
|
||||
"recent_trades = pnl_tracker.get_recent_trades(limit=10)\n",
|
||||
"\n",
|
||||
"if not recent_trades.empty:\n",
|
||||
" # Format for display\n",
|
||||
" recent_trades['entry_time'] = pd.to_datetime(recent_trades['entry_time']).dt.strftime('%Y-%m-%d %H:%M')\n",
|
||||
" recent_trades['exit_time'] = pd.to_datetime(recent_trades['exit_time']).dt.strftime('%Y-%m-%d %H:%M')\n",
|
||||
" recent_trades['net_profit'] = recent_trades['net_profit'].round(2)\n",
|
||||
" recent_trades['pips'] = recent_trades['pips'].round(1)\n",
|
||||
" recent_trades['duration_hours'] = recent_trades['duration_hours'].round(1)\n",
|
||||
" recent_trades['status'] = recent_trades['is_win'].apply(lambda x: '✅ WIN' if x else '❌ LOSS')\n",
|
||||
"\n",
|
||||
" # Select columns to display\n",
|
||||
" display_cols = ['position_id', 'symbol', 'type', 'entry_time', 'exit_time',\n",
|
||||
" 'net_profit', 'pips', 'duration_hours', 'status']\n",
|
||||
"\n",
|
||||
" print(\"\\n\" + recent_trades[display_cols].to_string(index=False))\n",
|
||||
"else:\n",
|
||||
" print(\"\\n❌ No recent trades found\")\n",
|
||||
"\n",
|
||||
"print(\"\\n\" + \"=\" * 80)\n",
|
||||
"print(\"✅ Dashboard refresh complete!\")\n",
|
||||
"print(f\"Last updated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\")\n",
|
||||
"print(\"=\" * 80)\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
@@ -3278,4 +3520,4 @@
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user