initial balance on dash
This commit is contained in:
parent
4567912186
commit
ae62d893bc
@ -1,17 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"trade_id": 1,
|
|
||||||
"side": "LONG",
|
|
||||||
"entry_time": "2025-05-27T10:47:14.593940+00:00",
|
|
||||||
"exit_time": "2025-05-27T10:47:19.603178+00:00",
|
|
||||||
"entry_price": 2635.93,
|
|
||||||
"exit_price": 2635.41,
|
|
||||||
"size": 0.179,
|
|
||||||
"gross_pnl": -0.09307999999999673,
|
|
||||||
"fees": 0.0,
|
|
||||||
"net_pnl": -0.09307999999999673,
|
|
||||||
"duration": "0:00:05.009238",
|
|
||||||
"symbol": "ETH/USDT",
|
|
||||||
"mexc_executed": false
|
|
||||||
}
|
|
||||||
]
|
|
@ -401,4 +401,47 @@ class TradingExecutor:
|
|||||||
"""Reset daily statistics (call at start of new day)"""
|
"""Reset daily statistics (call at start of new day)"""
|
||||||
self.daily_trades = 0
|
self.daily_trades = 0
|
||||||
self.daily_loss = 0.0
|
self.daily_loss = 0.0
|
||||||
logger.info("Daily trading statistics reset")
|
logger.info("Daily trading statistics reset")
|
||||||
|
|
||||||
|
def get_account_balance(self) -> Dict[str, Dict[str, float]]:
|
||||||
|
"""Get account balance information from MEXC
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Dict with asset balances in format:
|
||||||
|
{
|
||||||
|
'USDT': {'free': 100.0, 'locked': 0.0},
|
||||||
|
'ETH': {'free': 0.5, 'locked': 0.0},
|
||||||
|
...
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if not self.exchange:
|
||||||
|
logger.error("Exchange interface not available")
|
||||||
|
return {}
|
||||||
|
|
||||||
|
# Get account info from MEXC
|
||||||
|
account_info = self.exchange.get_account_info()
|
||||||
|
if not account_info:
|
||||||
|
logger.error("Failed to get account info from MEXC")
|
||||||
|
return {}
|
||||||
|
|
||||||
|
balances = {}
|
||||||
|
for balance in account_info.get('balances', []):
|
||||||
|
asset = balance.get('asset', '')
|
||||||
|
free = float(balance.get('free', 0))
|
||||||
|
locked = float(balance.get('locked', 0))
|
||||||
|
|
||||||
|
# Only include assets with non-zero balance
|
||||||
|
if free > 0 or locked > 0:
|
||||||
|
balances[asset] = {
|
||||||
|
'free': free,
|
||||||
|
'locked': locked,
|
||||||
|
'total': free + locked
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info(f"Retrieved balances for {len(balances)} assets")
|
||||||
|
return balances
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error getting account balance: {e}")
|
||||||
|
return {}
|
222
test_mexc_balance_orders.py
Normal file
222
test_mexc_balance_orders.py
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Test script for MEXC balance retrieval and $1 order execution
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Add project root to path
|
||||||
|
sys.path.insert(0, os.path.abspath('.'))
|
||||||
|
|
||||||
|
from core.trading_executor import TradingExecutor
|
||||||
|
from core.data_provider import DataProvider
|
||||||
|
|
||||||
|
# Setup logging
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.INFO,
|
||||||
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||||
|
)
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
def test_mexc_balance():
|
||||||
|
"""Test MEXC balance retrieval"""
|
||||||
|
print("="*60)
|
||||||
|
print("TESTING MEXC BALANCE RETRIEVAL")
|
||||||
|
print("="*60)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Initialize trading executor
|
||||||
|
executor = TradingExecutor()
|
||||||
|
|
||||||
|
# Check if trading is enabled
|
||||||
|
print(f"Trading enabled: {executor.trading_enabled}")
|
||||||
|
print(f"Dry run mode: {executor.dry_run}")
|
||||||
|
|
||||||
|
if not executor.trading_enabled:
|
||||||
|
print("❌ Trading not enabled - check config.yaml and API keys")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Test balance retrieval
|
||||||
|
print("\n📊 Retrieving account balance...")
|
||||||
|
balances = executor.get_account_balance()
|
||||||
|
|
||||||
|
if not balances:
|
||||||
|
print("❌ No balances retrieved - check API connectivity")
|
||||||
|
return False
|
||||||
|
|
||||||
|
print(f"✅ Retrieved balances for {len(balances)} assets:")
|
||||||
|
for asset, balance_info in balances.items():
|
||||||
|
free = balance_info['free']
|
||||||
|
locked = balance_info['locked']
|
||||||
|
total = balance_info['total']
|
||||||
|
print(f" {asset}: Free: {free:.6f}, Locked: {locked:.6f}, Total: {total:.6f}")
|
||||||
|
|
||||||
|
# Check USDT balance specifically
|
||||||
|
if 'USDT' in balances:
|
||||||
|
usdt_free = balances['USDT']['free']
|
||||||
|
print(f"\n💰 USDT available for trading: ${usdt_free:.2f}")
|
||||||
|
|
||||||
|
if usdt_free >= 2.0: # Need at least $2 for testing
|
||||||
|
print("✅ Sufficient USDT balance for $1 order testing")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print(f"⚠️ Insufficient USDT balance for testing (need $2+, have ${usdt_free:.2f})")
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
print("❌ No USDT balance found")
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error testing MEXC balance: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def test_mexc_order_execution():
|
||||||
|
"""Test $1 order execution (dry run)"""
|
||||||
|
print("\n" + "="*60)
|
||||||
|
print("TESTING $1 ORDER EXECUTION (DRY RUN)")
|
||||||
|
print("="*60)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Initialize components
|
||||||
|
executor = TradingExecutor()
|
||||||
|
data_provider = DataProvider()
|
||||||
|
|
||||||
|
if not executor.trading_enabled:
|
||||||
|
print("❌ Trading not enabled - cannot test order execution")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Test symbol
|
||||||
|
symbol = "ETH/USDT"
|
||||||
|
|
||||||
|
# Get current price
|
||||||
|
print(f"\n📈 Getting current price for {symbol}...")
|
||||||
|
ticker_data = data_provider.get_historical_data(symbol, '1m', limit=1, refresh=True)
|
||||||
|
|
||||||
|
if ticker_data is None or ticker_data.empty:
|
||||||
|
print(f"❌ Could not get price data for {symbol}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
current_price = float(ticker_data['close'].iloc[-1])
|
||||||
|
print(f"✅ Current {symbol} price: ${current_price:.2f}")
|
||||||
|
|
||||||
|
# Calculate order size for $1
|
||||||
|
usd_amount = 1.0
|
||||||
|
crypto_amount = usd_amount / current_price
|
||||||
|
print(f"💱 $1 USD = {crypto_amount:.6f} ETH")
|
||||||
|
|
||||||
|
# Test buy signal execution
|
||||||
|
print(f"\n🛒 Testing BUY signal execution...")
|
||||||
|
buy_success = executor.execute_signal(
|
||||||
|
symbol=symbol,
|
||||||
|
action='BUY',
|
||||||
|
confidence=0.75,
|
||||||
|
current_price=current_price
|
||||||
|
)
|
||||||
|
|
||||||
|
if buy_success:
|
||||||
|
print("✅ BUY signal executed successfully")
|
||||||
|
|
||||||
|
# Check position
|
||||||
|
positions = executor.get_positions()
|
||||||
|
if symbol in positions:
|
||||||
|
position = positions[symbol]
|
||||||
|
print(f"📍 Position opened: {position.quantity:.6f} {symbol} @ ${position.entry_price:.2f}")
|
||||||
|
|
||||||
|
# Test sell signal execution
|
||||||
|
print(f"\n💰 Testing SELL signal execution...")
|
||||||
|
sell_success = executor.execute_signal(
|
||||||
|
symbol=symbol,
|
||||||
|
action='SELL',
|
||||||
|
confidence=0.80,
|
||||||
|
current_price=current_price * 1.001 # Simulate small price increase
|
||||||
|
)
|
||||||
|
|
||||||
|
if sell_success:
|
||||||
|
print("✅ SELL signal executed successfully")
|
||||||
|
|
||||||
|
# Check trade history
|
||||||
|
trades = executor.get_trade_history()
|
||||||
|
if trades:
|
||||||
|
last_trade = trades[-1]
|
||||||
|
print(f"📊 Trade completed: P&L = ${last_trade.pnl:.4f}")
|
||||||
|
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print("❌ SELL signal failed")
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
print("❌ No position found after BUY signal")
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
print("❌ BUY signal failed")
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error testing order execution: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def test_dashboard_balance_integration():
|
||||||
|
"""Test dashboard balance integration"""
|
||||||
|
print("\n" + "="*60)
|
||||||
|
print("TESTING DASHBOARD BALANCE INTEGRATION")
|
||||||
|
print("="*60)
|
||||||
|
|
||||||
|
try:
|
||||||
|
from web.dashboard import TradingDashboard
|
||||||
|
|
||||||
|
# Create dashboard with trading executor
|
||||||
|
executor = TradingExecutor()
|
||||||
|
dashboard = TradingDashboard(trading_executor=executor)
|
||||||
|
|
||||||
|
print(f"Dashboard starting balance: ${dashboard.starting_balance:.2f}")
|
||||||
|
|
||||||
|
if dashboard.starting_balance > 0:
|
||||||
|
print("✅ Dashboard successfully retrieved starting balance")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print("⚠️ Dashboard using default balance (MEXC not connected)")
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error testing dashboard integration: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Run all tests"""
|
||||||
|
print("🚀 MEXC INTEGRATION TESTING")
|
||||||
|
print("Testing balance retrieval and $1 order execution")
|
||||||
|
|
||||||
|
# Test 1: Balance retrieval
|
||||||
|
balance_test = test_mexc_balance()
|
||||||
|
|
||||||
|
# Test 2: Order execution (only if balance test passes)
|
||||||
|
if balance_test:
|
||||||
|
order_test = test_mexc_order_execution()
|
||||||
|
else:
|
||||||
|
print("\n⏭️ Skipping order execution test (balance test failed)")
|
||||||
|
order_test = False
|
||||||
|
|
||||||
|
# Test 3: Dashboard integration
|
||||||
|
dashboard_test = test_dashboard_balance_integration()
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
print("\n" + "="*60)
|
||||||
|
print("TEST SUMMARY")
|
||||||
|
print("="*60)
|
||||||
|
print(f"Balance Retrieval: {'✅ PASS' if balance_test else '❌ FAIL'}")
|
||||||
|
print(f"Order Execution: {'✅ PASS' if order_test else '❌ FAIL'}")
|
||||||
|
print(f"Dashboard Integration: {'✅ PASS' if dashboard_test else '❌ FAIL'}")
|
||||||
|
|
||||||
|
if balance_test and order_test and dashboard_test:
|
||||||
|
print("\n🎉 ALL TESTS PASSED - Ready for live $1 testing!")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print("\n⚠️ Some tests failed - check configuration and API keys")
|
||||||
|
return False
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
success = main()
|
||||||
|
sys.exit(0 if success else 1)
|
@ -93,7 +93,7 @@ class TradingDashboard:
|
|||||||
self.current_position = None # {'side': 'BUY', 'price': 3456.78, 'size': 0.1, 'timestamp': datetime}
|
self.current_position = None # {'side': 'BUY', 'price': 3456.78, 'size': 0.1, 'timestamp': datetime}
|
||||||
self.total_realized_pnl = 0.0
|
self.total_realized_pnl = 0.0
|
||||||
self.total_fees = 0.0
|
self.total_fees = 0.0
|
||||||
self.starting_balance = 100.0 # Starting portfolio value in USD
|
self.starting_balance = self._get_initial_balance() # Get balance from MEXC or default to 100
|
||||||
|
|
||||||
# Closed trades tracking for accounting
|
# Closed trades tracking for accounting
|
||||||
self.closed_trades = [] # List of all closed trades with full details
|
self.closed_trades = [] # List of all closed trades with full details
|
||||||
@ -143,6 +143,34 @@ class TradingDashboard:
|
|||||||
|
|
||||||
logger.info("Trading Dashboard initialized with continuous training")
|
logger.info("Trading Dashboard initialized with continuous training")
|
||||||
|
|
||||||
|
def _get_initial_balance(self) -> float:
|
||||||
|
"""Get initial USDT balance from MEXC or return default"""
|
||||||
|
try:
|
||||||
|
if self.trading_executor and hasattr(self.trading_executor, 'get_account_balance'):
|
||||||
|
logger.info("Fetching initial balance from MEXC...")
|
||||||
|
|
||||||
|
# Get USDT balance from MEXC
|
||||||
|
balance_info = self.trading_executor.get_account_balance()
|
||||||
|
if balance_info and 'USDT' in balance_info:
|
||||||
|
usdt_balance = float(balance_info['USDT'].get('free', 0))
|
||||||
|
if usdt_balance > 0:
|
||||||
|
logger.info(f"MEXC: Retrieved USDT balance: ${usdt_balance:.2f}")
|
||||||
|
return usdt_balance
|
||||||
|
else:
|
||||||
|
logger.warning("MEXC: No USDT balance found")
|
||||||
|
else:
|
||||||
|
logger.warning("MEXC: Failed to retrieve balance info")
|
||||||
|
else:
|
||||||
|
logger.info("MEXC: Trading executor not available for balance retrieval")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error getting MEXC balance: {e}")
|
||||||
|
|
||||||
|
# Fallback to default
|
||||||
|
default_balance = 100.0
|
||||||
|
logger.info(f"Using default starting balance: ${default_balance:.2f}")
|
||||||
|
return default_balance
|
||||||
|
|
||||||
def _setup_layout(self):
|
def _setup_layout(self):
|
||||||
"""Setup the dashboard layout"""
|
"""Setup the dashboard layout"""
|
||||||
self.app.layout = html.Div([
|
self.app.layout = html.Div([
|
||||||
@ -1376,11 +1404,16 @@ class TradingDashboard:
|
|||||||
# Add MEXC execution status to decision record
|
# Add MEXC execution status to decision record
|
||||||
decision['mexc_executed'] = mexc_success
|
decision['mexc_executed'] = mexc_success
|
||||||
|
|
||||||
# Calculate confidence-based position size (0.05 to 0.2 range)
|
# Calculate USD-based position size for testing ($1 orders)
|
||||||
base_size = 0.1 # Base size
|
if current_price and current_price > 0:
|
||||||
confidence_multiplier = max(0.5, min(2.0, decision['confidence'] * 2)) # 0.5x to 2x multiplier
|
usd_size = 1.0 # $1 per trade for testing
|
||||||
position_size = base_size * confidence_multiplier
|
position_size = usd_size / current_price # Convert USD to crypto amount
|
||||||
decision['size'] = round(position_size, 3) # Update decision with calculated size
|
decision['size'] = round(position_size, 6) # Update decision with calculated size
|
||||||
|
decision['usd_size'] = usd_size # Track USD amount for logging
|
||||||
|
else:
|
||||||
|
# Fallback if no price available
|
||||||
|
decision['size'] = 0.001
|
||||||
|
decision['usd_size'] = 1.0
|
||||||
|
|
||||||
if decision['action'] == 'BUY':
|
if decision['action'] == 'BUY':
|
||||||
# First, close any existing SHORT position
|
# First, close any existing SHORT position
|
||||||
@ -1452,7 +1485,7 @@ class TradingDashboard:
|
|||||||
trade_record['fees'] = fee
|
trade_record['fees'] = fee
|
||||||
self.session_trades.append(trade_record)
|
self.session_trades.append(trade_record)
|
||||||
|
|
||||||
logger.info(f"[TRADE] OPENED LONG: {decision['size']} @ ${decision['price']:.2f} (confidence: {decision['confidence']:.1%})")
|
logger.info(f"[TRADE] OPENED LONG: {decision['size']:.6f} (~${decision.get('usd_size', 1.0):.2f}) @ ${decision['price']:.2f} (confidence: {decision['confidence']:.1%})")
|
||||||
|
|
||||||
elif self.current_position['side'] == 'LONG':
|
elif self.current_position['side'] == 'LONG':
|
||||||
# Already have a long position - could add to it or replace it
|
# Already have a long position - could add to it or replace it
|
||||||
@ -1577,7 +1610,7 @@ class TradingDashboard:
|
|||||||
trade_record['fees'] = fee
|
trade_record['fees'] = fee
|
||||||
self.session_trades.append(trade_record)
|
self.session_trades.append(trade_record)
|
||||||
|
|
||||||
logger.info(f"[TRADE] OPENED SHORT: {decision['size']} @ ${decision['price']:.2f} (confidence: {decision['confidence']:.1%})")
|
logger.info(f"[TRADE] OPENED SHORT: {decision['size']:.6f} (~${decision.get('usd_size', 1.0):.2f}) @ ${decision['price']:.2f} (confidence: {decision['confidence']:.1%})")
|
||||||
|
|
||||||
elif self.current_position['side'] == 'SHORT':
|
elif self.current_position['side'] == 'SHORT':
|
||||||
# Already have a short position - could add to it or replace it
|
# Already have a short position - could add to it or replace it
|
||||||
|
Loading…
x
Reference in New Issue
Block a user