wow gold

You see the spammers in the game all the time advertising cheap wow gold in wow in stock and it seems like a great way to get some gold for the things you want and need. As the trusted name for players to buy wow account without Paypal, CWG has never sent any spam. We have a strict anti-spam policy to fight against such behaviour. Enjoy our cheap wow gold instant delivery from one of the best sellers. Read more: [url=http://www.alliance-warcraftgold.com] Cheap WoW Gold | alliance-warcraftgold.com | alliance-warcraftgold.com[/url]
Apart from the low price and fast delivery of Cheap WoW Accounts at alliance-wow-account.com, all players can also enjoy king-like after-sale service after purchase. It is far more better than you have expected. We assure that here is your ideal place to buy wow characters. There is no other places you can be so satisfied. Our professional staff are always working in turn around the clock in order to solve your questions without delay. That is why most of our deals are based on our frequent customers who speak high of our online store. Besides, we offer various payment methods, like Google Checkout, Credit Card, PayPal and MoneyBookers. Of course, WoW accounts without PayPal is also available at our website. Read more: [url=http://www.alliance-wow-account.com] Buy Cheap WOW Account - alliance-wow-account.com [/url]
The online store has 200 cheap wow account in stock. The account covers with all 10 classes, and is at leveling 55 at least! In fact, most of wow accounts here is at level 55. So that they are all ready for creating new Death Knight character. As the gamer just you, we trust each character in WOW has the owner’s emotions. One more thing we have to mention here is that some of top wow accounts here includes more than one characters. But we only price it as single character(the one with the highest leveling). In other words, it is really cheap Wow accounts and you can get cheap wow gold. Read more: [url=http://www.buy-account-us.com] Cheap WOW Accounts - buy-account-us.com[/url]
Buying WoW gold is easy and closer than you think, as you are coming to VCSale! Even though prices fluctuate daily we regularly check to make sure we’re the LOWEST in the WOW GOLD market! Now, our advantages are listed here! Can’t easy purchase, low price and excellent service attract you a bit? 10% off regularly! Flying delivery! Large stock! Professional service team provides advices for you to buy EU cheap wow gold in WoW fast. Read more: [url=http://www.buy-account-eu.com]WoW Account | buy-account-eu.com | buy-account-eu.com[/url]
Frankly speaking, it’s pretty hard to find an online game currency store which is both cheap and safe for wow account. Online frauds happen all the time and it seems hard to avoid it. Situation is different from here! We are one of the most reliable World of Warcraft Gold sellers on the internet. After all these years’hard work, we have become one of the safest Wow Gold suppliers from around the globe. The moment you step into our store to buy cheap wow gold, all your personal information is under our secured guarantee. No need to worry about the safty issue! All you have to do is have some fun! Read more: [url=http://www.cheap-wow-gold-us.com] Cheap WOW Gold - cheap-wow-gold-us.com[/url]
Welcome to WOW world! We are specialized, professional and reliable website for WOW GOLD selling. We supply fast and cheapest wow gold to our loyal and reliable customers .If you want to buy cheap wow gold, please come here. We assure you that you will buy wow gold at a competitive price. With the lowest price and fast delivery speed, as well as good service for you buying wow gold, you will have a lot fun in purchasing wow gold. Read more: [url=http://www.cheap-wow-gold-eu.com] Cheap WoW Gold - cheap-wow-gold-eu.com[/url]
Buy WoW Gold Cheap with Secured Guarantee from here! All your personal information will never be released during Gold for WoW Buying process. Once you come to us, not only can you enjoy cheap wow gold instant delivery, but only safe wow gold online.You can buy WoW Gold EU with PayPal, Credit Card through PayPal and MoneyBookers. If you still have any questions, click Live Chat and get instant help! Read more: [url=http://www.cheapest-wow-gold-us.com] Cheapest WoW Gold - cheapest-wow-gold-us.com[/url]
If you are going to buy Cheapest WoW Gold, then you can make your decision to buy world of warcraft gold in GWW. Only those people who are mining gold 24/7 and selling large quantities of wow gold to other players will have to worry about getting banned. Furthermore, all WoW characters EU at our site is acquired totally by hand, not those that are generated by bots. Read more: [url=http://www.cheapest-wow-gold-eu.com] Cheapest WoW Gold | cheapest-wow-gold-eu.com |cheapest-wow-gold-eu.com[/url]
We buy accounts for most MMO games. Submit all your game account information, click to receive a quote, fill out your information, and you will receive payment for your account within 12 hours. Prices are determined from all categories based on server, level, class, race, gender, equipment, currency, tradeskills, expansions, special abilities and more depending on the game. Read more: [url=http://www.horde-wow-account.com]Buy Accounts | horde-wow-account.com | horde-wow-account.com[/url]
You can Buy Cheap WoW Gold safe without hacks and if there were, it’s not useful oryour account would get banned. We have become one of the safest wow online store after all non-stop hard work. And we continually update our security equipment to guarantee all your account and private information is safe and sound during the whole process from our store. Please feel free to contact our 24/7 live chat if you have any problems. Give it a shot and explore more fun! Read more: [url=http://www.horde-warcraftgold.com] Buy WoW Gold | horde-warcraftgold.com | horde-warcraftgold.com[/url]
# -*- coding: utf-8 -*- """ 金银市场分析程序 - Windows Server 2008 R2 兼容版本 优化内容: 1. 移除win10toast依赖 2. 使用Agg后端,无需图形界面 3. 图表保存为文件而非显示 4. 添加更完善的错误处理 5. 优化内存使用 """ import json from datetime import datetime import matplotlib # 使用Agg后端,无需图形界面 matplotlib.use('Agg') import matplotlib.dates as mdates import matplotlib.pyplot as plt import pandas as pd import requests import os import sys import time import logging from typing import Optional, Tuple import warnings warnings.filterwarnings('ignore') # 设置Matplotlib全局参数 - 使用英文字体避免中文问题 plt.rcParams['font.sans-serif'] = ['DejaVu Sans', 'Arial', 'Helvetica'] plt.rcParams['axes.unicode_minus'] = False # 全局配置 CONFIG = { 'text_fontsize': 9, 'start_year': '2000', 'start_date': '20000101', 'timeout': 30, 'max_retries': 3, 'output_dir': 'precious_metals_analysis' } # 设置日志 def setup_logging(): """配置日志系统""" if not os.path.exists(CONFIG['output_dir']): os.makedirs(CONFIG['output_dir']) logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler(os.path.join(CONFIG['output_dir'], 'analysis.log')), logging.StreamHandler(sys.stdout) ] ) return logging.getLogger(__name__) logger = setup_logging() class NotificationManager: """通知管理器 - 控制台版本""" def send_notification(self, title: str, message: str, duration: int = 3) -> bool: """ 发送控制台通知 Args: title: 通知标题 message: 通知内容 duration: 显示时长(秒) Returns: bool: 是否成功发送 """ try: timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") print(f"\n{'=' * 60}") print(f"📢 {title} - {timestamp}") print(f"📝 {message}") print(f"{'=' * 60}") logger.info(f"{title}: {message}") # 模拟显示时长 if duration > 0: time.sleep(min(duration, 5)) return True except Exception as e: logger.error(f"通知发送失败: {e}") return True # 通知失败不影响主流程 class DataManager: """数据管理器""" def __init__(self, notification_mgr: NotificationManager): self.notification_mgr = notification_mgr self.session = requests.Session() # 设置请求头,模拟浏览器 self.session.headers.update({ 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36' }) def download_with_retry(self, url: str, filename: str, retries: int = None) -> bool: """ 带重试机制的数据下载 Args: url: 下载URL filename: 保存文件名 retries: 重试次数 Returns: bool: 是否成功 """ if retries is None: retries = CONFIG['max_retries'] for attempt in range(retries): try: self.notification_mgr.send_notification( "Download Data", f"Downloading {filename} (Attempt {attempt + 1}/{retries})" ) response = self.session.get(url, timeout=CONFIG['timeout']) response.raise_for_status() with open(filename, 'wb') as f: f.write(response.content) file_size = len(response.content) logger.info(f"Downloaded: {filename} ({file_size} bytes)") self.notification_mgr.send_notification( "Download Complete", f"{filename} downloaded successfully" ) return True except Exception as e: error_msg = f"Download failed (Attempt {attempt + 1}/{retries}): {e}" logger.error(error_msg) if attempt < retries - 1: wait_time = 2 ** attempt # 指数退避 logger.info(f"Waiting {wait_time} seconds before retry...") time.sleep(wait_time) else: self.notification_mgr.send_notification( "Download Error", f"{filename} download failed" ) return False def process_json_data(self, filename: str, column_name: str) -> Optional[pd.DataFrame]: """ 处理JSON数据文件 Args: filename: JSON文件名 column_name: 数据列名 Returns: Optional[pd.DataFrame]: 处理后的DataFrame """ try: # 检查文件是否存在 if not os.path.exists(filename): logger.error(f"File not found: {filename}") return None with open(filename, 'r', encoding='utf-8') as f: data = json.load(f) # 创建DataFrame df = pd.json_normalize(data) # 检查必要列是否存在 if 'v' not in df.columns: logger.error(f"Required column 'v' not found in {filename}") return None # 处理价格数据列 price_cols = df['v'].apply(pd.Series) price_cols.columns = ['USD', 'GBP', 'EUR'] # 清理数据 columns_to_drop = ['is_cms_locked', 'v'] for col in columns_to_drop: if col in df.columns: df.drop(col, axis=1, inplace=True) df = pd.concat([df, price_cols['USD']], axis=1) # 重命名列 df = df.rename(columns={'d': 'date', 'USD': column_name}) # 日期处理 df['date'] = pd.to_datetime(df['date']) df.set_index('date', inplace=True) # 筛选数据范围 start_date = datetime.strptime(CONFIG['start_date'], "%Y%m%d") df = df[df.index >= start_date] # 检查数据是否为空 if df.empty: logger.warning(f"No data found after filtering for {filename}") return None df.reset_index(inplace=True) logger.info(f"Processed {filename}: {len(df)} records") return df except Exception as e: error_msg = f"Error processing file {filename}: {e}" logger.error(error_msg) self.notification_mgr.send_notification("Data Processing Error", error_msg) return None def combine_metal_data(self) -> Optional[pd.DataFrame]: """ 组合金银数据 Returns: Optional[pd.DataFrame]: 组合后的数据 """ try: self.notification_mgr.send_notification("Data Processing", "Processing gold and silver data") # 处理黄金数据 gold_df = self.process_json_data('gold.json', 'gold') if gold_df is None: return None # 处理白银数据 silver_df = self.process_json_data('silver.json', 'silver') if silver_df is None: return None # 合并数据 merged_df = pd.merge(gold_df, silver_df, on='date', how='inner') # 检查合并结果 if merged_df.empty: logger.error("No common dates found between gold and silver data") return None # 数据转换和计算 initial_gold = merged_df['gold'].iloc[0] initial_silver = merged_df['silver'].iloc[0] # 白银价格标准化(基于初始值的相对变化) merged_df['silver_normalized'] = round( merged_df['silver'] * initial_gold / initial_silver, 2 ) # 计算金银比 merged_df['ratio'] = round(merged_df['gold'] / merged_df['silver'], 2) # 计算分位值 merged_df['ratio_70th'] = round(merged_df['ratio'].quantile(0.7), 2) merged_df['ratio_30th'] = round(merged_df['ratio'].quantile(0.3), 2) # 确保输出目录存在 if not os.path.exists(CONFIG['output_dir']): os.makedirs(CONFIG['output_dir']) # 保存到CSV output_path = os.path.join(CONFIG['output_dir'], "precious_metals_data.csv") merged_df.to_csv(output_path, index=False, encoding='utf-8') logger.info(f"Data combination completed and saved to {output_path}") self.notification_mgr.send_notification( "Data Processing Complete", f"Gold and silver data combined: {len(merged_df)} records" ) return merged_df except Exception as e: error_msg = f"Data combination failed: {e}" logger.error(error_msg) self.notification_mgr.send_notification("Data Combination Error", error_msg) return None class ChartManager: """图表管理器 - 保存为文件版本""" def __init__(self, notification_mgr: NotificationManager): self.notification_mgr = notification_mgr # 确保输出目录存在 if not os.path.exists(CONFIG['output_dir']): os.makedirs(CONFIG['output_dir']) def create_price_comparison_chart(self, df: pd.DataFrame) -> bool: """创建金银价格对比图并保存为文件""" try: # 创建更小的图表以适应服务器环境 fig, ax1 = plt.subplots(figsize=(10, 6)) fig.set_facecolor('#f8f9fa') ax1.set_facecolor('#ffffff') x = df['date'] gold_prices = df['gold'] silver_prices = df['silver'] # 绘制黄金价格 ax1.plot(x, gold_prices, label='Gold', color='#FFD700', linewidth=2.0, alpha=0.8) ax1.set_ylabel('Gold Price (USD/oz)', fontsize=10, color='#FFD700') ax1.tick_params(axis='y', labelcolor='#FFD700') ax1.grid(True, alpha=0.3) # 标注黄金极值 gold_max_idx = gold_prices.idxmax() gold_min_idx = gold_prices.idxmin() ax1.annotate(f'High: {gold_prices[gold_max_idx]:.0f}', xy=(x[gold_max_idx], gold_prices[gold_max_idx]), xytext=(10, 10), textcoords='offset points', bbox=dict(boxstyle='round,pad=0.3', facecolor='#FFD700', alpha=0.7), fontsize=8) # 创建第二个y轴用于白银 ax2 = ax1.twinx() ax2.plot(x, silver_prices, label='Silver', color='#C0C0C0', linewidth=2.0, alpha=0.8) ax2.set_ylabel('Silver Price (USD/oz)', fontsize=10, color='#C0C0C0') ax2.tick_params(axis='y', labelcolor='#C0C0C0') # 标注白银极值 silver_max_idx = silver_prices.idxmax() ax2.annotate(f'High: {silver_prices[silver_max_idx]:.2f}', xy=(x[silver_max_idx], silver_prices[silver_max_idx]), xytext=(10, -15), textcoords='offset points', bbox=dict(boxstyle='round,pad=0.3', facecolor='#C0C0C0', alpha=0.7), fontsize=8) # 设置标题和格式 ax1.set_title(f'{CONFIG["start_year"]}-2025 Gold vs Silver Price Comparison', fontsize=12, fontweight='bold', pad=15) ax1.set_xlabel('Date', fontsize=10) # 合并图例 lines1, labels1 = ax1.get_legend_handles_labels() lines2, labels2 = ax2.get_legend_handles_labels() ax1.legend(lines1 + lines2, labels1 + labels2, loc='upper left', framealpha=0.9) # 设置x轴刻度 ax1.xaxis.set_major_locator(mdates.YearLocator(2)) plt.xticks(rotation=45) plt.tight_layout() # 保存图表 chart_path = os.path.join(CONFIG['output_dir'], "gold_silver_comparison.png") plt.savefig(chart_path, dpi=150, bbox_inches='tight') plt.close(fig) # 关闭图表释放内存 self.notification_mgr.send_notification( "Chart Generated", f"Price comparison chart saved to {chart_path}" ) return True except Exception as e: error_msg = f"Price comparison chart generation failed: {str(e)}" logger.error(error_msg) self.notification_mgr.send_notification("Chart Error", error_msg) return False def create_ratio_chart(self, df: pd.DataFrame) -> bool: """创建金银比图表并保存为文件""" try: fig, ax = plt.subplots(figsize=(10, 6)) fig.set_facecolor('#f8f9fa') ax.set_facecolor('#ffffff') x = df['date'] ratio = df['ratio'] ratio_70 = df['ratio_70th'].iloc[0] ratio_30 = df['ratio_30th'].iloc[0] # 绘制金银比 ax.plot(x, ratio, label='Gold/Silver Ratio', color='#1f77b4', linewidth=2.0, alpha=0.8) ax.set_ylabel('Gold/Silver Ratio', fontsize=10) ax.grid(True, alpha=0.3) # 添加分位线 ax.axhline(y=ratio_70, color='#ff7f0e', linestyle='--', alpha=0.7, label=f'70th Percentile: {ratio_70:.1f}') ax.axhline(y=ratio_30, color='#2ca02c', linestyle='--', alpha=0.7, label=f'30th Percentile: {ratio_30:.1f}') # 填充分位区域 ax.fill_between(x, ratio_30, ratio_70, alpha=0.2, color='gray', label='Normal Range') # 标注极值 max_idx = ratio.idxmax() min_idx = ratio.idxmin() ax.annotate(f'Peak: {ratio[max_idx]:.1f}', xy=(x[max_idx], ratio[max_idx]), xytext=(10, 10), textcoords='offset points', bbox=dict(boxstyle='round,pad=0.3', facecolor='lightblue', alpha=0.7), fontsize=8) ax.set_title(f'{CONFIG["start_year"]}-2025 Gold/Silver Ratio Analysis', fontsize=12, fontweight='bold', pad=15) ax.set_xlabel('Date', fontsize=10) ax.legend(loc='upper left', framealpha=0.9) # 设置x轴刻度 ax.xaxis.set_major_locator(mdates.YearLocator(2)) plt.xticks(rotation=45) plt.tight_layout() # 保存图表 chart_path = os.path.join(CONFIG['output_dir'], "gold_silver_ratio.png") plt.savefig(chart_path, dpi=150, bbox_inches='tight') plt.close(fig) # 关闭图表释放内存 self.notification_mgr.send_notification( "Chart Generated", f"Ratio chart saved to {chart_path}" ) return True except Exception as e: error_msg = f"Ratio chart generation failed: {str(e)}" logger.error(error_msg) self.notification_mgr.send_notification("Chart Error", error_msg) return False def create_combined_chart(self, df: pd.DataFrame) -> bool: """创建组合图表并保存为文件""" try: fig, ax1 = plt.subplots(figsize=(12, 7)) fig.set_facecolor('#f8f9fa') ax1.set_facecolor('#ffffff') x = df['date'] gold_prices = df['gold'] silver_normalized = df['silver_normalized'] ratio = df['ratio'] # 左侧Y轴 - 价格 ax1.plot(x, gold_prices, label='Gold Price', color='#FFD700', linewidth=2.0) ax1.plot(x, silver_normalized, label='Silver (Normalized)', color='#C0C0C0', linewidth=2.0, linestyle='--') ax1.set_ylabel('Price (USD/oz)', fontsize=10) ax1.grid(True, alpha=0.3) # 右侧Y轴 - 金银比 ax2 = ax1.twinx() ax2.plot(x, ratio, label='Gold/Silver Ratio', color='#1f77b4', linewidth=1.5, alpha=0.7) ax2.set_ylabel('Gold/Silver Ratio', fontsize=10, color='#1f77b4') ax2.tick_params(axis='y', labelcolor='#1f77b4') # 添加分位线 ratio_70 = df['ratio_70th'].iloc[0] ratio_30 = df['ratio_30th'].iloc[0] ax2.axhline(y=ratio_70, color='red', linestyle=':', alpha=0.6, label='70th %') ax2.axhline(y=ratio_30, color='green', linestyle=':', alpha=0.6, label='30th %') ax1.set_title(f'{CONFIG["start_year"]}-2025 Comprehensive Precious Metals Analysis', fontsize=12, fontweight='bold', pad=15) ax1.set_xlabel('Date', fontsize=10) # 合并图例 lines1, labels1 = ax1.get_legend_handles_labels() lines2, labels2 = ax2.get_legend_handles_labels() ax1.legend(lines1 + lines2, labels1 + labels2, loc='upper left', framealpha=0.9) # 设置x轴刻度 ax1.xaxis.set_major_locator(mdates.YearLocator(2)) plt.xticks(rotation=45) plt.tight_layout() # 保存图表 chart_path = os.path.join(CONFIG['output_dir'], "comprehensive_analysis.png") plt.savefig(chart_path, dpi=150, bbox_inches='tight') plt.close(fig) # 关闭图表释放内存 self.notification_mgr.send_notification( "Chart Generated", f"Comprehensive chart saved to {chart_path}" ) return True except Exception as e: error_msg = f"Combined chart generation failed: {str(e)}" logger.error(error_msg) self.notification_mgr.send_notification("Chart Error", error_msg) return False class AnalysisReporter: """分析报告生成器""" @staticmethod def generate_report(df: pd.DataFrame) -> bool: """生成分析报告""" try: # 基本统计 gold_stats = { 'mean': df['gold'].mean(), 'max': df['gold'].max(), 'min': df['gold'].min(), 'current': df['gold'].iloc[-1], 'max_date': df.loc[df['gold'].idxmax(), 'date'].strftime('%Y-%m-%d') } silver_stats = { 'mean': df['silver'].mean(), 'max': df['silver'].max(), 'min': df['silver'].min(), 'current': df['silver'].iloc[-1], 'max_date': df.loc[df['silver'].idxmax(), 'date'].strftime('%Y-%m-%d') } ratio_stats = { 'mean': df['ratio'].mean(), 'max': df['ratio'].max(), 'min': df['ratio'].min(), 'current': df['ratio'].iloc[-1], 'max_date': df.loc[df['ratio'].idxmax(), 'date'].strftime('%Y-%m-%d') } # 生成报告 report_lines = [] report_lines.append("=" * 70) report_lines.append("PRECIOUS METALS ANALYSIS REPORT") report_lines.append("=" * 70) report_lines.append(f"\nBASIC STATISTICS ({CONFIG['start_year']}-2025):") report_lines.append(f" Gold: Avg=${gold_stats['mean']:.2f}, High=${gold_stats['max']:.2f} " f"(on {gold_stats['max_date']}), Current=${gold_stats['current']:.2f}") report_lines.append(f" Silver: Avg=${silver_stats['mean']:.2f}, High=${silver_stats['max']:.2f} " f"(on {silver_stats['max_date']}), Current=${silver_stats['current']:.2f}") report_lines.append(f" Gold/Silver Ratio: Avg={ratio_stats['mean']:.2f}, " f"Range[{ratio_stats['min']:.1f}-{ratio_stats['max']:.1f}], " f"Current={ratio_stats['current']:.2f}") report_lines.append(f"\nPERCENTILE ANALYSIS:") report_lines.append(f" 70th Percentile: {df['ratio_70th'].iloc[0]:.2f}") report_lines.append(f" 30th Percentile: {df['ratio_30th'].iloc[0]:.2f}") current_ratio = ratio_stats['current'] ratio_70 = df['ratio_70th'].iloc[0] ratio_30 = df['ratio_30th'].iloc[0] if current_ratio > ratio_70: status = "HIGH (Silver relatively undervalued)" elif current_ratio < ratio_30: status = "LOW (Gold relatively undervalued)" else: status = "NORMAL" report_lines.append(f" Current Ratio Status: {status}") report_lines.append(f"\nRECENT TREND (Last 5 trading days):") recent = df.tail()[['date', 'gold', 'silver', 'ratio']].copy() recent['date'] = recent['date'].dt.strftime('%Y-%m-%d') # 格式化近期数据表格 report_lines.append(" Date | Gold | Silver | Ratio") report_lines.append(" " + "-" * 40) for _, row in recent.iterrows(): report_lines.append( f" {row['date']} | ${row['gold']:7.2f} | ${row['silver']:6.2f} | {row['ratio']:5.1f}") report_lines.append(f"\nINVESTMENT INSIGHTS:") if status == "HIGH (Silver relatively undervalued)": report_lines.append(" Consider increasing silver allocation - silver is relatively cheap vs gold") elif status == "LOW (Gold relatively undervalued)": report_lines.append(" Consider increasing gold allocation - gold is relatively cheap vs silver") else: report_lines.append(" Current ratio is in normal range - maintain balanced allocation") report_lines.append("=" * 70) # 输出到控制台 report_text = "\n".join(report_lines) print(report_text) # 保存到文件 report_path = os.path.join(CONFIG['output_dir'], "analysis_report.txt") with open(report_path, 'w', encoding='utf-8') as f: f.write(report_text) logger.info(f"Analysis report generated and saved to {report_path}") return True except Exception as e: logger.error(f"Report generation failed: {e}") return False def check_system_compatibility(): """检查系统兼容性""" logger.info("Checking system compatibility...") # 检查Python版本 python_version = sys.version_info logger.info(f"Python version: {python_version.major}.{python_version.minor}.{python_version.micro}") # 检查必要包 required_packages = ['pandas', 'matplotlib', 'requests'] for package in required_packages: try: __import__(package) logger.info(f"✓ {package} is available") except ImportError: logger.error(f"✗ {package} is not available") return False # 检查磁盘空间 try: import shutil total, used, free = shutil.disk_usage(".") free_gb = free // (2 ** 30) logger.info(f"Disk space: {free_gb} GB free") if free_gb < 1: logger.warning("Low disk space warning") except: logger.warning("Could not check disk space") return True def main(): """主程序""" logger.info("Starting Precious Metals Analysis Program...") # 检查兼容性 if not check_system_compatibility(): logger.error("System compatibility check failed") return # 初始化管理器 notification_mgr = NotificationManager() data_mgr = DataManager(notification_mgr) chart_mgr = ChartManager(notification_mgr) # 发送启动通知 notification_mgr.send_notification( "Precious Metals Analysis", "Program starting...", duration=2 ) try: # 数据源URL data_sources = { 'gold.json': 'https://prices.lbma.org.uk/json/gold_pm.json', 'silver.json': 'https://prices.lbma.org.uk/json/silver.json' } # 添加时间戳参数避免缓存 timestamp = int(time.time()) data_sources = { 'gold.json': f'https://prices.lbma.org.uk/json/gold_pm.json?r={timestamp}', 'silver.json': f'https://prices.lbma.org.uk/json/silver.json?r={timestamp}' } # 下载数据 download_success = all( data_mgr.download_with_retry(url, filename) for filename, url in data_sources.items() ) if not download_success: logger.error("Data download failed, program exiting") return # 处理数据 combined_data = data_mgr.combine_metal_data() if combined_data is None: logger.error("Data processing failed, program exiting") return # 生成分析报告 AnalysisReporter.generate_report(combined_data) # 生成图表 charts_created = 0 if chart_mgr.create_price_comparison_chart(combined_data): charts_created += 1 if chart_mgr.create_ratio_chart(combined_data): charts_created += 1 if chart_mgr.create_combined_chart(combined_data): charts_created += 1 # 完成通知 output_dir = os.path.abspath(CONFIG['output_dir']) notification_mgr.send_notification( "Analysis Complete", f"Program finished successfully! Generated {charts_created} charts\n" f"Output directory: {output_dir}", duration=5 ) logger.info(f"Program completed successfully! Generated {charts_created} charts") except KeyboardInterrupt: logger.info("Program interrupted by user") notification_mgr.send_notification("Program Interrupted", "User cancelled operation") except Exception as e: error_msg = f"Program execution failed: {str(e)}" logger.error(error_msg) notification_mgr.send_notification("Program Error", error_msg) import traceback traceback.print_exc() if __name__ == "__main__": main() 优化代码可以打包成windows server 2008 R2可以使用的程序
10-09
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值