This commit is contained in:
lz_db
2025-11-16 12:31:03 +08:00
commit 0fab423a18
1451 changed files with 743213 additions and 0 deletions

153
test/_test_mt5_fixed.py Normal file
View File

@@ -0,0 +1,153 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import asyncio
import logging
import sys
import os
# 添加 ccxt 路径
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from ccxt import mt5 as mt5_sync
from ccxt.async_support import mt5 as mt5_async
# 配置日志
logging.basicConfig(level=logging.INFO, format='%(message)s')
logger = logging.getLogger('MT5-Fixed-Test')
# 测试配置 - 使用你的配置
TEST_CONFIG = {
'apiKey': '76888962',
'secret': 'LZ-trade666888',
'hostname': '43.167.188.220:5000',
'host': '18.163.85.196',
'port': 443,
'sandbox': True,
'verbose': True,
}
def test_url_fix():
"""测试 URL 修复"""
logger.info("🔧 测试 URL 修复...")
try:
exchange = mt5_sync(TEST_CONFIG)
# 检查 URLs 配置
logger.info("检查 URLs 配置:")
logger.info(f" Public API: {exchange.urls['api']['public']}")
logger.info(f" Private API: {exchange.urls['api']['private']}")
# 测试连接
logger.info("\n测试连接...")
token = exchange.get_token()
logger.info(f"✅ 连接成功! Token: {token}")
return True
except Exception as e:
logger.error(f"❌ 测试失败: {e}")
import traceback
traceback.print_exc()
return False
async def test_async_url_fix():
"""测试异步 URL 修复"""
logger.info("\n🔧 测试异步 URL 修复...")
exchange = None
try:
exchange = mt5_async(TEST_CONFIG)
# 检查 URLs 配置
logger.info("检查异步 URLs 配置:")
logger.info(f" Public API: {exchange.urls['api']['public']}")
logger.info(f" Private API: {exchange.urls['api']['private']}")
# 测试连接
logger.info("\n测试异步连接...")
token = await exchange.get_token()
logger.info(f"✅ 异步连接成功! Token: {token}")
return True
except Exception as e:
logger.error(f"❌ 异步测试失败: {e}")
import traceback
traceback.print_exc()
return False
finally:
if exchange:
await exchange.close()
def test_direct_connection():
"""测试直接连接"""
logger.info("\n🔧 测试直接连接...")
try:
# 使用 requests 直接测试连接
import requests
url = "http://43.167.188.220:5000/Connect"
params = {
'user': '76888962',
'password': 'LZ-trade666888',
'host': '18.163.85.196',
'port': 443,
'connectTimeoutSeconds': 30
}
logger.info(f"测试直接请求: {url}")
response = requests.get(url, params=params, timeout=30)
logger.info(f"状态码: {response.status_code}")
logger.info(f"响应内容: {response.text}")
if response.status_code == 200:
logger.info("✅ 直接连接成功!")
return True
else:
logger.error(f"❌ 直接连接失败: {response.status_code}")
return False
except Exception as e:
logger.error(f"❌ 直接连接测试失败: {e}")
return False
async def main():
"""运行修复测试"""
print("🚀 MT5 URL 修复测试")
print("="*50)
# 测试直接连接
direct_success = test_direct_connection()
# 测试同步版本
sync_success = test_url_fix()
# 测试异步版本
async_success = await test_async_url_fix()
print("\n" + "="*50)
print("📊 修复测试结果")
print(f"直接连接: {'✅ 通过' if direct_success else '❌ 失败'}")
print(f"同步版本: {'✅ 通过' if sync_success else '❌ 失败'}")
print(f"异步版本: {'✅ 通过' if async_success else '❌ 失败'}")
if direct_success and sync_success and async_success:
print("🎉 所有修复测试通过!")
else:
print("\n⚠️ 如果直接连接失败,请检查:")
print(" 1. 网络连接是否正常")
print(" 2. 服务器地址是否正确")
print(" 3. 防火墙设置")
print(" 4. 服务器状态")
if __name__ == "__main__":
asyncio.run(main())

134
test/_test_mt5_manual.py Normal file
View File

@@ -0,0 +1,134 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import requests
import asyncio
import aiohttp
import logging
logging.basicConfig(level=logging.INFO, format='%(message)s')
logger = logging.getLogger('MT5-Manual-Test')
# 配置
CONFIG = {
'user': '76888962',
'password': 'LZ-trade666888',
'host': '18.163.85.196',
'port': 443,
'connectTimeoutSeconds': 30
}
BASE_URL = "http://43.167.188.220:5000"
def test_manual_connect():
"""手动测试连接"""
logger.info("🔧 手动测试连接...")
try:
url = f"{BASE_URL}/Connect"
logger.info(f"请求URL: {url}")
logger.info(f"请求参数: {CONFIG}")
response = requests.get(url, params=CONFIG, timeout=30)
logger.info(f"状态码: {response.status_code}")
logger.info(f"响应头: {dict(response.headers)}")
logger.info(f"响应内容: {response.text}")
if response.status_code == 200:
token = response.text
logger.info(f"✅ 连接成功! Token: {token}")
# 测试其他端点
test_other_endpoints(token)
return True
else:
logger.error(f"❌ 连接失败: {response.status_code}")
return False
except requests.exceptions.RequestException as e:
logger.error(f"❌ 请求异常: {e}")
return False
except Exception as e:
logger.error(f"❌ 未知错误: {e}")
return False
def test_other_endpoints(token):
"""测试其他端点"""
logger.info("\n🔧 测试其他端点...")
endpoints = [
'/CheckConnect',
'/AccountSummary',
'/Symbols',
'/GetQuote?symbol=EURUSD'
]
for endpoint in endpoints:
try:
url = f"{BASE_URL}{endpoint}"
params = {'id': token}
logger.info(f"测试端点: {endpoint}")
response = requests.get(url, params=params, timeout=10)
logger.info(f" 状态码: {response.status_code}")
if response.status_code == 200:
logger.info(f" ✅ 成功")
if len(response.text) < 100: # 避免输出过长
logger.info(f" 响应: {response.text}")
else:
logger.error(f" ❌ 失败")
except Exception as e:
logger.error(f" ❌ 错误: {e}")
async def test_async_manual():
"""异步手动测试"""
logger.info("\n🔧 异步手动测试...")
try:
url = f"{BASE_URL}/Connect"
async with aiohttp.ClientSession() as session:
logger.info(f"异步请求URL: {url}")
async with session.get(url, params=CONFIG, timeout=30) as response:
logger.info(f"异步状态码: {response.status}")
text = await response.text()
logger.info(f"异步响应: {text}")
if response.status == 200:
logger.info("✅ 异步连接成功!")
return True
else:
logger.error("❌ 异步连接失败!")
return False
except Exception as e:
logger.error(f"❌ 异步测试失败: {e}")
return False
def main():
"""运行手动测试"""
print("🚀 MT5 手动连接测试")
print("="*50)
# 同步测试
sync_success = test_manual_connect()
# 异步测试
async_success = asyncio.run(test_async_manual())
print("\n" + "="*50)
print("📊 手动测试结果")
print(f"同步测试: {'✅ 通过' if sync_success else '❌ 失败'}")
print(f"异步测试: {'✅ 通过' if async_success else '❌ 失败'}")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,529 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import asyncio
import logging
import sys
import os
from datetime import datetime
# 添加 ccxt 路径
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from ccxt import mt5 as mt5_sync
from ccxt.async_support import mt5 as mt5_async
from ccxt.pro import mt5 as mt5_pro
from ccxt.base.errors import ExchangeError, AuthenticationError, InvalidOrder
# 配置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.StreamHandler(),
logging.FileHandler('mt5_test.log', encoding='utf-8')
]
)
logger = logging.getLogger('MT5-Test')
# 测试配置
TEST_CONFIG = {
'apiKey': '76888962',
'secret': 'LZ-trade666888',
'verbose': False, # 启用详细日志
'hostname': '43.167.188.220:5000',
'host': '18.163.85.196',
'port': 443,
}
class MT5SyncTest:
"""同步版本测试"""
def __init__(self):
self.exchange = mt5_sync(TEST_CONFIG)
self.test_results = {}
def run_all_tests(self):
"""运行所有同步测试"""
logger.info("🚀 开始同步版本测试")
tests = [
self.test_connection,
self.test_token_management,
self.test_markets,
self.test_balance,
self.test_ticker,
self.test_account_details,
self.test_orders,
self.test_order_operations,
]
for test in tests:
try:
test_name = test.__name__
logger.info(f"\n{'='*50}")
logger.info(f"执行测试: {test_name}")
logger.info(f"{'='*50}")
result = test()
self.test_results[test_name] = result
status = "✅ 通过" if result else "❌ 失败"
logger.info(f"{status} - {test_name}")
except Exception as e:
logger.error(f"❌ 测试失败 {test.__name__}: {e}")
self.test_results[test.__name__] = False
self.print_test_summary()
return self.test_results
def test_connection(self):
"""测试连接"""
try:
logger.info("测试服务器连接...")
result = self.exchange.ping_server()
logger.info(f"Ping 结果: {result}")
return result is True
except Exception as e:
logger.error(f"连接测试失败: {e}")
return False
def test_token_management(self):
"""测试 Token 管理"""
try:
logger.info("测试 Token 获取...")
token = self.exchange.get_token()
logger.info(f"获取到 Token: {token}")
# logger.info("测试连接检查...")
# check_result = self.exchange.check_connect()
# logger.info(f"连接检查: {check_result}")
logger.info("测试服务器时区...")
timezone = self.exchange.server_timezone()
logger.info(f"服务器时区: {timezone}")
return token is not None and timezone is not None
except Exception as e:
logger.error(f"Token 管理测试失败: {e}")
return False
def test_markets(self):
"""测试市场数据"""
try:
logger.info("获取交易对列表...")
markets = self.exchange.fetch_markets()
logger.info(f"获取到 {len(markets)} 个交易对")
# 显示前5个交易对
for i, market in enumerate(markets[:5]):
logger.info(f" {i+1}. {market['symbol']} - {market['base']}/{market['quote']}")
if len(markets) > 5:
logger.info(f" ... 还有 {len(markets) - 5} 个交易对")
return len(markets) > 0
except Exception as e:
logger.error(f"市场数据测试失败: {e}")
return False
def test_balance(self):
"""测试余额查询"""
try:
logger.info("获取账户余额...")
balance = self.exchange.fetch_balance()
logger.info(f"余额信息: {balance}")
if 'USDT' in balance['total']:
total = balance['total']['USDT']
free = balance['free']['USDT']
used = balance['used']['USDT']
logger.info(f"USDT 余额 - 总额: {total}, 可用: {free}, 占用: {used}")
return balance is not None
except Exception as e:
logger.error(f"余额查询测试失败: {e}")
return False
def test_ticker(self):
"""测试行情数据"""
try:
symbols_to_test = ['EUR/USD', 'GBP/USD', 'USD/JPY']
for symbol in symbols_to_test:
try:
logger.info(f"获取 {symbol} 行情...")
ticker = self.exchange.fetch_ticker(symbol)
if ticker:
logger.info(f" {symbol}: 买={ticker['bid']}, 卖={ticker['ask']}, 最后={ticker['last']}")
else:
logger.warning(f" 无法获取 {symbol} 行情")
except Exception as e:
logger.warning(f" 获取 {symbol} 行情失败: {e}")
# 测试批量获取行情
logger.info("测试批量获取行情...")
tickers = self.exchange.fetch_tickers(['EUR/USD', 'GBP/USD'])
logger.info(f"批量获取到 {len(tickers)} 个行情")
return True
except Exception as e:
logger.error(f"行情数据测试失败: {e}")
return False
def test_account_details(self):
"""测试账户详情"""
try:
logger.info("获取账户详情...")
account_details = self.exchange.fetch_account_details()
logger.info(f"账户详情: {account_details}")
required_fields = ['serverName', 'user', 'currency', 'accountLeverage']
for field in required_fields:
if field in account_details:
logger.info(f" {field}: {account_details[field]}")
return account_details is not None
except Exception as e:
logger.error(f"账户详情测试失败: {e}")
return False
def test_orders(self):
"""测试订单查询"""
try:
logger.info("获取未平仓订单...")
open_orders = self.exchange.fetch_open_orders()
logger.info(f"未平仓订单数量: {len(open_orders)}")
for order in open_orders[:3]: # 显示前3个订单
logger.info(f" 订单 {order['id']}: {order['symbol']} {order['side']} {order['type']} {order['status']}")
logger.info("获取已平仓订单...")
closed_orders = self.exchange.fetch_closed_orders()
logger.info(f"已平仓订单数量: {len(closed_orders)}")
return True
except Exception as e:
logger.error(f"订单查询测试失败: {e}")
return False
def test_order_operations(self):
"""测试订单操作(只测试不实际下单)"""
try:
logger.info("测试订单创建参数验证...")
# 测试市价单参数
market_order_params = {
'symbol': 'EUR/USD',
'type': 'market',
'side': 'buy',
'amount': 0.01,
}
# 测试限价单参数
limit_order_params = {
'symbol': 'EUR/USD',
'type': 'limit',
'side': 'buy',
'amount': 0.01,
'price': 1.0800,
}
logger.info("✅ 订单参数验证通过")
logger.info("注意: 实际下单测试需要在真实环境中进行")
return True
except Exception as e:
logger.error(f"订单操作测试失败: {e}")
return False
def print_test_summary(self):
"""打印测试总结"""
logger.info("\n" + "="*60)
logger.info("📊 同步版本测试总结")
logger.info("="*60)
passed = sum(1 for result in self.test_results.values() if result)
total = len(self.test_results)
for test_name, result in self.test_results.items():
status = "✅ 通过" if result else "❌ 失败"
logger.info(f" {test_name}: {status}")
logger.info(f"\n总体结果: {passed}/{total} 通过")
if passed == total:
logger.info("🎉 所有测试通过!")
else:
logger.info("⚠️ 部分测试失败,请检查日志")
class MT5AsyncTest:
"""异步版本测试"""
def __init__(self):
self.exchange = None
self.test_results = {}
async def initialize(self):
"""初始化异步交易所"""
self.exchange = mt5_async(TEST_CONFIG)
async def run_all_tests(self):
"""运行所有异步测试"""
logger.info("\n🚀 开始异步版本测试")
await self.initialize()
tests = [
self.test_connection_async,
self.test_markets_async,
self.test_balance_async,
self.test_ticker_async,
self.test_orders_async,
]
for test in tests:
try:
test_name = test.__name__
logger.info(f"\n{'='*50}")
logger.info(f"执行测试: {test_name}")
logger.info(f"{'='*50}")
result = await test()
self.test_results[test_name] = result
status = "✅ 通过" if result else "❌ 失败"
logger.info(f"{status} - {test_name}")
except Exception as e:
logger.error(f"❌ 测试失败 {test.__name__}: {e}")
self.test_results[test.__name__] = False
await self.exchange.close()
self.print_test_summary()
return self.test_results
async def test_connection_async(self):
"""测试异步连接"""
try:
logger.info("测试异步 Token 获取...")
token = await self.exchange.get_token()
logger.info(f"获取到 Token: {token}")
return token is not None
except Exception as e:
logger.error(f"异步连接测试失败: {e}")
return False
async def test_markets_async(self):
"""测试异步市场数据"""
try:
logger.info("获取异步交易对列表...")
markets = await self.exchange.fetch_markets()
logger.info(f"获取到 {len(markets)} 个交易对")
return len(markets) > 0
except Exception as e:
logger.error(f"异步市场数据测试失败: {e}")
return False
async def test_balance_async(self):
"""测试异步余额查询"""
try:
logger.info("获取异步账户余额...")
balance = await self.exchange.fetch_balance()
logger.info(f"余额信息: {balance}")
return balance is not None
except Exception as e:
logger.error(f"异步余额查询测试失败: {e}")
return False
async def test_ticker_async(self):
"""测试异步行情数据"""
try:
logger.info("获取异步行情...")
ticker = await self.exchange.fetch_ticker('EUR/USD')
logger.info(f"EUR/USD: 买={ticker['bid']}, 卖={ticker['ask']}")
return ticker is not None
except Exception as e:
logger.error(f"异步行情数据测试失败: {e}")
return False
async def test_orders_async(self):
"""测试异步订单查询"""
try:
logger.info("获取异步未平仓订单...")
open_orders = await self.exchange.fetch_open_orders()
logger.info(f"未平仓订单数量: {len(open_orders)}")
return True
except Exception as e:
logger.error(f"异步订单查询测试失败: {e}")
return False
def print_test_summary(self):
"""打印测试总结"""
logger.info("\n" + "="*60)
logger.info("📊 异步版本测试总结")
logger.info("="*60)
passed = sum(1 for result in self.test_results.values() if result)
total = len(self.test_results)
for test_name, result in self.test_results.items():
status = "✅ 通过" if result else "❌ 失败"
logger.info(f" {test_name}: {status}")
logger.info(f"\n总体结果: {passed}/{total} 通过")
class MT5WebSocketTest:
"""WebSocket 测试"""
def __init__(self):
self.exchange = None
self.received_messages = []
async def initialize(self):
"""初始化 WebSocket 交易所"""
self.exchange = mt5_pro(TEST_CONFIG)
async def test_websocket_orders(self):
"""测试 WebSocket 订单监听"""
try:
await self.initialize()
logger.info("\n🔌 开始 WebSocket 订单监听测试")
logger.info("监听订单更新...")
# 设置超时
timeout = 30 # 30秒后停止监听
async def order_listener():
try:
orders = await self.exchange.watch_orders()
logger.info(f"📦 收到订单更新: {len(orders)} 个订单")
for order in orders:
logger.info(f" 订单 {order['id']}: {order['symbol']} {order['side']} {order['status']}")
self.received_messages.append({
'type': 'order',
'data': order,
'timestamp': datetime.now()
})
except Exception as e:
logger.error(f"订单监听错误: {e}")
# 运行监听器
await asyncio.wait_for(order_listener(), timeout=timeout)
return len(self.received_messages) > 0
except asyncio.TimeoutError:
logger.info("⏰ WebSocket 监听超时(正常结束)")
return len(self.received_messages) > 0
except Exception as e:
logger.error(f"WebSocket 测试失败: {e}")
return False
finally:
if self.exchange:
await self.exchange.close()
async def test_websocket_balance(self):
"""测试 WebSocket 余额监听"""
try:
await self.initialize()
logger.info("\n💰 开始 WebSocket 余额监听测试")
logger.info("监听余额更新...")
timeout = 20 # 20秒后停止监听
async def balance_listener():
try:
balance = await self.exchange.watch_balance()
logger.info(f"💰 收到余额更新")
logger.info(f" 余额信息: {balance}")
self.received_messages.append({
'type': 'balance',
'data': balance,
'timestamp': datetime.now()
})
except Exception as e:
logger.error(f"余额监听错误: {e}")
await asyncio.wait_for(balance_listener(), timeout=timeout)
return len([msg for msg in self.received_messages if msg['type'] == 'balance']) > 0
except asyncio.TimeoutError:
logger.info("⏰ WebSocket 余额监听超时(正常结束)")
return len([msg for msg in self.received_messages if msg['type'] == 'balance']) > 0
except Exception as e:
logger.error(f"WebSocket 余额测试失败: {e}")
return False
finally:
if self.exchange:
await self.exchange.close()
async def main():
"""主测试函数"""
print("="*70)
print("MT5 集成测试套件")
print("="*70)
# 同步测试
sync_test = MT5SyncTest()
sync_results = sync_test.run_all_tests()
# 异步测试
async_test = MT5AsyncTest()
async_results = await async_test.run_all_tests()
# WebSocket 测试
ws_test = MT5WebSocketTest()
print("\n" + "="*70)
print("🔌 WebSocket 测试(需要实际交易活动)")
print("="*70)
ws_order_result = await ws_test.test_websocket_orders()
ws_balance_result = await ws_test.test_websocket_balance()
# 最终总结
print("\n" + "="*70)
print("🎯 最终测试总结")
print("="*70)
sync_passed = sum(1 for result in sync_results.values() if result)
async_passed = sum(1 for result in async_results.values() if result)
print(f"同步版本: {sync_passed}/{len(sync_results)} 通过")
print(f"异步版本: {async_passed}/{len(async_results)} 通过")
print(f"WebSocket 订单: {'✅ 通过' if ws_order_result else '❌ 失败'}")
print(f"WebSocket 余额: {'✅ 通过' if ws_balance_result else '❌ 失败'}")
total_tests = len(sync_results) + len(async_results) + 2
total_passed = sync_passed + async_passed + ws_order_result + ws_balance_result
print(f"\n总体结果: {total_passed}/{total_tests} 通过")
if total_passed == total_tests:
print("🎉 所有测试通过MT5 集成工作正常")
else:
print("⚠️ 部分测试失败,请检查日志文件 'mt5_test.log'")
if __name__ == "__main__":
try:
asyncio.run(main())
except KeyboardInterrupt:
print("\n👋 用户中断测试")
except Exception as e:
print(f"❌ 测试执行错误: {e}")
import traceback
traceback.print_exc()

136
test/atest_mt5_quick.py Normal file
View File

@@ -0,0 +1,136 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import asyncio
import logging
from ccxt import mt5 as mt5_sync
from ccxt.async_support import mt5 as mt5_async
# 简单日志配置
logging.basicConfig(level=logging.INFO, format='%(message)s')
logger = logging.getLogger('MT5-Quick-Test')
CONFIG = {
'apiKey': '76888962',
'secret': 'LZ-trade666888',
'verbose': False, # 启用详细日志
'hostname': '43.167.188.220:5000',
'host': '18.163.85.196',
'port': 443,
}
def quick_sync_test():
"""快速同步测试"""
logger.info("🔧 快速同步测试...")
try:
exchange = mt5_sync(CONFIG)
# 测试连接
logger.info("1. 测试连接...")
token = exchange.get_token()
logger.info(f" ✅ Token: {token}")
# # 测试交易对
logger.info("4. 测试交易对...")
markets = exchange.fetch_markets()
logger.info(f" ✅ 交易对数量: {len(markets)}")
# # 测试余额
# logger.info("2. 测试余额...")
# balance = exchange.fetch_balance()
# logger.info(f" ✅ 余额: {balance['total'].get('USDT', 'N/A')}")
# 测试行情
# logger.info("3. 测试行情...")
# ticker = exchange.fetch_ticker('EUR/USD')
# logger.info(f" ✅ EUR/USD: {ticker['bid']} / {ticker['ask']}")
# 测试订单
logger.info("3. 测试订单...")
ticker = exchange.fetch_closed_orders('EUR/USD')
logger.info(f" ✅ EUR/USD: {ticker['bid']} / {ticker['ask']}")
logger.info("🎉 快速同步测试完成!")
return True
except Exception as e:
logger.error(f"❌ 快速同步测试失败: {e}")
return False
async def quick_async_test():
"""快速异步测试"""
logger.info("\n🔧 快速异步测试...")
try:
exchange = mt5_async(CONFIG)
# 测试连接
logger.info("1. 测试异步连接...")
token = await exchange.get_token()
logger.info(f" ✅ Token: {token}")
# 测试余额
logger.info("2. 测试异步余额...")
balance = await exchange.fetch_balance()
logger.info(f" ✅ 余额: {balance['total'].get('USDT', 'N/A')}")
# 测试行情
logger.info("3. 测试异步行情...")
ticker = await exchange.fetch_ticker('EUR/USD')
logger.info(f" ✅ EUR/USD: {ticker['bid']} / {ticker['ask']}")
await exchange.close()
logger.info("🎉 快速异步测试完成!")
return True
except Exception as e:
logger.error(f"❌ 快速异步测试失败: {e}")
return False
async def main():
"""运行快速测试"""
print("🚀 MT5 快速测试")
print("="*40)
# 同步测试
sync_success = quick_sync_test()
# 异步测试
# async_success = await quick_async_test()
async_success = True
print("\n" + "="*40)
print("📊 快速测试结果")
print(f"同步测试: {'✅ 通过' if sync_success else '❌ 失败'}")
print(f"异步测试: {'✅ 通过' if async_success else '❌ 失败'}")
if sync_success and async_success:
print("🎉 所有快速测试通过!")
else:
print("⚠️ 部分测试失败,请运行完整测试套件查看详情")
if __name__ == "__main__":
# asyncio.run(main())
exchange = mt5_sync(CONFIG)
# 测试连接
logger.info("1. 测试连接...")
token = exchange.get_token()
logger.info(f" ✅ Token: {token}")
# # 测试交易对
logger.info("4. 测试交易对...")
markets = exchange.fetch_markets()
logger.info(f" ✅ 交易对数量: {len(markets)}")
logger.info("3. 测试订单...")
ticker = exchange.fetch_closed_orders('BTC/USD')
logger.info(f"{ticker}")

188
test/test.py Normal file
View File

@@ -0,0 +1,188 @@
#!/usr/bin/env python3
import ccxt
import sys
import json
def test_mt5_comprehensive():
print("=== MT5 Comprehensive Test ===")
try:
# 创建 MT5 实例
exchange = ccxt.mt5({
'apiKey': '76888962',
'secret': 'LZ-trade666888',
'verbose': True, # 启用详细日志
'hostname': '43.167.188.220:5000',
'options': {
# 'server': '147.160.254.81:443', # 使用服务器名称
# 或者
'host': '18.163.85.196',
'port': 443,
},
})
# 测试连接
print("\n🔗 Testing connection...")
try:
token = exchange.get_token()
print(f"✅ Connected successfully! Token: {token[:20]}...")
except Exception as e:
print(f"❌ Connection failed: {e}")
return False
# print("\n💰 Testing ping...")
# try:
# ping = exchange.ping_server()
# print(ping)
# except Exception as e:
# print(f"⚠️ ping fetch failed: {e}")
# 先加载市场数据
# print("\n📊 Loading markets first...")
# try:
# markets = exchange.load_markets()
# print(f"✅ Markets loaded: {len(markets)} symbols")
# except Exception as e:
# print(f"⚠️ Markets load failed: {e}")
# 测试余额
# print("\n💰 Testing balance...")
# try:
# balance = exchange.fetch_balance()
# print(f"✅ Balance fetched: {balance}")
# except Exception as e:
# print(f"⚠️ Balance fetch failed: {e}")
# print("\n💰 Testing AccountDetails...")
# try:
# account_details = exchange.fetch_account_details()
# print(f"✅ AccountDetails fetched: {account_details}")
# except Exception as e:
# print(f"⚠️ AccountDetails fetch failed: {e}")
# 测试交易对
# print("\n📊 Testing markets...")
# try:
# markets = exchange.fetch_markets()
# print(f"✅ Markets fetched: {len(markets)} symbols")
# if markets:
# for i, market in enumerate(markets[:3]):
# print(f" {i+1}. {market['symbol']}")
# except Exception as e:
# print(f"⚠️ Markets fetch failed: {e}")
# 测试行情
# print("\n💰 Testing ticker...")
# try:
# ticker = exchange.fetch_ticker('BTCUSD')
# print(ticker)
# # print(f"✅ Ticker fetched: {ticker['symbol']} - Bid: {ticker['bid']}, Ask: {ticker['ask']}")
# except Exception as e:
# print(f"⚠️ Ticker fetch failed: {e}")
# print("\n💰 Testing order_book...")
# try:
# order_book = exchange.fetch_ticker('BTCUSD')
# print(order_book)
# except Exception as e:
# print(f"⚠️ order_book fetch failed: {e}")
# 测试时区
# print("\n💰 Testing server_timezone...")
# try:
# timezone = exchange.server_timezone()
# print(timezone)
# # print(f"✅ Ticker fetched: {ticker['symbol']} - Bid: {ticker['bid']}, Ask: {ticker['ask']}")
# except Exception as e:
# print(f"⚠️ server_timezone fetch failed: {e}")
# 测试市场观察行情 - 使用不同的符号测试
# print("\n📊 Testing market watch ticker...")
# test_symbols = ['XAUUSD+'] # 多试几个符号
# for symbol in test_symbols:
# try:
# market_watch = exchange.fetch_ticker_with_market_watch(symbol)
# print(f"✅ Market watch ticker for {symbol}:")
# print(f" High: {market_watch['high']}")
# print(f" Low: {market_watch['low']}")
# print(f" Open: {market_watch['open']}")
# print(f" Close: {market_watch['close']}")
# break # 成功一个就停止
# except Exception as e:
# print(f"⚠️ Market watch for {symbol} failed: {e}")
# 测试K线数据
# print("\n🕯 Testing XAUUSD+...")
# try:
# ohlcv = exchange.fetch_ohlcv('XAUUSD+', '1h', limit=3) # 使用 XAUUSD+ 测试
# print(f"✅ XAUUSD+ fetched: {len(ohlcv)} bars")
# for i, candle in enumerate(ohlcv):
# print(f" Bar {i+1}: Time={candle[0]}, O={candle[1]}, H={candle[2]}, L={candle[3]}, C={candle[4]}, V={candle[5]}")
# except Exception as e:
# print(f"⚠️ XAUUSD+ failed: {e}")
# 测试订单查询
# print("\n📋 Testing open orders...")
# try:
# open_orders = exchange.fetch_open_orders()
# print(f"✅ Open orders: {len(open_orders)}")
# # for order in open_orders:
# # print(f" Order: {order['ticket']} - {order['symbol']} - {order['orderType']} - {order['lots']}")
# except Exception as e:
# print(f"⚠️ Open orders failed: {e}")
# 测试持仓查询
# print("\n📊 Testing positions...")
# try:
# positions = exchange.fetch_positions()
# print(f"✅ Positions fetched: {len(positions)} positions")
# for i, position in enumerate(positions):
# print(f"\n📈 Position {i+1}:")
# print(f" ID: {position['id']}")
# print(f" Symbol: {position['symbol']}")
# print(f" Side: {position['side']}")
# print(f" Contracts: {position['contracts']}")
# print(f" Entry Price: {position['entryPrice']}")
# print(f" Unrealized PnL: {position['unrealizedPnl']}")
# print(f" Stop Loss: {position['stopLossPrice']}")
# print(f" Take Profit: {position['takeProfitPrice']}")
# print(f" Timestamp: {position['timestamp']}")
# except Exception as e:
# print(f"❌ Positions failed: {e}")
# import traceback
# traceback.print_exc()
# 测试单个持仓查询(如果有持仓的话)
# if positions:
# first_symbol = positions[0]['symbol']
# print(f"\n🎯 Testing single position for {first_symbol}...")
# try:
# single_position = exchange.fetch_position(first_symbol)
# print(f"✅ Single position fetched:")
# print(f" Symbol: {single_position['symbol']}")
# print(f" Side: {single_position['side']}")
# print(f" Contracts: {single_position['contracts']}")
# except Exception as e:
# print(f"⚠️ Single position failed: {e}")
# print("\n🎉 Positions test completed!")
# print("\n🎉 Comprehensive test completed!")
return True
except Exception as e:
print(f"❌ Error: {e}")
import traceback
traceback.print_exc()
return False
if __name__ == "__main__":
success = test_mt5_comprehensive()
sys.exit(0 if success else 1)

32
test/test2.py Normal file
View File

@@ -0,0 +1,32 @@
# -*- coding:utf-8 -*-
import asyncio
import ccxt.pro as ccxtpro
async def fetch_balance_demo():
async with ccxtpro.mt5({
'apiKey': '76888962',
'secret': 'LZ-trade666888',
'verbose': False, # 启用详细日志
'hostname': '43.167.188.220:5000',
'options': {
# 'server': '147.160.254.81:443', # 使用服务器名称
# 或者
'host': '18.163.85.196',
'port': 443,
},
}) as exchange:
try:
res = await exchange.watch_order()
print(res)
except Exception as e:
print(f"错误: {e}")
async def main():
print("开始测试...")
await fetch_balance_demo()
print("程序执行完成")
if __name__ == "__main__":
asyncio.run(main())

147
test/test_mt5_tools.py Normal file
View File

@@ -0,0 +1,147 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import asyncio
import json
import logging
from ccxt.pro import mt5
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger('MT5-Tools')
class MT5OrderAnalyzer:
"""MT5 订单分析工具"""
def __init__(self, exchange):
self.exchange = exchange
self.order_history = []
async def analyze_orders(self, symbol=None, days=7):
"""分析订单数据"""
try:
# 获取订单历史
orders = await self.exchange.fetch_orders(symbol)
# 分析订单统计
total_orders = len(orders)
open_orders = len([o for o in orders if o['status'] == 'open'])
closed_orders = len([o for o in orders if o['status'] == 'closed'])
canceled_orders = len([o for o in orders if o['status'] == 'canceled'])
# 分析盈亏
profitable_trades = []
losing_trades = []
for order in orders:
if order['status'] == 'closed' and order.get('cost'):
if order.get('filled', 0) > 0:
# 这里需要根据具体订单数据计算盈亏
pass
logger.info(f"📈 订单分析结果:")
logger.info(f" 总订单数: {total_orders}")
logger.info(f" 开单数: {open_orders}")
logger.info(f" 平单数: {closed_orders}")
logger.info(f" 取消单数: {canceled_orders}")
return {
'total_orders': total_orders,
'open_orders': open_orders,
'closed_orders': closed_orders,
'canceled_orders': canceled_orders
}
except Exception as e:
logger.error(f"分析订单失败: {e}")
return {}
async def quick_order_test():
"""快速订单测试"""
logger.info("🚀 快速订单测试开始")
exchange = mt5({
'user': 62333850,
'password': 'tecimil4',
'host': '78.140.180.198',
'port': 443,
'sandbox': True,
})
try:
# 测试连接
balance = await exchange.fetch_balance()
logger.info(f"✅ 连接成功,余额: {balance['total'].get('USD', 'N/A')}")
# 获取市场信息
markets = await exchange.fetch_markets()
logger.info(f"✅ 获取到 {len(markets)} 个交易对")
# 获取当前价格
ticker = await exchange.fetch_ticker('EUR/USD')
logger.info(f"✅ EUR/USD 当前价格: 买={ticker['bid']}, 卖={ticker['ask']}")
# 获取订单簿
orderbook = await exchange.fetch_order_book('EUR/USD')
logger.info(f"✅ EUR/USD 订单簿深度: {len(orderbook['bids'])} 买单, {len(orderbook['asks'])} 卖单")
# 获取开单
open_orders = await exchange.fetch_open_orders()
logger.info(f"✅ 当前开单数量: {len(open_orders)}")
for order in open_orders:
logger.info(f" 订单 {order['id']}: {order['symbol']} {order['side']} {order['type']} {order['status']}")
except Exception as e:
logger.error(f"❌ 测试失败: {e}")
finally:
await exchange.close()
async def websocket_quick_test():
"""WebSocket 快速测试"""
logger.info("🔌 WebSocket 快速测试开始")
exchange = mt5({
'apiKey': '76888962',
'secret': 'LZ-trade666888',
'verbose': False, # 启用详细日志
'hostname': '43.167.188.220:5000',
'options': {
# 'server': '147.160.254.81:443', # 使用服务器名称
# 或者
'host': '18.163.85.196',
'port': 443,
},
})
try:
# 监听订单更新
async def order_listener():
orders = await exchange.watch_orders()
for order in orders:
logger.info(f"📦 订单更新: {order['id']} {order['symbol']} {order['side']} {order['status']}")
# 监听余额更新
async def balance_listener():
balance = await exchange.watch_balance()
total = sum([v for v in balance['total'].values() if v is not None])
logger.info(f"💰 余额更新: 总余额 {total:.2f}")
# 运行监听器
await asyncio.gather(
order_listener(),
balance_listener(),
return_exceptions=True
)
except Exception as e:
logger.error(f"WebSocket 测试错误: {e}")
finally:
await exchange.close()
if __name__ == "__main__":
# 运行快速测试
asyncio.run(quick_order_test())

View File

@@ -0,0 +1,475 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import asyncio
import json
import logging
from datetime import datetime
from ccxt.pro import mt5
from ccxt.base.errors import ExchangeError, AuthenticationError
# 设置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger('MT5-WebSocket-Test')
class MT5WebSocketOrderTest:
def __init__(self, config):
self.exchange = mt5({
'apiKey': config.get('apiKey', ''),
'secret': config.get('secret', ''),
'password': config.get('password', ''),
'user': config.get('user', 62333850),
'host': config.get('host', '78.140.180.198'),
'port': config.get('port', 443),
'sandbox': True,
'verbose': True,
})
# 存储数据
self.balance = None
self.orders = []
self.open_orders = []
self.closed_orders = []
# 统计信息
self.stats = {
'order_updates': 0,
'balance_updates': 0,
'trade_updates': 0,
'errors': 0
}
logger.info("MT5 WebSocket 订单测试初始化完成")
async def watch_orders(self):
"""监听订单更新"""
logger.info("开始监听订单更新...")
while True:
try:
orders = await self.exchange.watch_orders()
for order in orders:
await self.handle_order_update(order)
except Exception as e:
logger.error(f"监听订单时发生错误: {e}")
self.stats['errors'] += 1
await asyncio.sleep(5) # 等待后重试
async def watch_balance(self):
"""监听余额更新"""
logger.info("开始监听余额更新...")
while True:
try:
balance = await self.exchange.watch_balance()
await self.handle_balance_update(balance)
except Exception as e:
logger.error(f"监听余额时发生错误: {e}")
self.stats['errors'] += 1
await asyncio.sleep(5)
async def watch_my_trades(self):
"""监听交易更新"""
logger.info("开始监听交易更新...")
while True:
try:
trades = await self.exchange.watch_my_trades()
for trade in trades:
await self.handle_trade_update(trade)
except Exception as e:
logger.error(f"监听交易时发生错误: {e}")
self.stats['errors'] += 1
await asyncio.sleep(5)
async def handle_order_update(self, order):
"""处理订单更新"""
self.stats['order_updates'] += 1
order_id = order['id']
symbol = order['symbol']
status = order['status']
side = order['side']
order_type = order['type']
price = order.get('price')
amount = order.get('amount')
filled = order.get('filled')
# 检查是否是新的订单
existing_order = next((o for o in self.orders if o['id'] == order_id), None)
if existing_order:
# 更新现有订单
old_status = existing_order['status']
if old_status != status:
logger.info(f"🔁 订单状态更新: {order_id} {symbol} {side} {old_status} -> {status}")
# 更新订单信息
existing_order.update(order)
else:
# 新订单
logger.info(f"🆕 新订单: {order_id} {symbol} {side} {order_type} {status}")
self.orders.append(order.copy())
# 更新开单/平单列表
self.update_order_lists(order)
# 打印订单详情
self.print_order_details(order)
async def handle_balance_update(self, balance):
"""处理余额更新"""
self.stats['balance_updates'] += 1
self.balance = balance
# 提取主要余额信息
total_balance = 0
free_balance = 0
used_balance = 0
for currency, info in balance['total'].items():
if info is not None:
total_balance += info
for currency, info in balance['free'].items():
if info is not None:
free_balance += info
for currency, info in balance['used'].items():
if info is not None:
used_balance += info
logger.info(f"💰 余额更新 - 总余额: {total_balance:.2f}, 可用: {free_balance:.2f}, 占用: {used_balance:.2f}")
# 打印详细余额信息
self.print_balance_details(balance)
async def handle_trade_update(self, trade):
"""处理交易更新"""
self.stats['trade_updates'] += 1
trade_id = trade['id']
order_id = trade['order']
symbol = trade['symbol']
side = trade['side']
price = trade['price']
amount = trade['amount']
cost = trade.get('cost')
fee = trade.get('fee', {})
logger.info(f"💸 交易执行: {trade_id} | 订单: {order_id} | {symbol} {side} {amount} @ {price}")
if cost:
logger.info(f" 交易成本: {cost:.2f}")
if fee and fee.get('cost'):
logger.info(f" 手续费: {fee['cost']} {fee.get('currency', '')}")
def update_order_lists(self, order):
"""更新开单和平单列表"""
order_id = order['id']
status = order['status']
# 从开单列表中移除已关闭的订单
self.open_orders = [o for o in self.open_orders if o['id'] != order_id]
# 如果是开单状态,添加到开单列表
if status in ['open', 'pending']:
self.open_orders.append(order.copy())
# 如果是关闭状态,添加到平单列表
elif status in ['closed', 'canceled', 'expired', 'rejected']:
# 检查是否已经在平单列表中
if not any(o['id'] == order_id for o in self.closed_orders):
self.closed_orders.append(order.copy())
def print_order_details(self, order):
"""打印订单详情"""
order_id = order['id']
symbol = order['symbol']
status = order['status']
side = order['side']
order_type = order['type']
price = order.get('price', 'N/A')
amount = order.get('amount', 'N/A')
filled = order.get('filled', 'N/A')
remaining = order.get('remaining', 'N/A')
cost = order.get('cost', 'N/A')
details = [
f"订单ID: {order_id}",
f"交易对: {symbol}",
f"方向: {side}",
f"类型: {order_type}",
f"状态: {status}",
f"价格: {price}",
f"数量: {amount}",
f"已成交: {filled}",
f"未成交: {remaining}",
f"成本: {cost}"
]
logger.debug("📋 订单详情: " + " | ".join(details))
def print_balance_details(self, balance):
"""打印余额详情"""
if not balance:
return
logger.debug("💳 详细余额信息:")
for currency in ['USD', 'EUR', 'GBP', 'JPY']:
if currency in balance['total'] and balance['total'][currency] is not None:
total = balance['total'][currency]
free = balance['free'].get(currency, 0)
used = balance['used'].get(currency, 0)
logger.debug(f" {currency}: 总额={total:.2f}, 可用={free:.2f}, 占用={used:.2f}")
async def place_test_orders(self):
"""放置测试订单"""
logger.info("开始放置测试订单...")
test_orders = [
{
'symbol': 'EUR/USD',
'type': 'limit',
'side': 'buy',
'amount': 0.01,
'price': 1.0800
},
{
'symbol': 'EUR/USD',
'type': 'limit',
'side': 'sell',
'amount': 0.01,
'price': 1.0900
},
{
'symbol': 'GBP/USD',
'type': 'market',
'side': 'buy',
'amount': 0.01
}
]
created_orders = []
for order_params in test_orders:
try:
logger.info(f"尝试下单: {order_params}")
order = await self.exchange.create_order(
order_params['symbol'],
order_params['type'],
order_params['side'],
order_params['amount'],
order_params.get('price')
)
created_orders.append(order)
logger.info(f"✅ 下单成功: {order['id']}")
await asyncio.sleep(2) # 间隔2秒
except Exception as e:
logger.error(f"❌ 下单失败: {e}")
return created_orders
async def cancel_test_orders(self, orders):
"""取消测试订单"""
logger.info("开始取消测试订单...")
for order in orders:
try:
if order['status'] in ['open', 'pending']:
await self.exchange.cancel_order(order['id'], order['symbol'])
logger.info(f"✅ 取消订单成功: {order['id']}")
await asyncio.sleep(1)
except Exception as e:
logger.error(f"❌ 取消订单失败 {order['id']}: {e}")
async def get_current_orders(self):
"""获取当前订单状态"""
try:
open_orders = await self.exchange.fetch_open_orders()
closed_orders = await self.exchange.fetch_closed_orders()
logger.info(f"当前开单数量: {len(open_orders)}")
logger.info(f"历史订单数量: {len(closed_orders)}")
return open_orders, closed_orders
except Exception as e:
logger.error(f"获取订单状态失败: {e}")
return [], []
def print_statistics(self):
"""打印统计信息"""
logger.info("📊 WebSocket 测试统计:")
logger.info(f" 订单更新次数: {self.stats['order_updates']}")
logger.info(f" 余额更新次数: {self.stats['balance_updates']}")
logger.info(f" 交易更新次数: {self.stats['trade_updates']}")
logger.info(f" 错误次数: {self.stats['errors']}")
logger.info(f" 总订单数: {len(self.orders)}")
logger.info(f" 当前开单: {len(self.open_orders)}")
logger.info(f" 已关闭订单: {len(self.closed_orders)}")
if self.balance:
total = sum([v for v in self.balance['total'].values() if v is not None])
logger.info(f" 当前总余额: {total:.2f}")
async def run_test(self, duration=300, place_test_orders=True):
"""运行测试"""
logger.info(f"🚀 开始 MT5 WebSocket 订单测试,持续时间: {duration}")
start_time = datetime.now()
try:
# 启动监听任务
watch_tasks = [
asyncio.create_task(self.watch_orders()),
asyncio.create_task(self.watch_balance()),
asyncio.create_task(self.watch_my_trades()),
]
# 等待连接建立
await asyncio.sleep(5)
# 放置测试订单
test_orders = []
if place_test_orders:
test_orders = await self.place_test_orders()
# 等待订单处理
await asyncio.sleep(10)
# 获取当前订单状态
await self.get_current_orders()
# 等待一段时间后取消测试订单
await asyncio.sleep(30)
await self.cancel_test_orders(test_orders)
# 主测试循环
test_task = asyncio.create_task(self.test_loop(duration))
await test_task
# 取消监听任务
for task in watch_tasks:
task.cancel()
# 等待任务结束
await asyncio.gather(*watch_tasks, return_exceptions=True)
except Exception as e:
logger.error(f"测试运行错误: {e}")
finally:
# 关闭连接
await self.exchange.close()
end_time = datetime.now()
duration_actual = (end_time - start_time).total_seconds()
logger.info(f"✅ 测试完成,实际运行时间: {duration_actual:.2f}")
self.print_statistics()
async def test_loop(self, duration):
"""测试主循环"""
start_time = asyncio.get_event_loop().time()
while True:
current_time = asyncio.get_event_loop().time()
elapsed = current_time - start_time
if elapsed >= duration:
break
# 每分钟打印一次状态
if int(elapsed) % 60 == 0:
logger.info(f"⏰ 测试运行中... 已运行: {int(elapsed)}")
self.print_statistics()
await asyncio.sleep(1)
async def real_time_monitoring(self):
"""实时监控模式"""
logger.info("🔍 启动实时监控模式...")
try:
await asyncio.gather(
self.watch_orders(),
self.watch_balance(),
self.watch_my_trades(),
)
except KeyboardInterrupt:
logger.info("👋 用户中断监控")
finally:
await self.exchange.close()
self.print_statistics()
# 测试配置
TEST_CONFIG = {
'user': 62333850, # 演示账户
'password': 'tecimil4',
'host': '78.140.180.198',
'port': 443,
}
async def main():
"""主函数"""
print("=" * 60)
print("MT5 WebSocket 订单信息测试")
print("=" * 60)
# 创建测试实例
tester = MT5WebSocketOrderTest(TEST_CONFIG)
try:
# 选择测试模式
print("\n选择测试模式:")
print("1. 完整测试 (包含测试订单)")
print("2. 实时监控模式")
print("3. 仅测试连接")
choice = input("请输入选择 (1-3, 默认1): ").strip()
if choice == "2":
# 实时监控模式
await tester.real_time_monitoring()
elif choice == "3":
# 仅测试连接
await tester.get_current_orders()
await tester.exchange.close()
else:
# 完整测试
duration = input("输入测试持续时间(秒, 默认300): ").strip()
duration = int(duration) if duration.isdigit() else 300
place_orders = input("是否放置测试订单? (y/n, 默认y): ").strip().lower()
place_orders = place_orders != 'n'
await tester.run_test(duration=duration, place_test_orders=place_orders)
except KeyboardInterrupt:
logger.info("👋 用户中断测试")
except Exception as e:
logger.error(f"测试执行错误: {e}")
finally:
print("\n" + "=" * 60)
print("测试结束")
print("=" * 60)
if __name__ == "__main__":
# 运行测试
asyncio.run(main())