mexc API failed, working on futures API as it what i we need anyway

This commit is contained in:
Dobromir Popov
2025-07-03 00:56:02 +03:00
parent 568ec049db
commit 118c34b990
8 changed files with 17370 additions and 714 deletions

File diff suppressed because it is too large Load Diff

View File

@ -154,7 +154,7 @@ trading:
# MEXC Trading API Configuration # MEXC Trading API Configuration
mexc_trading: mexc_trading:
enabled: true enabled: true
trading_mode: simulation # simulation, testnet, live trading_mode: live # simulation, testnet, live
# FIXED: Meaningful position sizes for learning # FIXED: Meaningful position sizes for learning
base_position_usd: 25.0 # $25 base position (was $1) base_position_usd: 25.0 # $25 base position (was $1)

View File

@ -27,7 +27,6 @@ try:
from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException, WebDriverException from selenium.common.exceptions import TimeoutException, WebDriverException
from webdriver_manager.chrome import ChromeDriverManager from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
except ImportError: except ImportError:
print("Please install selenium and webdriver-manager:") print("Please install selenium and webdriver-manager:")
print("pip install selenium webdriver-manager") print("pip install selenium webdriver-manager")
@ -68,16 +67,21 @@ class MEXCRequestInterceptor:
self.cookies_file = f"mexc_cookies_{self.timestamp}.json" self.cookies_file = f"mexc_cookies_{self.timestamp}.json"
def setup_chrome_with_logging(self) -> webdriver.Chrome: def setup_chrome_with_logging(self) -> webdriver.Chrome:
"""Setup Chrome with performance logging enabled""" """Setup Brave browser with performance logging enabled"""
logger.info("Setting up ChromeDriver with request interception...") logger.info("Setting up ChromeDriver with request interception for Brave browser...")
# Chrome options # Chrome options (used for Brave as it's Chromium-based)
chrome_options = Options() chrome_options = Options()
if self.headless: if self.headless:
chrome_options.add_argument("--headless") chrome_options.add_argument("--headless")
logger.info("Running in headless mode") logger.info("Running in headless mode")
# Set the binary location for Brave
# brave_binary_path = "C:\\Program Files\\BraveSoftware\\Brave-Browser\\Application\\brave.exe"
# chrome_options.binary_location = brave_binary_path
# logger.info(f"Using Brave binary at: {brave_binary_path}")
# Essential options for automation # Essential options for automation
chrome_options.add_argument("--no-sandbox") chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-dev-shm-usage") chrome_options.add_argument("--disable-dev-shm-usage")
@ -99,12 +103,14 @@ class MEXCRequestInterceptor:
chrome_options.add_argument("--log-level=0") chrome_options.add_argument("--log-level=0")
chrome_options.add_argument("--v=1") chrome_options.add_argument("--v=1")
# Set capabilities for performance logging # Set logging preferences for performance data
caps = DesiredCapabilities.CHROME chrome_options.set_capability('goog:loggingPrefs', {
caps['goog:loggingPrefs'] = {
'performance': 'ALL', 'performance': 'ALL',
'browser': 'ALL' 'browser': 'ALL'
} })
# # Add profile directory argument as provided by the user
# chrome_options.add_argument("--profile-directory=Profile 3")
try: try:
# Automatically download and install ChromeDriver # Automatically download and install ChromeDriver
@ -114,8 +120,7 @@ class MEXCRequestInterceptor:
# Create driver # Create driver
driver = webdriver.Chrome( driver = webdriver.Chrome(
service=service, service=service,
options=chrome_options, options=chrome_options
desired_capabilities=caps
) )
# Hide automation indicators # Hide automation indicators

View File

@ -3,6 +3,9 @@ Trading Executor for MEXC API Integration
This module handles the execution of trading signals through the MEXC exchange API. This module handles the execution of trading signals through the MEXC exchange API.
It includes position management, risk controls, and safety features. It includes position management, risk controls, and safety features.
https://github.com/mexcdevelop/mexc-api-postman/blob/main/MEXC%20V3.postman_collection.json
MEXC V3.postman_collection.json
""" """
import logging import logging
@ -89,7 +92,8 @@ class TradingExecutor:
self.exchange = MEXCInterface( self.exchange = MEXCInterface(
api_key=api_key, api_key=api_key,
api_secret=api_secret, api_secret=api_secret,
test_mode=exchange_test_mode test_mode=exchange_test_mode,
trading_mode=trading_mode
) )
# Trading state # Trading state
@ -101,6 +105,8 @@ class TradingExecutor:
self.trading_enabled = self.mexc_config.get('enabled', False) self.trading_enabled = self.mexc_config.get('enabled', False)
self.trading_mode = trading_mode self.trading_mode = trading_mode
logger.debug(f"TRADING EXECUTOR: Initial trading_enabled state from config: {self.trading_enabled}")
# Legacy compatibility (deprecated) # Legacy compatibility (deprecated)
self.dry_run = self.simulation_mode self.dry_run = self.simulation_mode
@ -109,7 +115,12 @@ class TradingExecutor:
# Connect to exchange # Connect to exchange
if self.trading_enabled: if self.trading_enabled:
self._connect_exchange() logger.info("TRADING EXECUTOR: Attempting to connect to exchange...")
if not self._connect_exchange():
logger.error("TRADING EXECUTOR: Failed initial exchange connection. Trading will be disabled.")
self.trading_enabled = False
else:
logger.info("TRADING EXECUTOR: Trading is explicitly disabled in config.")
logger.info(f"Trading Executor initialized - Mode: {self.trading_mode}, Enabled: {self.trading_enabled}") logger.info(f"Trading Executor initialized - Mode: {self.trading_mode}, Enabled: {self.trading_enabled}")
@ -143,17 +154,20 @@ class TradingExecutor:
def _connect_exchange(self) -> bool: def _connect_exchange(self) -> bool:
"""Connect to the MEXC exchange""" """Connect to the MEXC exchange"""
try: try:
logger.debug("TRADING EXECUTOR: Calling self.exchange.connect()...")
connected = self.exchange.connect() connected = self.exchange.connect()
logger.debug(f"TRADING EXECUTOR: self.exchange.connect() returned: {connected}")
if connected: if connected:
logger.info("Successfully connected to MEXC exchange") logger.info("Successfully connected to MEXC exchange")
return True return True
else: else:
logger.error("Failed to connect to MEXC exchange") logger.error("Failed to connect to MEXC exchange: Connection returned False.")
if not self.dry_run: if not self.dry_run:
logger.info("TRADING EXECUTOR: Setting trading_enabled to False due to connection failure.")
self.trading_enabled = False self.trading_enabled = False
return False return False
except Exception as e: except Exception as e:
logger.error(f"Error connecting to MEXC exchange: {e}") logger.error(f"Error connecting to MEXC exchange: {e}. Setting trading_enabled to False.")
self.trading_enabled = False self.trading_enabled = False
return False return False
@ -170,8 +184,9 @@ class TradingExecutor:
Returns: Returns:
bool: True if trade executed successfully bool: True if trade executed successfully
""" """
logger.debug(f"TRADING EXECUTOR: execute_signal called. trading_enabled: {self.trading_enabled}")
if not self.trading_enabled: if not self.trading_enabled:
logger.info(f"Trading disabled - Signal: {action} {symbol} (confidence: {confidence:.2f})") logger.info(f"Trading disabled - Signal: {action} {symbol} (confidence: {confidence:.2f}) - Reason: Trading executor is not enabled.")
return False return False
if action == 'HOLD': if action == 'HOLD':
@ -181,23 +196,51 @@ class TradingExecutor:
if not self._check_safety_conditions(symbol, action): if not self._check_safety_conditions(symbol, action):
return False return False
# Get current price if not provided # Get current price if not provided
if current_price is None: if current_price is None:
ticker = self.exchange.get_ticker(symbol) ticker = self.exchange.get_ticker(symbol)
if not ticker: if not ticker or 'last' not in ticker:
logger.error(f"Failed to get current price for {symbol}") logger.error(f"Failed to get current price for {symbol} or ticker is malformed.")
return False return False
current_price = ticker['last'] current_price = ticker['last']
# Assert that current_price is not None for type checking # Assert that current_price is not None for type checking
assert current_price is not None, "current_price should not be None at this point" assert current_price is not None, "current_price should not be None at this point"
# --- Balance check before executing trade ---
# Only perform balance check for BUY actions or SHORT (initial sell) actions
if action == 'BUY' or (action == 'SELL' and symbol not in self.positions) or (action == 'SHORT'):
# Determine the quote asset (e.g., USDT, USDC) from the symbol
if '/' in symbol:
quote_asset = symbol.split('/')[1].upper() # Assuming symbol is like ETH/USDT
else:
# Fallback for symbols like ETHUSDT (assuming last 4 chars are quote)
quote_asset = symbol[-4:].upper()
# Calculate required capital for the trade
# If we are selling (to open a short position), we need collateral based on the position size
# For simplicity, assume required capital is the full position value in USD
required_capital = self._calculate_position_size(confidence, current_price)
# Get available balance for the quote asset
available_balance = self.exchange.get_balance(quote_asset)
logger.info(f"BALANCE CHECK: Symbol: {symbol}, Action: {action}, Required: ${required_capital:.2f} {quote_asset}, Available: ${available_balance:.2f} {quote_asset}")
if available_balance < required_capital:
logger.warning(f"Trade blocked for {symbol} {action}: Insufficient {quote_asset} balance. "
f"Required: ${required_capital:.2f}, Available: ${available_balance:.2f}")
return False
# --- End Balance check ---
with self.lock: with self.lock:
try: try:
if action == 'BUY': if action == 'BUY':
return self._execute_buy(symbol, confidence, current_price) return self._execute_buy(symbol, confidence, current_price)
elif action == 'SELL': elif action == 'SELL':
return self._execute_sell(symbol, confidence, current_price) return self._execute_sell(symbol, confidence, current_price)
elif action == 'SHORT': # Explicitly handle SHORT if it's a direct signal
return self._execute_short(symbol, confidence, current_price)
else: else:
logger.warning(f"Unknown action: {action}") logger.warning(f"Unknown action: {action}")
return False return False

View File

@ -0,0 +1,29 @@
{
"bm_sv": "D92603BBC020E9C2CD11B2EBC8F22050~YAAQJKVf1NW5K7CXAQAAwtMVzRzHARcY60jrPVzy9G79fN3SY4z988SWHHxQlbPpyZHOj76c20AjCnS0QwveqzB08zcRoauoIe/sP3svlaIso9PIdWay0KIIVUe1XsiTJRfTm/DmS+QdrOuJb09rbfWLcEJF4/0QK7VY0UTzPTI2V3CMtxnmYjd1+tjfYsvt1R6O+Mw9mYjb7SjhRmiP/exY2UgZdLTJiqd+iWkc5Wejy5m6g5duOfRGtiA9mfs=~1",
"bm_sz": "98D80FE4B23FE6352AE5194DA699FDDB~YAAQJKVf1GK4K7CXAQAAeQ0UzRw+aXiY5/Ujp+sZm0a4j+XAJFn6fKT4oph8YqIKF6uHSgXkFY3mBt8WWY98Y2w1QzOEFRkje8HTUYQgJsV59y5DIOTZKC6wutPD/bKdVi9ZKtk4CWbHIIRuCrnU1Nw2jqj5E0hsorhKGh8GeVsAeoao8FWovgdYD6u8Qpbr9aL5YZgVEIqJx6WmWLmcIg+wA8UFj8751Fl0B3/AGxY2pACUPjonPKNuX/UDYA5e98plOYUnYLyQMEGIapSrWKo1VXhKBDPLNedJ/Q2gOCGEGlj/u1Fs407QxxXwCvRSegL91y6modtL5JGoFucV1pYc4pgTwEAEdJfcLCEBaButTbaHI9T3SneqgCoGeatMMaqz0GHbvMD7fBQofARBqzN1L6aGlmmAISMzI3wx/SnsfXBl~3228228~3294529",
"_abck": "0288E759712AF333A6EE15F66BC2A662~-1~YAAQJKVf1GC4K7CXAQAAeQ0UzQ77TfyX5SOWTgdW3DVqNFrTLz2fhLo2OC4I6ZHnW9qB0vwTjFDfOB65BwLSeFZoyVypVCGTtY/uL6f4zX0AxEGAU8tLg/jeO0acO4JpGrjYZSW1F56vEd9JbPU2HQPNERorgCDLQMSubMeLCfpqMp3VCW4w0Ssnk6Y4pBSs4mh0PH95v56XXDvat9k20/JPoK3Ip5kK2oKh5Vpk5rtNTVea66P0NBjVUw/EddRUuDDJpc8T4DtTLDXnD5SNDxEq8WDkrYd5kP4dNe0PtKcSOPYs2QLUbvAzfBuMvnhoSBaCjsqD15EZ3eDAoioli/LzsWSxaxetYfm0pA/s5HBXMdOEDi4V0E9b79N28rXcC8IJEHXtfdZdhJjwh1FW14lqF9iuOwER81wDEnIVtgwTwpd3ffrc35aNjb+kGiQ8W0FArFhUI/ZY2NDvPVngRjNrmRm0CsCm+6mdxxVNsGNMPKYG29mcGDi2P9HGDk45iOm0vzoaYUl1PlOh4VGq/V3QGbPYpkBsBtQUjrf/SQJe5IAbjCICTYlgxTo+/FAEjec+QdUsagTgV8YNycQfTK64A2bs1L1n+RO5tapLThU6NkxnUbqHOm6168RnT8ZRoAUpkJ5m3QpqSsuslnPRUPyxUr73v514jTBIUGsq4pUeRpXXd9FAh8Xkn4VZ9Bh3q4jP7eZ9Sv58mgnEVltNBFkeG3zsuIp5Hu69MSBU+8FD4gVlncbBinrTLNWRB8F00Gyvc03unrAznsTEyLiDq9guQf9tQNcGjxfggfnGq/Z1Gy/A7WMjiYw7pwGRVzAYnRgtcZoww9gQ/FdGkbp2Xl+oVZpaqFsHVvafWyOFr4pqQsmd353ddgKLjsEnpy/jcdUsIR/Ph3pYv++XlypXehXj0/GHL+WsosujJrYk4TuEsPKUcyHNr+r844mYUIhCYsI6XVKrq3fimdfdhmlkW8J1kZSTmFwP8QcwGlTK/mZDTJPyf8K5ugXcqOU8oIQzt5B2zfRwRYKHdhb8IUw=~-1~-1~-1",
"RT": "\"z=1&dm=www.mexc.com&si=f5d53b58-7845-4db4-99f1-444e43d35199&ss=mcmh857q&sl=3&tt=90n&bcn=%2F%2F684dd311.akstat.io%2F&ld=1c9o\"",
"mexc_fingerprint_visitorId": "tv1xchuZQbx9N0aBztUG",
"_ga_L6XJCQTK75": "GS2.1.s1751492192$o1$g1$t1751492248$j4$l0$h0",
"uc_token": "WEB66f893ede865e5d927efdea4a82e655ad5190239c247997d744ef9cd075f6f1e",
"u_id": "WEB66f893ede865e5d927efdea4a82e655ad5190239c247997d744ef9cd075f6f1e",
"_fbp": "fb.1.1751492193579.314807866777158389",
"mxc_exchange_layout": "BA",
"sensorsdata2015jssdkcross": "%7B%22distinct_id%22%3A%2221a8728990b84f4fa3ae64c8004b4aaa%22%2C%22first_id%22%3A%22197cd11dc751be-0dd66c04c69e96-26011f51-3686400-197cd11dc76189d%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%2C%22%24latest_referrer%22%3A%22%22%2C%22%24latest_landing_page%22%3A%22https%3A%2F%2Fwww.mexc.com%2Fen-GB%2Flogin%3Fprevious%3D%252Ffutures%252FETH_USDT%253Ftype%253Dlinear_swap%22%7D%2C%22identities%22%3A%22eyIkaWRlbnRpdHlfY29va2llX2lkIjoiMTk3Y2QxMWRjNzUxYmUtMGRkNjZjMDRjNjllOTYtMjYwMTFmNTEtMzY4NjQwMC0xOTdjZDExZGM3NjE4OWQiLCIkaWRlbnRpdHlfbG9naW5faWQiOiIyMWE4NzI4OTkwYjg0ZjRmYTNhZTY0YzgwMDRiNGFhYSJ9%22%2C%22history_login_id%22%3A%7B%22name%22%3A%22%24identity_login_id%22%2C%22value%22%3A%2221a8728990b84f4fa3ae64c8004b4aaa%22%7D%2C%22%24device_id%22%3A%22197cd11dc751be-0dd66c04c69e96-26011f51-3686400-197cd11dc76189d%22%7D",
"mxc_theme_main": "dark",
"mexc_fingerprint_requestId": "1751492199306.WMvKJd",
"_ym_visorc": "b",
"mexc_clearance_modal_show_date": "2025-07-03-undefined",
"ak_bmsc": "35C21AA65F819E0BF9BEBDD10DCF7B70~000000000000000000000000000000~YAAQJKVf1BK2K7CXAQAAPAISzRwQdUOUs1H3HPAdl4COMFQAl+aEPzppLbdgrwA7wXbP/LZpxsYCFflUHDppYKUjzXyTZ9tIojSF3/6CW3OCiPhQo/qhf6XPbC4oQHpCNWaC9GJWEs/CGesQdfeBbhkXdfh+JpgmgCF788+x8IveDE9+9qaL/3QZRy+E7zlKjjvmMxBpahRy+ktY9/KMrCY2etyvtm91KUclr4k8HjkhtNJOlthWgUyiANXJtfbNUMgt+Hqgqa7QzSUfAEpxIXQ1CuROoY9LbU292LRN5TbtBy/uNv6qORT38rKsnpi7TGmyFSB9pj3YsoSzIuAUxYXSh4hXRgAoUQm3Yh5WdLp4ONeyZC1LIb8VCY5xXRy/VbfaHH1w7FodY1HpfHGKSiGHSNwqoiUmMPx13Rgjsgki4mE7bwFmG2H5WAilRIOZA5OkndEqGrOuiNTON7l6+g6mH0MzZ+/+3AjnfF2sXxFuV9itcs9x",
"mxc_theme_upcolor": "upgreen",
"_vid_t": "mQUFl49q1yLZhrL4tvOtFF38e+hGW5QoMS+eXKVD9Q4vQau6icnyipsdyGLW/FBukiO2ItK7EtzPIPMFrE5SbIeLSm1NKc/j+ZmobhX063QAlskf1x1J",
"_ym_isad": "2",
"_ym_d": "1751492196",
"_ym_uid": "1751492196843266888",
"bm_mi": "02862693F007017AEFD6639269A60D08~YAAQJKVf1Am2K7CXAQAAIf4RzRzNGqZ7Q3BC0kAAp/0sCOhHxxvEWTb7mBl8p7LUz0W6RZbw5Etz03Tvqu3H6+sb+yu1o0duU+bDflt7WLVSOfG5cA3im8Jeo6wZhqmxTu6gGXuBgxhrHw/RGCgcknxuZQiRM9cbM6LlZIAYiugFm2xzmO/1QcpjDhs4S8d880rv6TkMedlkYGwdgccAmvbaRVSmX9d5Yukm+hY+5GWuyKMeOjpatAhcgjShjpSDwYSpyQE7vVZLBp7TECIjI9uoWzR8A87YHScKYEuE08tb8YtGdG3O6g70NzasSX0JF3XTCjrVZA==~1",
"_ga": "GA1.1.626437359.1751492192",
"NEXT_LOCALE": "en-GB",
"x-mxc-fingerprint": "tv1xchuZQbx9N0aBztUG",
"CLIENT_LANG": "en-GB",
"sajssdk_2015_cross_new_user": "1"
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,64 @@
import os
import logging
import sys
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
# Add project root to path
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from NN.exchanges.mexc_interface import MEXCInterface
from core.config import get_config
def test_mexc_private_api():
"""Test MEXC private API endpoints"""
# Load configuration
config = get_config('config.yaml')
mexc_config = config.get('mexc_trading', {})
# Get API credentials
api_key = os.getenv('MEXC_API_KEY', mexc_config.get('api_key', ''))
api_secret = os.getenv('MEXC_SECRET_KEY', mexc_config.get('api_secret', ''))
if not api_key or not api_secret:
logger.error("API key or secret not found. Please set MEXC_API_KEY and MEXC_SECRET_KEY environment variables.")
return
# Initialize MEXC interface in test mode
mexc = MEXCInterface(api_key=api_key, api_secret=api_secret, test_mode=True, trading_mode='simulation')
# Test connection
if not mexc.connect():
logger.error("Failed to connect to MEXC API")
return
# Test getting account information
logger.info("Testing account information retrieval...")
account_info = mexc.get_account_info()
if account_info:
logger.info(f"Account info retrieved: {account_info}")
else:
logger.error("Failed to retrieve account info")
# Test getting balance for a specific asset
asset = "USDT"
logger.info(f"Testing balance retrieval for {asset}...")
balance = mexc.get_balance(asset)
logger.info(f"Balance for {asset}: {balance}")
# Test placing a simulated order (in test mode)
symbol = "ETH/USDT"
side = "buy"
order_type = "market"
quantity = 0.01 # Small quantity for testing
logger.info(f"Testing order placement for {symbol} ({side}, {order_type}, qty: {quantity})...")
order_result = mexc.place_order(symbol=symbol, side=side, order_type=order_type, quantity=quantity)
if order_result:
logger.info(f"Order placed successfully: {order_result}")
else:
logger.error("Failed to place order")
if __name__ == "__main__":
test_mexc_private_api()

View File

@ -1,13 +1,31 @@
from NN.exchanges.mexc_interface import MEXCInterface
import logging import logging
import os
from NN.exchanges.mexc_interface import MEXCInterface
# Set up logging to see debug info # Set up logging to see debug info
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
# Load API credentials from environment variables or a configuration file
# For testing, prioritize environment variables for CI/CD or sensitive data
# Fallback to a placeholder or configuration reading if env vars are not set
api_key = os.getenv('MEXC_API_KEY', '')
api_secret = os.getenv('MEXC_SECRET_KEY', '')
# If using a config file, you might do something like:
# from core.config import get_config
# config = get_config('config.yaml')
# mexc_config = config.get('mexc_trading', {})
# api_key = mexc_config.get('api_key', api_key)
# api_secret = mexc_config.get('api_secret', api_secret)
if not api_key or not api_secret:
logging.error("API keys are not set. Please set MEXC_API_KEY and MEXC_SECRET_KEY environment variables or configure config.yaml")
exit(1)
# Create interface with API credentials # Create interface with API credentials
mexc = MEXCInterface( mexc = MEXCInterface(
api_key='mx0aBYs33eIilxBWC5', api_key=api_key,
api_secret='45d0b3c26f2644f19bfb98b07741b2f5', api_secret=api_secret,
trading_mode='simulation' trading_mode='simulation'
) )