| | import pandas as pd
|
| | from bs4 import BeautifulSoup
|
| | import re
|
| | from datetime import datetime
|
| |
|
| | class MT5ReportParser:
|
| | def __init__(self, html_file_path):
|
| | """Initialize parser with HTML file path"""
|
| | self.html_file_path = html_file_path
|
| | self.soup = None
|
| | self.deals_df = None
|
| | self.statistics = {}
|
| |
|
| | def load_html(self):
|
| | """Load and parse HTML file"""
|
| | with open(self.html_file_path, 'r', encoding='utf-8') as f:
|
| | content = f.read()
|
| | self.soup = BeautifulSoup(content, 'html.parser')
|
| |
|
| | def extract_deals_table(self):
|
| | """Extract the Deals table from HTML"""
|
| |
|
| | tables = self.soup.find_all('table')
|
| |
|
| | for table in tables:
|
| | headers = [th.get_text(strip=True) for th in table.find_all('th')]
|
| |
|
| |
|
| | if 'Deal' in headers or 'Time' in headers:
|
| |
|
| | cols = headers
|
| |
|
| |
|
| | rows = []
|
| | for tr in table.find_all('tr')[1:]:
|
| | cells = tr.find_all('td')
|
| | if cells:
|
| | row = [td.get_text(strip=True) for td in cells]
|
| | rows.append(row)
|
| |
|
| |
|
| | if rows:
|
| | self.deals_df = pd.DataFrame(rows, columns=cols)
|
| | self._clean_deals_data()
|
| | break
|
| |
|
| | def _clean_deals_data(self):
|
| | """Clean and convert data types in deals DataFrame"""
|
| | if self.deals_df is None:
|
| | return
|
| |
|
| |
|
| | numeric_cols = ['Volume', 'Price', 'Commission', 'Swap', 'Profit', 'Balance']
|
| | for col in numeric_cols:
|
| | if col in self.deals_df.columns:
|
| | self.deals_df[col] = pd.to_numeric(
|
| | self.deals_df[col].str.replace(r'[^\d.-]', '', regex=True),
|
| | errors='coerce'
|
| | )
|
| |
|
| |
|
| | if 'Time' in self.deals_df.columns:
|
| | try:
|
| | self.deals_df['Time'] = pd.to_datetime(self.deals_df['Time'])
|
| | except:
|
| | pass
|
| |
|
| | def extract_statistics(self):
|
| | """Extract all statistics from the report"""
|
| |
|
| | all_tables = self.soup.find_all('table')
|
| |
|
| | for table in all_tables:
|
| | rows = table.find_all('tr')
|
| | for row in rows:
|
| | cells = row.find_all('td')
|
| | if len(cells) == 2:
|
| | key = cells[0].get_text(strip=True)
|
| | value = cells[1].get_text(strip=True)
|
| |
|
| |
|
| | key = key.replace(':', '').strip()
|
| |
|
| | if key and value:
|
| |
|
| | try:
|
| | value = float(value.replace(' ', '').replace(',', ''))
|
| | except:
|
| | pass
|
| |
|
| | self.statistics[key] = value
|
| |
|
| |
|
| | divs = self.soup.find_all('div')
|
| | for div in divs:
|
| | text = div.get_text(strip=True)
|
| | if ':' in text:
|
| | parts = text.split(':')
|
| | if len(parts) == 2:
|
| | key = parts[0].strip()
|
| | value = parts[1].strip()
|
| | if key and value and key not in self.statistics:
|
| | try:
|
| | value = float(value.replace(' ', '').replace(',', ''))
|
| | except:
|
| | pass
|
| | self.statistics[key] = value
|
| |
|
| | def get_common_statistics(self):
|
| | """Extract commonly used MT5 statistics"""
|
| | common_stats = {
|
| | 'Initial Deposit': None,
|
| | 'Total Net Profit': None,
|
| | 'Gross Profit': None,
|
| | 'Gross Loss': None,
|
| | 'Profit Factor': None,
|
| | 'Expected Payoff': None,
|
| | 'Absolute Drawdown': None,
|
| | 'Maximal Drawdown': None,
|
| | 'Relative Drawdown': None,
|
| | 'Total Trades': None,
|
| | 'Short Positions': None,
|
| | 'Long Positions': None,
|
| | 'Profit Trades': None,
|
| | 'Loss Trades': None,
|
| | 'Largest Profit': None,
|
| | 'Largest Loss': None,
|
| | 'Average Profit': None,
|
| | 'Average Loss': None,
|
| | 'Maximum Consecutive Wins': None,
|
| | 'Maximum Consecutive Losses': None,
|
| | 'Maximal Consecutive Profit': None,
|
| | 'Maximal Consecutive Loss': None,
|
| | 'Average Consecutive Wins': None,
|
| | 'Average Consecutive Losses': None,
|
| | }
|
| |
|
| |
|
| | for key in self.statistics:
|
| | for common_key in common_stats.keys():
|
| | if common_key.lower() in key.lower():
|
| | common_stats[common_key] = self.statistics[key]
|
| |
|
| | return common_stats
|
| |
|
| | def parse(self):
|
| | """Main method to parse the entire report"""
|
| | self.load_html()
|
| | self.extract_deals_table()
|
| | self.extract_statistics()
|
| |
|
| | def save_deals_to_csv(self, output_path='deals.csv'):
|
| | """Save deals table to CSV"""
|
| | if self.deals_df is not None:
|
| | self.deals_df.to_csv(output_path, index=False)
|
| | print(f"Deals saved to {output_path}")
|
| | else:
|
| | print("No deals table found")
|
| |
|
| | def save_statistics_to_csv(self, output_path='statistics.csv'):
|
| | """Save statistics to CSV"""
|
| | if self.statistics:
|
| | stats_df = pd.DataFrame(list(self.statistics.items()),
|
| | columns=['Statistic', 'Value'])
|
| | stats_df.to_csv(output_path, index=False)
|
| | print(f"Statistics saved to {output_path}")
|
| | else:
|
| | print("No statistics found")
|
| |
|
| | def print_summary(self):
|
| | """Print a summary of the parsed data"""
|
| | print("=" * 60)
|
| | print("MT5 TRADE REPORT SUMMARY")
|
| | print("=" * 60)
|
| |
|
| | if self.deals_df is not None:
|
| | print(f"\nDeals Table: {len(self.deals_df)} rows")
|
| | print(f"Columns: {', '.join(self.deals_df.columns.tolist())}")
|
| | print("\nFirst 5 deals:")
|
| | print(self.deals_df.head())
|
| | else:
|
| | print("\nNo deals table found")
|
| |
|
| | print(f"\n\nStatistics Found: {len(self.statistics)}")
|
| | common_stats = self.get_common_statistics()
|
| | print("\nCommon Statistics:")
|
| | for key, value in common_stats.items():
|
| | if value is not None:
|
| | print(f" {key}: {value}")
|
| |
|
| | print("\n" + "=" * 60)
|
| |
|
| |
|
| |
|
| | if __name__ == "__main__":
|
| |
|
| | html_file = "mt5_report.html"
|
| |
|
| |
|
| | parser = MT5ReportParser(html_file)
|
| |
|
| |
|
| | parser.parse()
|
| |
|
| |
|
| | parser.print_summary()
|
| |
|
| |
|
| | parser.save_deals_to_csv("deals.csv")
|
| | parser.save_statistics_to_csv("statistics.csv")
|
| |
|
| |
|
| | deals_df = parser.deals_df
|
| | statistics = parser.statistics
|
| | common_stats = parser.get_common_statistics()
|
| |
|
| |
|
| | if deals_df is not None and 'Profit' in deals_df.columns:
|
| | total_profit = deals_df['Profit'].sum()
|
| | print(f"\nTotal Profit from Deals: {total_profit}") |