mexc debug files
This commit is contained in:
118
NN/exchanges/mexc/debug/final_mexc_order_test.py
Normal file
118
NN/exchanges/mexc/debug/final_mexc_order_test.py
Normal file
@ -0,0 +1,118 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Final MEXC Order Test - Exact match to working examples
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import hmac
|
||||
import hashlib
|
||||
import requests
|
||||
import json
|
||||
from urllib.parse import urlencode
|
||||
from pathlib import Path
|
||||
|
||||
# Add project root to path
|
||||
project_root = Path(__file__).parent
|
||||
sys.path.insert(0, str(project_root))
|
||||
|
||||
def test_final_mexc_order():
|
||||
"""Test MEXC order with the working method"""
|
||||
print("Final MEXC Order Test - Working Method")
|
||||
print("=" * 50)
|
||||
|
||||
# Get API credentials
|
||||
api_key = os.getenv('MEXC_API_KEY', '')
|
||||
api_secret = os.getenv('MEXC_SECRET_KEY', '')
|
||||
|
||||
if not api_key or not api_secret:
|
||||
print("❌ No MEXC API credentials found")
|
||||
return
|
||||
|
||||
# Parameters
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
|
||||
# Create the exact parameter string like the working example
|
||||
params = f"symbol=ETHUSDC&side=BUY&type=LIMIT&quantity=0.003&price=2900&recvWindow=5000×tamp={timestamp}"
|
||||
|
||||
print(f"Parameter string: {params}")
|
||||
|
||||
# Create signature exactly like the working example
|
||||
signature = hmac.new(
|
||||
api_secret.encode('utf-8'),
|
||||
params.encode('utf-8'),
|
||||
hashlib.sha256
|
||||
).hexdigest()
|
||||
|
||||
print(f"Signature: {signature}")
|
||||
|
||||
# Make the request exactly like the curl example
|
||||
url = f"https://api.mexc.com/api/v3/order"
|
||||
|
||||
headers = {
|
||||
'X-MEXC-APIKEY': api_key,
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
|
||||
data = f"{params}&signature={signature}"
|
||||
|
||||
try:
|
||||
print(f"\nPOST to: {url}")
|
||||
print(f"Headers: {headers}")
|
||||
print(f"Data: {data}")
|
||||
|
||||
response = requests.post(url, headers=headers, data=data)
|
||||
|
||||
print(f"\nStatus: {response.status_code}")
|
||||
print(f"Response: {response.text}")
|
||||
|
||||
if response.status_code == 200:
|
||||
print("✅ SUCCESS!")
|
||||
else:
|
||||
print("❌ FAILED")
|
||||
# Try alternative method - sending as query params
|
||||
print("\n--- Trying alternative method ---")
|
||||
test_alternative_method(api_key, api_secret)
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
|
||||
def test_alternative_method(api_key: str, api_secret: str):
|
||||
"""Try sending as query parameters instead"""
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
|
||||
params = {
|
||||
'symbol': 'ETHUSDC',
|
||||
'side': 'BUY',
|
||||
'type': 'LIMIT',
|
||||
'quantity': '0.003',
|
||||
'price': '2900',
|
||||
'timestamp': timestamp,
|
||||
'recvWindow': '5000'
|
||||
}
|
||||
|
||||
# Create query string
|
||||
query_string = '&'.join([f"{k}={v}" for k, v in sorted(params.items())])
|
||||
|
||||
# Create signature
|
||||
signature = hmac.new(
|
||||
api_secret.encode('utf-8'),
|
||||
query_string.encode('utf-8'),
|
||||
hashlib.sha256
|
||||
).hexdigest()
|
||||
|
||||
# Add signature to params
|
||||
params['signature'] = signature
|
||||
|
||||
headers = {
|
||||
'X-MEXC-APIKEY': api_key
|
||||
}
|
||||
|
||||
print(f"Alternative query params: {params}")
|
||||
|
||||
response = requests.post('https://api.mexc.com/api/v3/order', params=params, headers=headers)
|
||||
print(f"Alternative response: {response.status_code} - {response.text}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_final_mexc_order()
|
141
NN/exchanges/mexc/debug/fix_mexc_orders.py
Normal file
141
NN/exchanges/mexc/debug/fix_mexc_orders.py
Normal file
@ -0,0 +1,141 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Fix MEXC Order Placement based on Official API Documentation
|
||||
Uses the exact signature method from MEXC Postman collection
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import hmac
|
||||
import hashlib
|
||||
import requests
|
||||
from pathlib import Path
|
||||
|
||||
# Add project root to path
|
||||
project_root = Path(__file__).parent
|
||||
sys.path.insert(0, str(project_root))
|
||||
|
||||
def create_mexc_signature(access_key: str, secret_key: str, params: dict, method: str = "POST") -> tuple:
|
||||
"""Create MEXC signature exactly as specified in their documentation"""
|
||||
|
||||
# Get current timestamp in milliseconds
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
|
||||
# For POST requests, sort parameters alphabetically and create query string
|
||||
if method == "POST":
|
||||
# Sort parameters alphabetically
|
||||
sorted_params = dict(sorted(params.items()))
|
||||
|
||||
# Create parameter string
|
||||
param_parts = []
|
||||
for key, value in sorted_params.items():
|
||||
param_parts.append(f"{key}={value}")
|
||||
param_string = "&".join(param_parts)
|
||||
else:
|
||||
param_string = ""
|
||||
|
||||
# Create signature target string: access_key + timestamp + param_string
|
||||
signature_target = f"{access_key}{timestamp}{param_string}"
|
||||
|
||||
print(f"Signature target: {signature_target}")
|
||||
|
||||
# Generate HMAC SHA256 signature
|
||||
signature = hmac.new(
|
||||
secret_key.encode('utf-8'),
|
||||
signature_target.encode('utf-8'),
|
||||
hashlib.sha256
|
||||
).hexdigest()
|
||||
|
||||
return signature, timestamp, param_string
|
||||
|
||||
def test_mexc_order_placement():
|
||||
"""Test MEXC order placement with corrected signature"""
|
||||
print("Testing MEXC Order Placement with Official API Method...")
|
||||
print("=" * 60)
|
||||
|
||||
# Get API credentials
|
||||
api_key = os.getenv('MEXC_API_KEY', '')
|
||||
api_secret = os.getenv('MEXC_SECRET_KEY', '')
|
||||
|
||||
if not api_key or not api_secret:
|
||||
print("❌ No MEXC API credentials found")
|
||||
return
|
||||
|
||||
# Test parameters - very small order
|
||||
params = {
|
||||
'symbol': 'ETHUSDC',
|
||||
'side': 'BUY',
|
||||
'type': 'LIMIT',
|
||||
'quantity': '0.003', # $10 worth at ~$3000
|
||||
'price': '3000.0', # Safe price below market
|
||||
'timeInForce': 'GTC'
|
||||
}
|
||||
|
||||
print(f"Order Parameters: {params}")
|
||||
|
||||
# Create signature using official method
|
||||
signature, timestamp, param_string = create_mexc_signature(api_key, api_secret, params)
|
||||
|
||||
# Create headers as specified in documentation
|
||||
headers = {
|
||||
'X-MEXC-APIKEY': api_key,
|
||||
'Request-Time': timestamp,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
|
||||
# Add signature to parameters
|
||||
params['timestamp'] = timestamp
|
||||
params['recvWindow'] = '5000'
|
||||
params['signature'] = signature
|
||||
|
||||
# Create URL with parameters
|
||||
base_url = "https://api.mexc.com/api/v3/order"
|
||||
|
||||
try:
|
||||
print(f"\nMaking request to: {base_url}")
|
||||
print(f"Headers: {headers}")
|
||||
print(f"Parameters: {params}")
|
||||
|
||||
# Make the request using POST with query parameters (MEXC style)
|
||||
response = requests.post(base_url, headers=headers, params=params, timeout=10)
|
||||
|
||||
print(f"\nResponse Status: {response.status_code}")
|
||||
print(f"Response Headers: {dict(response.headers)}")
|
||||
|
||||
if response.status_code == 200:
|
||||
result = response.json()
|
||||
print("✅ Order placed successfully!")
|
||||
print(f"Order result: {result}")
|
||||
|
||||
# Try to cancel it immediately if we got an order ID
|
||||
if 'orderId' in result:
|
||||
print(f"\nCanceling order {result['orderId']}...")
|
||||
cancel_params = {
|
||||
'symbol': 'ETHUSDC',
|
||||
'orderId': result['orderId']
|
||||
}
|
||||
|
||||
cancel_sig, cancel_ts, _ = create_mexc_signature(api_key, api_secret, cancel_params, "DELETE")
|
||||
cancel_params['timestamp'] = cancel_ts
|
||||
cancel_params['recvWindow'] = '5000'
|
||||
cancel_params['signature'] = cancel_sig
|
||||
|
||||
cancel_headers = {
|
||||
'X-MEXC-APIKEY': api_key,
|
||||
'Request-Time': cancel_ts,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
|
||||
cancel_response = requests.delete(base_url, headers=cancel_headers, params=cancel_params, timeout=10)
|
||||
print(f"Cancel response: {cancel_response.status_code} - {cancel_response.text}")
|
||||
|
||||
else:
|
||||
print("❌ Order placement failed")
|
||||
print(f"Response: {response.text}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Request error: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_mexc_order_placement()
|
132
NN/exchanges/mexc/debug/fix_mexc_orders_v2.py
Normal file
132
NN/exchanges/mexc/debug/fix_mexc_orders_v2.py
Normal file
@ -0,0 +1,132 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
MEXC Order Fix V2 - Based on Exact Postman Collection Examples
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import hmac
|
||||
import hashlib
|
||||
import requests
|
||||
from urllib.parse import urlencode
|
||||
from pathlib import Path
|
||||
|
||||
# Add project root to path
|
||||
project_root = Path(__file__).parent
|
||||
sys.path.insert(0, str(project_root))
|
||||
|
||||
def create_mexc_signature_v2(api_key: str, secret_key: str, params: dict) -> tuple:
|
||||
"""Create MEXC signature based on exact Postman examples"""
|
||||
|
||||
# Current timestamp in milliseconds
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
|
||||
# Add timestamp and recvWindow to params
|
||||
params_with_time = params.copy()
|
||||
params_with_time['timestamp'] = timestamp
|
||||
params_with_time['recvWindow'] = '5000'
|
||||
|
||||
# Sort parameters alphabetically (as shown in MEXC examples)
|
||||
sorted_params = dict(sorted(params_with_time.items()))
|
||||
|
||||
# Create query string exactly like the examples
|
||||
query_string = urlencode(sorted_params, doseq=True)
|
||||
|
||||
print(f"API Key: {api_key}")
|
||||
print(f"Timestamp: {timestamp}")
|
||||
print(f"Query String: {query_string}")
|
||||
|
||||
# MEXC signature formula: HMAC-SHA256(query_string, secret_key)
|
||||
# This matches the curl examples in their documentation
|
||||
signature = hmac.new(
|
||||
secret_key.encode('utf-8'),
|
||||
query_string.encode('utf-8'),
|
||||
hashlib.sha256
|
||||
).hexdigest()
|
||||
|
||||
print(f"Generated Signature: {signature}")
|
||||
|
||||
return signature, timestamp, query_string
|
||||
|
||||
def test_mexc_order_v2():
|
||||
"""Test MEXC order placement with V2 signature method"""
|
||||
print("Testing MEXC Order V2 - Exact Postman Method...")
|
||||
print("=" * 60)
|
||||
|
||||
# Get API credentials
|
||||
api_key = os.getenv('MEXC_API_KEY', '')
|
||||
api_secret = os.getenv('MEXC_SECRET_KEY', '')
|
||||
|
||||
if not api_key or not api_secret:
|
||||
print("❌ No MEXC API credentials found")
|
||||
return
|
||||
|
||||
# Order parameters matching MEXC examples
|
||||
params = {
|
||||
'symbol': 'ETHUSDC',
|
||||
'side': 'BUY',
|
||||
'type': 'LIMIT',
|
||||
'quantity': '0.003', # Very small quantity
|
||||
'price': '2900.0', # Price below market
|
||||
'timeInForce': 'GTC'
|
||||
}
|
||||
|
||||
print(f"Order Parameters: {params}")
|
||||
|
||||
# Create signature
|
||||
signature, timestamp, query_string = create_mexc_signature_v2(api_key, api_secret, params)
|
||||
|
||||
# Build final URL with all parameters
|
||||
base_url = "https://api.mexc.com/api/v3/order"
|
||||
full_url = f"{base_url}?{query_string}&signature={signature}"
|
||||
|
||||
# Headers matching Postman examples
|
||||
headers = {
|
||||
'X-MEXC-APIKEY': api_key,
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
|
||||
try:
|
||||
print(f"\nMaking POST request to: {full_url}")
|
||||
print(f"Headers: {headers}")
|
||||
|
||||
# POST request with query parameters (as shown in examples)
|
||||
response = requests.post(full_url, headers=headers, timeout=10)
|
||||
|
||||
print(f"\nResponse Status: {response.status_code}")
|
||||
print(f"Response: {response.text}")
|
||||
|
||||
if response.status_code == 200:
|
||||
result = response.json()
|
||||
print("✅ Order placed successfully!")
|
||||
print(f"Order result: {result}")
|
||||
|
||||
# Cancel immediately if successful
|
||||
if 'orderId' in result:
|
||||
print(f"\n🔄 Canceling order {result['orderId']}...")
|
||||
cancel_order(api_key, api_secret, 'ETHUSDC', result['orderId'])
|
||||
|
||||
else:
|
||||
print("❌ Order placement failed")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Request error: {e}")
|
||||
|
||||
def cancel_order(api_key: str, secret_key: str, symbol: str, order_id: str):
|
||||
"""Cancel a MEXC order"""
|
||||
params = {
|
||||
'symbol': symbol,
|
||||
'orderId': order_id
|
||||
}
|
||||
|
||||
signature, timestamp, query_string = create_mexc_signature_v2(api_key, secret_key, params)
|
||||
|
||||
url = f"https://api.mexc.com/api/v3/order?{query_string}&signature={signature}"
|
||||
headers = {'X-MEXC-APIKEY': api_key}
|
||||
|
||||
response = requests.delete(url, headers=headers, timeout=10)
|
||||
print(f"Cancel response: {response.status_code} - {response.text}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_mexc_order_v2()
|
134
NN/exchanges/mexc/debug/fix_mexc_orders_v3.py
Normal file
134
NN/exchanges/mexc/debug/fix_mexc_orders_v3.py
Normal file
@ -0,0 +1,134 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
MEXC Order Fix V3 - Based on exact curl examples from MEXC documentation
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import hmac
|
||||
import hashlib
|
||||
import requests
|
||||
import json
|
||||
from urllib.parse import urlencode
|
||||
from pathlib import Path
|
||||
|
||||
# Add project root to path
|
||||
project_root = Path(__file__).parent
|
||||
sys.path.insert(0, str(project_root))
|
||||
|
||||
def create_mexc_signature_v3(query_string: str, secret_key: str) -> str:
|
||||
"""Create MEXC signature exactly as shown in curl examples"""
|
||||
|
||||
print(f"Signing string: {query_string}")
|
||||
|
||||
# MEXC uses HMAC SHA256 on the query string
|
||||
signature = hmac.new(
|
||||
secret_key.encode('utf-8'),
|
||||
query_string.encode('utf-8'),
|
||||
hashlib.sha256
|
||||
).hexdigest()
|
||||
|
||||
print(f"Generated signature: {signature}")
|
||||
return signature
|
||||
|
||||
def test_mexc_order_v3():
|
||||
"""Test MEXC order placement with V3 method matching curl examples"""
|
||||
print("Testing MEXC Order V3 - Exact curl examples...")
|
||||
print("=" * 60)
|
||||
|
||||
# Get API credentials
|
||||
api_key = os.getenv('MEXC_API_KEY', '')
|
||||
api_secret = os.getenv('MEXC_SECRET_KEY', '')
|
||||
|
||||
if not api_key or not api_secret:
|
||||
print("❌ No MEXC API credentials found")
|
||||
return
|
||||
|
||||
# Order parameters exactly like the examples
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
|
||||
# Build the query string in alphabetical order (like the examples)
|
||||
params = {
|
||||
'price': '2900.0',
|
||||
'quantity': '0.003',
|
||||
'recvWindow': '5000',
|
||||
'side': 'BUY',
|
||||
'symbol': 'ETHUSDC',
|
||||
'timeInForce': 'GTC',
|
||||
'timestamp': timestamp,
|
||||
'type': 'LIMIT'
|
||||
}
|
||||
|
||||
# Create query string in alphabetical order
|
||||
query_string = urlencode(sorted(params.items()))
|
||||
|
||||
print(f"Parameters: {params}")
|
||||
print(f"Query string: {query_string}")
|
||||
|
||||
# Generate signature
|
||||
signature = create_mexc_signature_v3(query_string, api_secret)
|
||||
|
||||
# Build the final URL and data exactly like the curl examples
|
||||
base_url = "https://api.mexc.com/api/v3/order"
|
||||
final_data = f"{query_string}&signature={signature}"
|
||||
|
||||
# Headers exactly like the curl examples
|
||||
headers = {
|
||||
'X-MEXC-APIKEY': api_key,
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
|
||||
try:
|
||||
print(f"\nMaking POST request to: {base_url}")
|
||||
print(f"Headers: {headers}")
|
||||
print(f"Data: {final_data}")
|
||||
|
||||
# POST with data in body (like curl -d option)
|
||||
response = requests.post(base_url, headers=headers, data=final_data, timeout=10)
|
||||
|
||||
print(f"\nResponse Status: {response.status_code}")
|
||||
print(f"Response: {response.text}")
|
||||
|
||||
if response.status_code == 200:
|
||||
result = response.json()
|
||||
print("✅ Order placed successfully!")
|
||||
print(f"Order result: {result}")
|
||||
|
||||
# Cancel immediately if successful
|
||||
if 'orderId' in result:
|
||||
print(f"\n🔄 Canceling order {result['orderId']}...")
|
||||
cancel_order_v3(api_key, api_secret, 'ETHUSDC', result['orderId'])
|
||||
|
||||
else:
|
||||
print("❌ Order placement failed")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Request error: {e}")
|
||||
|
||||
def cancel_order_v3(api_key: str, secret_key: str, symbol: str, order_id: str):
|
||||
"""Cancel a MEXC order using V3 method"""
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
|
||||
params = {
|
||||
'orderId': order_id,
|
||||
'recvWindow': '5000',
|
||||
'symbol': symbol,
|
||||
'timestamp': timestamp
|
||||
}
|
||||
|
||||
query_string = urlencode(sorted(params.items()))
|
||||
signature = create_mexc_signature_v3(query_string, secret_key)
|
||||
|
||||
url = f"https://api.mexc.com/api/v3/order"
|
||||
data = f"{query_string}&signature={signature}"
|
||||
headers = {
|
||||
'X-MEXC-APIKEY': api_key,
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
|
||||
response = requests.delete(url, headers=headers, data=data, timeout=10)
|
||||
print(f"Cancel response: {response.status_code} - {response.text}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_mexc_order_v3()
|
130
NN/exchanges/mexc/debug/test_mexc_interface_debug.py
Normal file
130
NN/exchanges/mexc/debug/test_mexc_interface_debug.py
Normal file
@ -0,0 +1,130 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Debug MEXC Interface vs Manual
|
||||
|
||||
Compare what the interface sends vs what works manually
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import hmac
|
||||
import hashlib
|
||||
from pathlib import Path
|
||||
|
||||
# Add project root to path
|
||||
project_root = Path(__file__).parent
|
||||
sys.path.insert(0, str(project_root))
|
||||
|
||||
def debug_interface():
|
||||
"""Debug the interface signature generation"""
|
||||
print("MEXC Interface vs Manual Debug")
|
||||
print("=" * 50)
|
||||
|
||||
# Get API credentials
|
||||
api_key = os.getenv('MEXC_API_KEY', '')
|
||||
api_secret = os.getenv('MEXC_SECRET_KEY', '')
|
||||
|
||||
if not api_key or not api_secret:
|
||||
print("❌ No MEXC API credentials found")
|
||||
return False
|
||||
|
||||
from NN.exchanges.mexc_interface import MEXCInterface
|
||||
|
||||
mexc = MEXCInterface(api_key=api_key, api_secret=api_secret, test_mode=False, trading_mode='live')
|
||||
|
||||
# Test parameters exactly like the interface would use
|
||||
symbol = 'ETH/USDT'
|
||||
formatted_symbol = mexc._format_spot_symbol(symbol)
|
||||
quantity = 0.003
|
||||
price = 2900.0
|
||||
|
||||
print(f"Symbol: {symbol} -> {formatted_symbol}")
|
||||
print(f"Quantity: {quantity}")
|
||||
print(f"Price: {price}")
|
||||
|
||||
# Interface parameters (what place_order would create)
|
||||
interface_params = {
|
||||
'symbol': formatted_symbol,
|
||||
'side': 'BUY',
|
||||
'type': 'LIMIT',
|
||||
'quantity': str(quantity), # Interface converts to string
|
||||
'price': str(price), # Interface converts to string
|
||||
'timeInForce': 'GTC' # Interface adds this
|
||||
}
|
||||
|
||||
print(f"\nInterface params (before timestamp/recvWindow): {interface_params}")
|
||||
|
||||
# Add timestamp and recvWindow like _send_private_request does
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
interface_params['timestamp'] = timestamp
|
||||
interface_params['recvWindow'] = str(mexc.recv_window)
|
||||
|
||||
print(f"Interface params (complete): {interface_params}")
|
||||
|
||||
# Generate signature using interface method
|
||||
interface_signature = mexc._generate_signature(interface_params)
|
||||
print(f"Interface signature: {interface_signature}")
|
||||
|
||||
# Manual signature (what we tested successfully)
|
||||
manual_params = {
|
||||
'symbol': 'ETHUSDC',
|
||||
'side': 'BUY',
|
||||
'type': 'LIMIT',
|
||||
'quantity': '0.003',
|
||||
'price': '2900',
|
||||
'timestamp': timestamp,
|
||||
'recvWindow': '5000'
|
||||
}
|
||||
|
||||
print(f"\nManual params: {manual_params}")
|
||||
|
||||
# Generate signature manually (working method)
|
||||
mexc_order = ['symbol', 'side', 'type', 'quantity', 'price', 'timestamp', 'recvWindow']
|
||||
param_list = []
|
||||
for key in mexc_order:
|
||||
if key in manual_params:
|
||||
param_list.append(f"{key}={manual_params[key]}")
|
||||
|
||||
manual_params_string = '&'.join(param_list)
|
||||
manual_signature = hmac.new(
|
||||
api_secret.encode('utf-8'),
|
||||
manual_params_string.encode('utf-8'),
|
||||
hashlib.sha256
|
||||
).hexdigest()
|
||||
|
||||
print(f"Manual params string: {manual_params_string}")
|
||||
print(f"Manual signature: {manual_signature}")
|
||||
|
||||
# Compare parameters
|
||||
print(f"\n📊 COMPARISON:")
|
||||
print(f"symbol: Interface='{interface_params['symbol']}', Manual='{manual_params['symbol']}' {'✅' if interface_params['symbol'] == manual_params['symbol'] else '❌'}")
|
||||
print(f"side: Interface='{interface_params['side']}', Manual='{manual_params['side']}' {'✅' if interface_params['side'] == manual_params['side'] else '❌'}")
|
||||
print(f"type: Interface='{interface_params['type']}', Manual='{manual_params['type']}' {'✅' if interface_params['type'] == manual_params['type'] else '❌'}")
|
||||
print(f"quantity: Interface='{interface_params['quantity']}', Manual='{manual_params['quantity']}' {'✅' if interface_params['quantity'] == manual_params['quantity'] else '❌'}")
|
||||
print(f"price: Interface='{interface_params['price']}', Manual='{manual_params['price']}' {'✅' if interface_params['price'] == manual_params['price'] else '❌'}")
|
||||
print(f"timestamp: Interface='{interface_params['timestamp']}', Manual='{manual_params['timestamp']}' {'✅' if interface_params['timestamp'] == manual_params['timestamp'] else '❌'}")
|
||||
print(f"recvWindow: Interface='{interface_params['recvWindow']}', Manual='{manual_params['recvWindow']}' {'✅' if interface_params['recvWindow'] == manual_params['recvWindow'] else '❌'}")
|
||||
|
||||
# Check for timeInForce difference
|
||||
if 'timeInForce' in interface_params:
|
||||
print(f"timeInForce: Interface='{interface_params['timeInForce']}', Manual=None ❌ (EXTRA PARAMETER)")
|
||||
|
||||
# Test without timeInForce
|
||||
print(f"\n🔧 TESTING WITHOUT timeInForce:")
|
||||
interface_params_minimal = interface_params.copy()
|
||||
del interface_params_minimal['timeInForce']
|
||||
|
||||
interface_signature_minimal = mexc._generate_signature(interface_params_minimal)
|
||||
print(f"Interface signature (no timeInForce): {interface_signature_minimal}")
|
||||
|
||||
if interface_signature_minimal == manual_signature:
|
||||
print("✅ Signatures match when timeInForce is removed!")
|
||||
return True
|
||||
else:
|
||||
print("❌ Still don't match")
|
||||
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
debug_interface()
|
166
NN/exchanges/mexc/debug/test_mexc_order_signature.py
Normal file
166
NN/exchanges/mexc/debug/test_mexc_order_signature.py
Normal file
@ -0,0 +1,166 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Debug MEXC Order Signature
|
||||
|
||||
Tests order signature generation against MEXC API
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import hmac
|
||||
import hashlib
|
||||
import logging
|
||||
import requests
|
||||
from pathlib import Path
|
||||
|
||||
# Add project root to path
|
||||
project_root = Path(__file__).parent
|
||||
sys.path.insert(0, str(project_root))
|
||||
|
||||
# Enable debug logging
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
def test_order_signature():
|
||||
"""Test order signature generation"""
|
||||
print("MEXC Order Signature Debug")
|
||||
print("=" * 50)
|
||||
|
||||
# Get API credentials
|
||||
api_key = os.getenv('MEXC_API_KEY', '')
|
||||
api_secret = os.getenv('MEXC_SECRET_KEY', '')
|
||||
|
||||
if not api_key or not api_secret:
|
||||
print("❌ No MEXC API credentials found")
|
||||
return False
|
||||
|
||||
# Test order parameters
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
params = {
|
||||
'symbol': 'ETHUSDC',
|
||||
'side': 'BUY',
|
||||
'type': 'LIMIT',
|
||||
'quantity': '0.003',
|
||||
'price': '2900',
|
||||
'timeInForce': 'GTC',
|
||||
'timestamp': timestamp,
|
||||
'recvWindow': '5000'
|
||||
}
|
||||
|
||||
print(f"Order parameters: {params}")
|
||||
|
||||
# Test 1: Manual signature generation (timestamp first)
|
||||
print("\n1. Manual signature generation (timestamp first):")
|
||||
|
||||
# Create parameter string with timestamp first, then alphabetical
|
||||
param_list = [f"timestamp={params['timestamp']}"]
|
||||
for key in sorted(params.keys()):
|
||||
if key != 'timestamp':
|
||||
param_list.append(f"{key}={params[key]}")
|
||||
|
||||
params_string = '&'.join(param_list)
|
||||
print(f"Params string: {params_string}")
|
||||
|
||||
signature_manual = hmac.new(
|
||||
api_secret.encode('utf-8'),
|
||||
params_string.encode('utf-8'),
|
||||
hashlib.sha256
|
||||
).hexdigest()
|
||||
|
||||
print(f"Manual signature: {signature_manual}")
|
||||
|
||||
# Test 2: Interface signature generation
|
||||
print("\n2. Interface signature generation:")
|
||||
from NN.exchanges.mexc_interface import MEXCInterface
|
||||
|
||||
mexc = MEXCInterface(api_key=api_key, api_secret=api_secret, test_mode=False)
|
||||
signature_interface = mexc._generate_signature(params)
|
||||
print(f"Interface signature: {signature_interface}")
|
||||
|
||||
# Compare
|
||||
if signature_manual == signature_interface:
|
||||
print("✅ Signatures match!")
|
||||
else:
|
||||
print("❌ Signatures don't match")
|
||||
print("This indicates a problem with the signature generation method")
|
||||
return False
|
||||
|
||||
# Test 3: Try order with manual signature
|
||||
print("\n3. Testing order with manual method:")
|
||||
|
||||
url = "https://api.mexc.com/api/v3/order"
|
||||
headers = {
|
||||
'X-MEXC-APIKEY': api_key
|
||||
}
|
||||
|
||||
order_params = params.copy()
|
||||
order_params['signature'] = signature_manual
|
||||
|
||||
print(f"Making POST request to: {url}")
|
||||
print(f"Headers: {headers}")
|
||||
print(f"Params: {order_params}")
|
||||
|
||||
try:
|
||||
response = requests.post(url, headers=headers, params=order_params, timeout=10)
|
||||
print(f"Response status: {response.status_code}")
|
||||
print(f"Response: {response.text}")
|
||||
|
||||
if response.status_code == 200:
|
||||
print("✅ Manual order method works!")
|
||||
return True
|
||||
else:
|
||||
print("❌ Manual order method failed")
|
||||
|
||||
# Test 4: Try test order endpoint
|
||||
print("\n4. Testing with test order endpoint:")
|
||||
test_url = "https://api.mexc.com/api/v3/order/test"
|
||||
|
||||
response2 = requests.post(test_url, headers=headers, params=order_params, timeout=10)
|
||||
print(f"Test order response: {response2.status_code} - {response2.text}")
|
||||
|
||||
if response2.status_code == 200:
|
||||
print("✅ Test order works - real order parameters might have issues")
|
||||
|
||||
# Test 5: Try different parameter variations
|
||||
print("\n5. Testing different parameter sets:")
|
||||
|
||||
# Minimal parameters
|
||||
minimal_params = {
|
||||
'symbol': 'ETHUSDC',
|
||||
'side': 'BUY',
|
||||
'type': 'LIMIT',
|
||||
'quantity': '0.003',
|
||||
'price': '2900',
|
||||
'timestamp': str(int(time.time() * 1000)),
|
||||
'recvWindow': '5000'
|
||||
}
|
||||
|
||||
# Generate signature for minimal params
|
||||
minimal_param_list = [f"timestamp={minimal_params['timestamp']}"]
|
||||
for key in sorted(minimal_params.keys()):
|
||||
if key != 'timestamp':
|
||||
minimal_param_list.append(f"{key}={minimal_params[key]}")
|
||||
|
||||
minimal_params_string = '&'.join(minimal_param_list)
|
||||
minimal_signature = hmac.new(
|
||||
api_secret.encode('utf-8'),
|
||||
minimal_params_string.encode('utf-8'),
|
||||
hashlib.sha256
|
||||
).hexdigest()
|
||||
|
||||
minimal_params['signature'] = minimal_signature
|
||||
|
||||
print(f"Minimal params: {minimal_params_string}")
|
||||
print(f"Minimal signature: {minimal_signature}")
|
||||
|
||||
response3 = requests.post(test_url, headers=headers, params=minimal_params, timeout=10)
|
||||
print(f"Minimal params response: {response3.status_code} - {response3.text}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Request failed: {e}")
|
||||
return False
|
||||
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_order_signature()
|
161
NN/exchanges/mexc/debug/test_mexc_order_signature_v2.py
Normal file
161
NN/exchanges/mexc/debug/test_mexc_order_signature_v2.py
Normal file
@ -0,0 +1,161 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Debug MEXC Order Signature V2
|
||||
|
||||
Tests different signature generation approaches for orders
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import hmac
|
||||
import hashlib
|
||||
import logging
|
||||
import requests
|
||||
from pathlib import Path
|
||||
|
||||
# Add project root to path
|
||||
project_root = Path(__file__).parent
|
||||
sys.path.insert(0, str(project_root))
|
||||
|
||||
def test_different_approaches():
|
||||
"""Test different signature generation approaches"""
|
||||
print("MEXC Order Signature V2 - Different Approaches")
|
||||
print("=" * 60)
|
||||
|
||||
# Get API credentials
|
||||
api_key = os.getenv('MEXC_API_KEY', '')
|
||||
api_secret = os.getenv('MEXC_SECRET_KEY', '')
|
||||
|
||||
if not api_key or not api_secret:
|
||||
print("❌ No MEXC API credentials found")
|
||||
return False
|
||||
|
||||
# Test order parameters
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
params = {
|
||||
'symbol': 'ETHUSDC',
|
||||
'side': 'BUY',
|
||||
'type': 'LIMIT',
|
||||
'quantity': '0.003',
|
||||
'price': '2900',
|
||||
'timestamp': timestamp,
|
||||
'recvWindow': '5000'
|
||||
}
|
||||
|
||||
print(f"Order parameters: {params}")
|
||||
|
||||
def generate_signature(params_dict, method_name):
|
||||
print(f"\n{method_name}:")
|
||||
|
||||
if method_name == "Alphabetical (all params)":
|
||||
# Pure alphabetical ordering
|
||||
sorted_params = sorted(params_dict.items())
|
||||
params_string = '&'.join([f"{k}={v}" for k, v in sorted_params])
|
||||
|
||||
elif method_name == "Timestamp first":
|
||||
# Timestamp first, then alphabetical
|
||||
param_list = [f"timestamp={params_dict['timestamp']}"]
|
||||
for key in sorted(params_dict.keys()):
|
||||
if key != 'timestamp':
|
||||
param_list.append(f"{key}={params_dict[key]}")
|
||||
params_string = '&'.join(param_list)
|
||||
|
||||
elif method_name == "Postman order":
|
||||
# Try exact Postman order from collection
|
||||
postman_order = ['symbol', 'side', 'type', 'quantity', 'price', 'timestamp', 'recvWindow']
|
||||
param_list = []
|
||||
for key in postman_order:
|
||||
if key in params_dict:
|
||||
param_list.append(f"{key}={params_dict[key]}")
|
||||
params_string = '&'.join(param_list)
|
||||
|
||||
elif method_name == "Binance-style":
|
||||
# Similar to Binance (alphabetical)
|
||||
sorted_params = sorted(params_dict.items())
|
||||
params_string = '&'.join([f"{k}={v}" for k, v in sorted_params])
|
||||
|
||||
print(f"Params string: {params_string}")
|
||||
|
||||
signature = hmac.new(
|
||||
api_secret.encode('utf-8'),
|
||||
params_string.encode('utf-8'),
|
||||
hashlib.sha256
|
||||
).hexdigest()
|
||||
|
||||
print(f"Signature: {signature}")
|
||||
return signature, params_string
|
||||
|
||||
# Try different methods
|
||||
methods = [
|
||||
"Alphabetical (all params)",
|
||||
"Timestamp first",
|
||||
"Postman order",
|
||||
"Binance-style"
|
||||
]
|
||||
|
||||
for method in methods:
|
||||
signature, params_string = generate_signature(params, method)
|
||||
|
||||
# Test with test order endpoint
|
||||
test_url = "https://api.mexc.com/api/v3/order/test"
|
||||
headers = {'X-MEXC-APIKEY': api_key}
|
||||
|
||||
test_params = params.copy()
|
||||
test_params['signature'] = signature
|
||||
|
||||
try:
|
||||
response = requests.post(test_url, headers=headers, params=test_params, timeout=10)
|
||||
print(f"Response: {response.status_code} - {response.text}")
|
||||
|
||||
if response.status_code == 200:
|
||||
print(f"✅ {method} WORKS!")
|
||||
return True
|
||||
else:
|
||||
print(f"❌ {method} failed")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ {method} error: {e}")
|
||||
|
||||
# Try one more approach - use minimal parameters
|
||||
print("\n" + "=" * 60)
|
||||
print("Trying minimal parameters (no timeInForce):")
|
||||
|
||||
minimal_params = {
|
||||
'symbol': 'ETHUSDC',
|
||||
'side': 'BUY',
|
||||
'type': 'LIMIT',
|
||||
'quantity': '0.003',
|
||||
'price': '2900',
|
||||
'timestamp': str(int(time.time() * 1000)),
|
||||
'recvWindow': '5000'
|
||||
}
|
||||
|
||||
# Try alphabetical order with minimal params
|
||||
sorted_minimal = sorted(minimal_params.items())
|
||||
minimal_string = '&'.join([f"{k}={v}" for k, v in sorted_minimal])
|
||||
print(f"Minimal params string: {minimal_string}")
|
||||
|
||||
minimal_signature = hmac.new(
|
||||
api_secret.encode('utf-8'),
|
||||
minimal_string.encode('utf-8'),
|
||||
hashlib.sha256
|
||||
).hexdigest()
|
||||
|
||||
minimal_params['signature'] = minimal_signature
|
||||
|
||||
try:
|
||||
response = requests.post(test_url, headers=headers, params=minimal_params, timeout=10)
|
||||
print(f"Minimal response: {response.status_code} - {response.text}")
|
||||
|
||||
if response.status_code == 200:
|
||||
print("✅ Minimal parameters work!")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Minimal parameters error: {e}")
|
||||
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_different_approaches()
|
140
NN/exchanges/mexc/debug/test_mexc_signature_debug.py
Normal file
140
NN/exchanges/mexc/debug/test_mexc_signature_debug.py
Normal file
@ -0,0 +1,140 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Debug MEXC Signature Generation
|
||||
|
||||
Tests signature generation against known working examples
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import hmac
|
||||
import hashlib
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
# Add project root to path
|
||||
project_root = Path(__file__).parent
|
||||
sys.path.insert(0, str(project_root))
|
||||
|
||||
# Enable debug logging
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
def test_signature_generation():
|
||||
"""Test signature generation with known parameters"""
|
||||
print("MEXC Signature Generation Debug")
|
||||
print("=" * 50)
|
||||
|
||||
# Get API credentials
|
||||
api_key = os.getenv('MEXC_API_KEY', '')
|
||||
api_secret = os.getenv('MEXC_SECRET_KEY', '')
|
||||
|
||||
if not api_key or not api_secret:
|
||||
print("❌ No MEXC API credentials found")
|
||||
return False
|
||||
|
||||
# Import the interface
|
||||
from NN.exchanges.mexc_interface import MEXCInterface
|
||||
|
||||
mexc = MEXCInterface(api_key=api_key, api_secret=api_secret, test_mode=False)
|
||||
|
||||
# Test 1: Manual signature generation (working method from examples)
|
||||
print("\n1. Manual signature generation (working method):")
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
|
||||
# Parameters in exact order from working example
|
||||
params_string = f"timestamp={timestamp}&recvWindow=5000"
|
||||
print(f"Params string: {params_string}")
|
||||
|
||||
signature_manual = hmac.new(
|
||||
api_secret.encode('utf-8'),
|
||||
params_string.encode('utf-8'),
|
||||
hashlib.sha256
|
||||
).hexdigest()
|
||||
|
||||
print(f"Manual signature: {signature_manual}")
|
||||
|
||||
# Test 2: Interface signature generation
|
||||
print("\n2. Interface signature generation:")
|
||||
params_dict = {
|
||||
'timestamp': timestamp,
|
||||
'recvWindow': '5000'
|
||||
}
|
||||
|
||||
signature_interface = mexc._generate_signature(params_dict)
|
||||
print(f"Interface signature: {signature_interface}")
|
||||
|
||||
# Compare
|
||||
if signature_manual == signature_interface:
|
||||
print("✅ Signatures match!")
|
||||
else:
|
||||
print("❌ Signatures don't match")
|
||||
print("This indicates a problem with the signature generation method")
|
||||
|
||||
# Test 3: Try account request with manual signature
|
||||
print("\n3. Testing account request with manual method:")
|
||||
|
||||
import requests
|
||||
|
||||
url = f"https://api.mexc.com/api/v3/account"
|
||||
headers = {
|
||||
'X-MEXC-APIKEY': api_key
|
||||
}
|
||||
|
||||
params = {
|
||||
'timestamp': timestamp,
|
||||
'recvWindow': '5000',
|
||||
'signature': signature_manual
|
||||
}
|
||||
|
||||
print(f"Making request to: {url}")
|
||||
print(f"Headers: {headers}")
|
||||
print(f"Params: {params}")
|
||||
|
||||
try:
|
||||
response = requests.get(url, headers=headers, params=params, timeout=10)
|
||||
print(f"Response status: {response.status_code}")
|
||||
print(f"Response: {response.text}")
|
||||
|
||||
if response.status_code == 200:
|
||||
print("✅ Manual method works!")
|
||||
return True
|
||||
else:
|
||||
print("❌ Manual method failed")
|
||||
|
||||
# Test 4: Try different parameter ordering
|
||||
print("\n4. Testing different parameter orderings:")
|
||||
|
||||
# Try alphabetical ordering (current implementation)
|
||||
params_alpha = sorted(params_dict.items())
|
||||
params_alpha_string = '&'.join([f"{k}={v}" for k, v in params_alpha])
|
||||
print(f"Alphabetical: {params_alpha_string}")
|
||||
|
||||
# Try the exact order from Postman collection
|
||||
params_postman_string = f"recvWindow=5000×tamp={timestamp}"
|
||||
print(f"Postman order: {params_postman_string}")
|
||||
|
||||
sig_alpha = hmac.new(api_secret.encode('utf-8'), params_alpha_string.encode('utf-8'), hashlib.sha256).hexdigest()
|
||||
sig_postman = hmac.new(api_secret.encode('utf-8'), params_postman_string.encode('utf-8'), hashlib.sha256).hexdigest()
|
||||
|
||||
print(f"Alpha signature: {sig_alpha}")
|
||||
print(f"Postman signature: {sig_postman}")
|
||||
|
||||
# Test with postman order
|
||||
params_test = {
|
||||
'timestamp': timestamp,
|
||||
'recvWindow': '5000',
|
||||
'signature': sig_postman
|
||||
}
|
||||
|
||||
response2 = requests.get(url, headers=headers, params=params_test, timeout=10)
|
||||
print(f"Postman order response: {response2.status_code} - {response2.text}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Request failed: {e}")
|
||||
return False
|
||||
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_signature_generation()
|
81
NN/exchanges/mexc/debug/test_small_mexc_order.py
Normal file
81
NN/exchanges/mexc/debug/test_small_mexc_order.py
Normal file
@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test Small MEXC Order
|
||||
Try to place a very small real order to see what happens
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Add project root to path
|
||||
project_root = Path(__file__).parent
|
||||
sys.path.insert(0, str(project_root))
|
||||
|
||||
from NN.exchanges.mexc_interface import MEXCInterface
|
||||
|
||||
def test_small_order():
|
||||
"""Test placing a very small order"""
|
||||
print("Testing Small MEXC Order...")
|
||||
print("=" * 50)
|
||||
|
||||
# Get API credentials
|
||||
api_key = os.getenv('MEXC_API_KEY', '')
|
||||
api_secret = os.getenv('MEXC_SECRET_KEY', '')
|
||||
|
||||
if not api_key or not api_secret:
|
||||
print("❌ No MEXC API credentials found")
|
||||
return
|
||||
|
||||
# Create MEXC interface
|
||||
mexc = MEXCInterface(api_key=api_key, api_secret=api_secret, test_mode=False)
|
||||
|
||||
if not mexc.connect():
|
||||
print("❌ Failed to connect to MEXC API")
|
||||
return
|
||||
|
||||
print("✅ Connected to MEXC API")
|
||||
|
||||
# Get current price
|
||||
ticker = mexc.get_ticker("ETH/USDT") # Will be converted to ETHUSDC
|
||||
if not ticker:
|
||||
print("❌ Failed to get ticker")
|
||||
return
|
||||
|
||||
current_price = ticker['last']
|
||||
print(f"Current ETHUSDC Price: ${current_price:.2f}")
|
||||
|
||||
# Calculate a very small quantity (minimum possible)
|
||||
min_order_value = 10.0 # $10 minimum
|
||||
quantity = min_order_value / current_price
|
||||
quantity = round(quantity, 5) # MEXC precision
|
||||
|
||||
print(f"Test order: {quantity} ETH at ${current_price:.2f} = ${quantity * current_price:.2f}")
|
||||
|
||||
# Try placing the order
|
||||
print("\nPlacing test order...")
|
||||
try:
|
||||
result = mexc.place_order(
|
||||
symbol="ETH/USDT", # Will be converted to ETHUSDC
|
||||
side="BUY",
|
||||
order_type="MARKET", # Will be converted to LIMIT
|
||||
quantity=quantity
|
||||
)
|
||||
|
||||
if result:
|
||||
print("✅ Order placed successfully!")
|
||||
print(f"Order result: {result}")
|
||||
|
||||
# Try to cancel it immediately
|
||||
if 'orderId' in result:
|
||||
print(f"\nCanceling order {result['orderId']}...")
|
||||
cancel_result = mexc.cancel_order("ETH/USDT", result['orderId'])
|
||||
print(f"Cancel result: {cancel_result}")
|
||||
else:
|
||||
print("❌ Order placement failed")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Order error: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_small_order()
|
@ -14,6 +14,7 @@ import logging
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
from typing import Optional, List
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
@ -37,7 +38,7 @@ except ImportError:
|
||||
from binance_interface import BinanceInterface
|
||||
from mexc_interface import MEXCInterface
|
||||
|
||||
def create_exchange(exchange_name: str, api_key: str = None, api_secret: str = None, test_mode: bool = True) -> ExchangeInterface:
|
||||
def create_exchange(exchange_name: str, api_key: Optional[str] = None, api_secret: Optional[str] = None, test_mode: bool = True) -> ExchangeInterface:
|
||||
"""Create an exchange interface instance.
|
||||
|
||||
Args:
|
||||
@ -51,14 +52,18 @@ def create_exchange(exchange_name: str, api_key: str = None, api_secret: str = N
|
||||
"""
|
||||
exchange_name = exchange_name.lower()
|
||||
|
||||
# Use empty strings if None provided
|
||||
key = api_key or ""
|
||||
secret = api_secret or ""
|
||||
|
||||
if exchange_name == 'binance':
|
||||
return BinanceInterface(api_key, api_secret, test_mode)
|
||||
return BinanceInterface(key, secret, test_mode)
|
||||
elif exchange_name == 'mexc':
|
||||
return MEXCInterface(api_key, api_secret, test_mode)
|
||||
return MEXCInterface(key, secret, test_mode)
|
||||
else:
|
||||
raise ValueError(f"Unsupported exchange: {exchange_name}. Supported exchanges: binance, mexc")
|
||||
|
||||
def test_exchange(exchange: ExchangeInterface, symbols: list = None):
|
||||
def test_exchange(exchange: ExchangeInterface, symbols: Optional[List[str]] = None):
|
||||
"""Test the exchange interface.
|
||||
|
||||
Args:
|
||||
|
@ -1,76 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Check ETHUSDC Trading Rules and Precision
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Add project root to path
|
||||
project_root = Path(__file__).parent
|
||||
sys.path.insert(0, str(project_root))
|
||||
|
||||
from NN.exchanges.mexc_interface import MEXCInterface
|
||||
|
||||
def check_ethusdc_precision():
|
||||
"""Check ETHUSDC trading rules"""
|
||||
print("Checking ETHUSDC Trading Rules...")
|
||||
print("=" * 50)
|
||||
|
||||
# Get API credentials
|
||||
api_key = os.getenv('MEXC_API_KEY', '')
|
||||
api_secret = os.getenv('MEXC_SECRET_KEY', '')
|
||||
|
||||
if not api_key or not api_secret:
|
||||
print("❌ No MEXC API credentials found")
|
||||
return
|
||||
|
||||
# Create MEXC interface
|
||||
mexc = MEXCInterface(api_key=api_key, api_secret=api_secret, test_mode=False)
|
||||
|
||||
if not mexc.connect():
|
||||
print("❌ Failed to connect to MEXC API")
|
||||
return
|
||||
|
||||
print("✅ Connected to MEXC API")
|
||||
|
||||
# Check if ETHUSDC is supported
|
||||
if mexc.is_symbol_supported("ETH/USDT"): # Will be converted to ETHUSDC
|
||||
print("✅ ETHUSDC is supported for trading")
|
||||
else:
|
||||
print("❌ ETHUSDC is not supported for trading")
|
||||
return
|
||||
|
||||
# Get current ticker to see price
|
||||
ticker = mexc.get_ticker("ETH/USDT") # Will query ETHUSDC
|
||||
if ticker:
|
||||
price = ticker.get('last', 0)
|
||||
print(f"Current ETHUSDC Price: ${price:.2f}")
|
||||
|
||||
# Test different quantities to find minimum
|
||||
test_quantities = [
|
||||
0.001, # $3 worth
|
||||
0.01, # $30 worth
|
||||
0.1, # $300 worth
|
||||
0.009871, # Our calculated quantity
|
||||
]
|
||||
|
||||
print("\nTesting different quantities:")
|
||||
print("-" * 30)
|
||||
|
||||
for qty in test_quantities:
|
||||
rounded_qty = round(qty, 6)
|
||||
value_usd = rounded_qty * price if ticker else 0
|
||||
print(f"Quantity: {rounded_qty:8.6f} ETH (~${value_usd:.2f})")
|
||||
|
||||
print(f"\nOur test quantity: 0.009871 ETH")
|
||||
print(f"Rounded to 6 decimals: {round(0.009871, 6):.6f} ETH")
|
||||
print(f"Value: ~${round(0.009871, 6) * price:.2f}")
|
||||
|
||||
print("\nNext steps:")
|
||||
print("1. Check if minimum order value is $10+ USD")
|
||||
print("2. Try with a larger quantity (0.01 ETH = ~$30)")
|
||||
|
||||
if __name__ == "__main__":
|
||||
check_ethusdc_precision()
|
@ -1,97 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Get MEXC Exchange Info for ETHUSDC
|
||||
"""
|
||||
|
||||
import requests
|
||||
import json
|
||||
|
||||
def get_mexc_exchange_info():
|
||||
"""Get detailed MEXC exchange information for ETHUSDC"""
|
||||
print("Getting MEXC Exchange Info for ETHUSDC...")
|
||||
print("=" * 50)
|
||||
|
||||
try:
|
||||
# Get exchange info from MEXC public API
|
||||
resp = requests.get('https://api.mexc.com/api/v3/exchangeInfo')
|
||||
data = resp.json()
|
||||
|
||||
# Find ETHUSDC symbol
|
||||
ethusdc_info = None
|
||||
for symbol_info in data.get('symbols', []):
|
||||
if symbol_info['symbol'] == 'ETHUSDC':
|
||||
ethusdc_info = symbol_info
|
||||
break
|
||||
|
||||
if not ethusdc_info:
|
||||
print("❌ ETHUSDC symbol not found")
|
||||
return
|
||||
|
||||
print("✅ Found ETHUSDC symbol information")
|
||||
print(f"Symbol: {ethusdc_info['symbol']}")
|
||||
print(f"Status: {ethusdc_info['status']}")
|
||||
print(f"Base Asset: {ethusdc_info['baseAsset']}")
|
||||
print(f"Quote Asset: {ethusdc_info['quoteAsset']}")
|
||||
print(f"Base Precision: {ethusdc_info['baseAssetPrecision']}")
|
||||
print(f"Quote Precision: {ethusdc_info['quoteAssetPrecision']}")
|
||||
|
||||
print("\nFilters:")
|
||||
print("-" * 20)
|
||||
|
||||
lot_size_filter = None
|
||||
min_notional_filter = None
|
||||
|
||||
for filter_info in ethusdc_info.get('filters', []):
|
||||
filter_type = filter_info['filterType']
|
||||
print(f"\n{filter_type}:")
|
||||
|
||||
if filter_type == 'LOT_SIZE':
|
||||
lot_size_filter = filter_info
|
||||
elif filter_type == 'MIN_NOTIONAL':
|
||||
min_notional_filter = filter_info
|
||||
|
||||
for key, value in filter_info.items():
|
||||
if key != 'filterType':
|
||||
print(f" {key}: {value}")
|
||||
|
||||
# Analyze requirements
|
||||
print("\n" + "=" * 50)
|
||||
print("ANALYSIS:")
|
||||
|
||||
if lot_size_filter:
|
||||
min_qty = float(lot_size_filter['minQty'])
|
||||
step_size = lot_size_filter['stepSize']
|
||||
|
||||
print(f"Minimum Quantity: {min_qty} ETH")
|
||||
print(f"Step Size: {step_size}")
|
||||
|
||||
# Check our test quantity
|
||||
test_qty = 0.009871
|
||||
print(f"\nOur quantity: {test_qty}")
|
||||
print(f"Meets minimum?: {'✅ Yes' if test_qty >= min_qty else '❌ No'}")
|
||||
|
||||
# Check step size compliance
|
||||
if '.' in step_size:
|
||||
decimal_places = len(step_size.split('.')[-1].rstrip('0'))
|
||||
properly_rounded = round(test_qty, decimal_places)
|
||||
print(f"Required decimals: {decimal_places}")
|
||||
print(f"Properly rounded: {properly_rounded}")
|
||||
|
||||
if min_notional_filter:
|
||||
min_notional = float(min_notional_filter['minNotional'])
|
||||
test_value = 0.009871 * 3031 # approximate price
|
||||
print(f"\nMinimum Order Value: ${min_notional}")
|
||||
print(f"Our order value: ${test_value:.2f}")
|
||||
print(f"Meets minimum?: {'✅ Yes' if test_value >= min_notional else '❌ No'}")
|
||||
|
||||
print("\n💡 RECOMMENDATIONS:")
|
||||
if lot_size_filter and min_notional_filter:
|
||||
safe_qty = max(float(lot_size_filter['minQty']) * 1.1, min_notional / 3000)
|
||||
print(f"Use quantity >= {safe_qty:.6f} ETH for safe trading")
|
||||
print(f"This equals ~${safe_qty * 3031:.2f} USD")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
get_mexc_exchange_info()
|
@ -1,170 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test Live Trading - Verify MEXC Connection and Trading
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import logging
|
||||
import asyncio
|
||||
from datetime import datetime
|
||||
|
||||
# Add project root to path
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
from core.trading_executor import TradingExecutor
|
||||
from core.config import get_config
|
||||
|
||||
# Setup logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
async def test_live_trading():
|
||||
"""Test live trading functionality"""
|
||||
try:
|
||||
logger.info("=== LIVE TRADING TEST ===")
|
||||
logger.info("Testing MEXC connection and account balance reading")
|
||||
|
||||
# Initialize trading executor
|
||||
logger.info("Initializing Trading Executor...")
|
||||
executor = TradingExecutor("config.yaml")
|
||||
|
||||
# Check trading mode
|
||||
logger.info(f"Trading Mode: {executor.trading_mode}")
|
||||
logger.info(f"Simulation Mode: {executor.simulation_mode}")
|
||||
logger.info(f"Trading Enabled: {executor.trading_enabled}")
|
||||
|
||||
if executor.simulation_mode:
|
||||
logger.warning("WARNING: Still in simulation mode. Check config.yaml")
|
||||
return
|
||||
|
||||
# Test 1: Get account balance
|
||||
logger.info("\n=== TEST 1: ACCOUNT BALANCE ===")
|
||||
try:
|
||||
balances = executor.get_account_balance()
|
||||
logger.info("Account Balances:")
|
||||
|
||||
total_value = 0.0
|
||||
for asset, balance_info in balances.items():
|
||||
if balance_info['total'] > 0:
|
||||
logger.info(f" {asset}: {balance_info['total']:.6f} ({balance_info['type']})")
|
||||
if asset in ['USDT', 'USDC', 'USD']:
|
||||
total_value += balance_info['total']
|
||||
|
||||
logger.info(f"Total USD Value: ${total_value:.2f}")
|
||||
|
||||
if total_value < 25:
|
||||
logger.warning(f"Account balance ${total_value:.2f} may be insufficient for testing")
|
||||
else:
|
||||
logger.info(f"Account balance ${total_value:.2f} looks good for testing")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting account balance: {e}")
|
||||
return
|
||||
|
||||
# Test 2: Get current ETH price
|
||||
logger.info("\n=== TEST 2: MARKET DATA ===")
|
||||
try:
|
||||
# Test getting current price for ETH/USDT
|
||||
if executor.exchange:
|
||||
ticker = executor.exchange.get_ticker("ETH/USDT")
|
||||
if ticker and 'last' in ticker:
|
||||
current_price = ticker['last']
|
||||
logger.info(f"Current ETH/USDT Price: ${current_price:.2f}")
|
||||
else:
|
||||
logger.error("Failed to get ETH/USDT ticker data")
|
||||
return
|
||||
else:
|
||||
logger.error("Exchange interface not available")
|
||||
return
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting market data: {e}")
|
||||
return
|
||||
|
||||
# Test 3: Calculate position sizing
|
||||
logger.info("\n=== TEST 3: POSITION SIZING ===")
|
||||
try:
|
||||
# Test position size calculation with different confidence levels
|
||||
test_confidences = [0.3, 0.5, 0.7, 0.9]
|
||||
|
||||
for confidence in test_confidences:
|
||||
position_size = executor._calculate_position_size(confidence, current_price)
|
||||
quantity = position_size / current_price
|
||||
logger.info(f"Confidence {confidence:.1f}: ${position_size:.2f} = {quantity:.6f} ETH")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error calculating position sizes: {e}")
|
||||
return
|
||||
|
||||
# Test 4: Small test trade (optional - requires confirmation)
|
||||
logger.info("\n=== TEST 4: TEST TRADE (OPTIONAL) ===")
|
||||
|
||||
user_input = input("Do you want to execute a SMALL test trade? (type 'YES' to confirm): ")
|
||||
if user_input.upper() == 'YES':
|
||||
try:
|
||||
logger.info("Executing SMALL test BUY order...")
|
||||
|
||||
# Execute a very small buy order with low confidence (minimum position size)
|
||||
success = executor.execute_signal(
|
||||
symbol="ETH/USDT",
|
||||
action="BUY",
|
||||
confidence=0.3, # Low confidence = minimum position size
|
||||
current_price=current_price
|
||||
)
|
||||
|
||||
if success:
|
||||
logger.info("✅ Test BUY order executed successfully!")
|
||||
|
||||
# Wait a moment, then try to sell
|
||||
await asyncio.sleep(2)
|
||||
|
||||
logger.info("Executing corresponding SELL order...")
|
||||
success = executor.execute_signal(
|
||||
symbol="ETH/USDT",
|
||||
action="SELL",
|
||||
confidence=0.9, # High confidence to ensure execution
|
||||
current_price=current_price
|
||||
)
|
||||
|
||||
if success:
|
||||
logger.info("✅ Test SELL order executed successfully!")
|
||||
logger.info("✅ Full test trade cycle completed!")
|
||||
else:
|
||||
logger.warning("❌ Test SELL order failed")
|
||||
else:
|
||||
logger.warning("❌ Test BUY order failed")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error executing test trade: {e}")
|
||||
else:
|
||||
logger.info("Test trade skipped")
|
||||
|
||||
# Test 5: Position and trade history
|
||||
logger.info("\n=== TEST 5: POSITIONS AND HISTORY ===")
|
||||
try:
|
||||
positions = executor.get_positions()
|
||||
trade_history = executor.get_trade_history()
|
||||
|
||||
logger.info(f"Current Positions: {len(positions)}")
|
||||
for symbol, position in positions.items():
|
||||
logger.info(f" {symbol}: {position.side} {position.quantity:.6f} @ ${position.entry_price:.2f}")
|
||||
|
||||
logger.info(f"Trade History: {len(trade_history)} trades")
|
||||
for trade in trade_history[-5:]: # Last 5 trades
|
||||
pnl_str = f"${trade.pnl:+.2f}" if trade.pnl else "$0.00"
|
||||
logger.info(f" {trade.symbol} {trade.side}: {pnl_str}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting positions/history: {e}")
|
||||
|
||||
logger.info("\n=== LIVE TRADING TEST COMPLETED ===")
|
||||
logger.info("If all tests passed, live trading is ready!")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error in live trading test: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(test_live_trading())
|
@ -1,50 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test MEXC Symbol Conversion
|
||||
Verify that USDT symbols are properly converted to USDC for MEXC execution
|
||||
"""
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Add project root to path
|
||||
project_root = Path(__file__).parent
|
||||
sys.path.insert(0, str(project_root))
|
||||
|
||||
from NN.exchanges.mexc_interface import MEXCInterface
|
||||
|
||||
def test_symbol_conversion():
|
||||
"""Test the symbol conversion logic"""
|
||||
print("Testing MEXC Symbol Conversion...")
|
||||
print("=" * 50)
|
||||
|
||||
# Create MEXC interface (no need for real API keys for symbol conversion)
|
||||
mexc = MEXCInterface(api_key="dummy", api_secret="dummy", test_mode=True)
|
||||
|
||||
# Test cases
|
||||
test_symbols = [
|
||||
"ETH/USDT",
|
||||
"BTC/USDT",
|
||||
"ETHUSDT",
|
||||
"BTCUSDT",
|
||||
"ETH/USDC", # Should stay as USDC
|
||||
"ETHUSDC" # Should stay as USDC
|
||||
]
|
||||
|
||||
print("Symbol Conversion Results:")
|
||||
print("-" * 30)
|
||||
|
||||
for symbol in test_symbols:
|
||||
converted = mexc._format_spot_symbol(symbol)
|
||||
print(f"{symbol:12} -> {converted}")
|
||||
|
||||
print("\nExpected Results for MEXC Trading:")
|
||||
print("- ETH/USDT should become ETHUSDC")
|
||||
print("- BTC/USDT should become BTCUSDC")
|
||||
print("- ETHUSDT should become ETHUSDC")
|
||||
print("- BTCUSDT should become BTCUSDC")
|
||||
print("- ETH/USDC should stay ETHUSDC")
|
||||
print("- ETHUSDC should stay ETHUSDC")
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_symbol_conversion()
|
Reference in New Issue
Block a user