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:
enabled: true
trading_mode: simulation # simulation, testnet, live
trading_mode: live # simulation, testnet, live
# FIXED: Meaningful position sizes for learning
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.common.exceptions import TimeoutException, WebDriverException
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
except ImportError:
print("Please install selenium and webdriver-manager:")
print("pip install selenium webdriver-manager")
@ -68,16 +67,21 @@ class MEXCRequestInterceptor:
self.cookies_file = f"mexc_cookies_{self.timestamp}.json"
def setup_chrome_with_logging(self) -> webdriver.Chrome:
"""Setup Chrome with performance logging enabled"""
logger.info("Setting up ChromeDriver with request interception...")
"""Setup Brave browser with performance logging enabled"""
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()
if self.headless:
chrome_options.add_argument("--headless")
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
chrome_options.add_argument("--no-sandbox")
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("--v=1")
# Set capabilities for performance logging
caps = DesiredCapabilities.CHROME
caps['goog:loggingPrefs'] = {
# Set logging preferences for performance data
chrome_options.set_capability('goog:loggingPrefs', {
'performance': 'ALL',
'browser': 'ALL'
}
})
# # Add profile directory argument as provided by the user
# chrome_options.add_argument("--profile-directory=Profile 3")
try:
# Automatically download and install ChromeDriver
@ -114,8 +120,7 @@ class MEXCRequestInterceptor:
# Create driver
driver = webdriver.Chrome(
service=service,
options=chrome_options,
desired_capabilities=caps
options=chrome_options
)
# 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.
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
@ -89,7 +92,8 @@ class TradingExecutor:
self.exchange = MEXCInterface(
api_key=api_key,
api_secret=api_secret,
test_mode=exchange_test_mode
test_mode=exchange_test_mode,
trading_mode=trading_mode
)
# Trading state
@ -101,6 +105,8 @@ class TradingExecutor:
self.trading_enabled = self.mexc_config.get('enabled', False)
self.trading_mode = trading_mode
logger.debug(f"TRADING EXECUTOR: Initial trading_enabled state from config: {self.trading_enabled}")
# Legacy compatibility (deprecated)
self.dry_run = self.simulation_mode
@ -109,7 +115,12 @@ class TradingExecutor:
# Connect to exchange
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}")
@ -143,17 +154,20 @@ class TradingExecutor:
def _connect_exchange(self) -> bool:
"""Connect to the MEXC exchange"""
try:
logger.debug("TRADING EXECUTOR: Calling self.exchange.connect()...")
connected = self.exchange.connect()
logger.debug(f"TRADING EXECUTOR: self.exchange.connect() returned: {connected}")
if connected:
logger.info("Successfully connected to MEXC exchange")
return True
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:
logger.info("TRADING EXECUTOR: Setting trading_enabled to False due to connection failure.")
self.trading_enabled = False
return False
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
return False
@ -170,8 +184,9 @@ class TradingExecutor:
Returns:
bool: True if trade executed successfully
"""
logger.debug(f"TRADING EXECUTOR: execute_signal called. trading_enabled: {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
if action == 'HOLD':
@ -184,20 +199,48 @@ class TradingExecutor:
# Get current price if not provided
if current_price is None:
ticker = self.exchange.get_ticker(symbol)
if not ticker:
logger.error(f"Failed to get current price for {symbol}")
if not ticker or 'last' not in ticker:
logger.error(f"Failed to get current price for {symbol} or ticker is malformed.")
return False
current_price = ticker['last']
# 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"
# --- 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:
try:
if action == 'BUY':
return self._execute_buy(symbol, confidence, current_price)
elif action == 'SELL':
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:
logger.warning(f"Unknown action: {action}")
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 os
from NN.exchanges.mexc_interface import MEXCInterface
# Set up logging to see debug 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
mexc = MEXCInterface(
api_key='mx0aBYs33eIilxBWC5',
api_secret='45d0b3c26f2644f19bfb98b07741b2f5',
api_key=api_key,
api_secret=api_secret,
trading_mode='simulation'
)