more quiet logging
This commit is contained in:
parent
1a1c410922
commit
dc532f8795
@ -2,6 +2,11 @@ https://github.com/mexcdevelop/mexc-api-sdk/blob/main/README.md#test-new-order
|
||||
|
||||
python mexc_tick_visualizer.py --symbol BTC/USDT --interval 1.0 --candle 60
|
||||
|
||||
python main.py --mode live --symbol ETH/USDT --timeframe 1m --use-websocket
|
||||
|
||||
python main.py --mode live --symbol BTC/USDT --timeframe 1m --use-websocket --dashboard
|
||||
# http://localhost:8060
|
||||
|
||||
|
||||
& 'C:\Users\popov\miniforge3\python.exe' 'c:\Users\popov\.cursor\extensions\ms-python.debugpy-2024.6.0-win32-x64\bundled\libs\debugpy\adapter/../..\debugpy\launcher' '51766' '--' 'main.py' '--mode' 'live' '--demo' 'false' '--symbol' 'ETH/USDT' '--timeframe' '1m' '--leverage' '50'
|
||||
|
||||
|
229
main.py
229
main.py
@ -48,6 +48,22 @@ logging.basicConfig(
|
||||
)
|
||||
logger = logging.getLogger("trading_bot")
|
||||
|
||||
# Look for WebSocket specific logger
|
||||
websocket_logger = logging.getLogger('websocket') # or similar name
|
||||
websocket_logger.setLevel(logging.INFO) # Change this from DEBUG to INFO
|
||||
|
||||
# Add this somewhere after the logger is defined
|
||||
class WebSocketFilter(logging.Filter):
|
||||
def filter(self, record):
|
||||
# Filter out DEBUG messages from WebSocket-related modules
|
||||
if record.levelno == logging.DEBUG and ('websocket' in record.name or
|
||||
'protocol' in record.name or
|
||||
'realtime' in record.name):
|
||||
return False
|
||||
return True
|
||||
|
||||
logger.addFilter(WebSocketFilter())
|
||||
|
||||
# Load environment variables
|
||||
load_dotenv()
|
||||
MEXC_API_KEY = os.getenv('MEXC_API_KEY')
|
||||
@ -287,8 +303,15 @@ class PricePredictionModel(nn.Module):
|
||||
return total_loss / epochs
|
||||
|
||||
class TradingEnvironment:
|
||||
"""Trading environment for reinforcement learning with enhanced features"""
|
||||
def __init__(self, initial_balance=INITIAL_BALANCE, window_size=30, demo=True):
|
||||
"""Initialize the trading environment"""
|
||||
"""Initialize trading environment
|
||||
|
||||
Args:
|
||||
initial_balance: Starting account balance
|
||||
window_size: Number of candles in the state window
|
||||
demo: Whether to run in demo mode
|
||||
"""
|
||||
self.initial_balance = initial_balance
|
||||
self.balance = initial_balance
|
||||
self.window_size = window_size
|
||||
@ -310,6 +333,13 @@ class TradingEnvironment:
|
||||
self.current_step = 0
|
||||
self.current_price = 0
|
||||
|
||||
# Risk management parameters (adjusted for more aggressive trading)
|
||||
self.stop_loss_pct = STOP_LOSS_PERCENT * 0.8 # Tighter stop loss (80% of original)
|
||||
self.take_profit_pct = TAKE_PROFIT_PERCENT * 1.5 # Higher take profit (150% of original)
|
||||
self.trailing_stop_activated = False
|
||||
self.trailing_stop_distance = 0
|
||||
self.max_position_size_pct = 0.8 # Use up to 80% of balance for position size
|
||||
|
||||
# For tracking signals for visualization
|
||||
self.trade_signals = []
|
||||
|
||||
@ -473,6 +503,9 @@ class TradingEnvironment:
|
||||
}
|
||||
return next_state, 0, done, info
|
||||
|
||||
# Adapt trading parameters to current market conditions
|
||||
self.adapt_trading_parameters_to_market()
|
||||
|
||||
# Store current price before taking action
|
||||
self.current_price = self.data[self.current_step]['close']
|
||||
|
||||
@ -985,8 +1018,9 @@ class TradingEnvironment:
|
||||
self.position = 'long'
|
||||
self.entry_price = self.current_price
|
||||
self.position_size = self.calculate_position_size()
|
||||
self.stop_loss = self.entry_price * (1 - STOP_LOSS_PERCENT/100)
|
||||
self.take_profit = self.entry_price * (1 + TAKE_PROFIT_PERCENT/100)
|
||||
# Use the adjusted risk parameters
|
||||
self.stop_loss = self.entry_price * (1 - self.stop_loss_pct/100)
|
||||
self.take_profit = self.entry_price * (1 + self.take_profit_pct/100)
|
||||
|
||||
# Check if this is an optimal buy point (bottom)
|
||||
current_idx = len(self.features['price']) - 1
|
||||
@ -1059,8 +1093,8 @@ class TradingEnvironment:
|
||||
self.entry_price = self.current_price
|
||||
self.entry_index = len(self.features['price']) - 1
|
||||
self.position_size = self.calculate_position_size()
|
||||
self.stop_loss = self.entry_price * (1 - STOP_LOSS_PERCENT/100)
|
||||
self.take_profit = self.entry_price * (1 + TAKE_PROFIT_PERCENT/100)
|
||||
self.stop_loss = self.entry_price * (1 - self.stop_loss_pct/100)
|
||||
self.take_profit = self.entry_price * (1 + self.take_profit_pct/100)
|
||||
|
||||
# Check if this is an optimal buy point
|
||||
if hasattr(self, 'optimal_bottoms') and self.entry_index in self.optimal_bottoms:
|
||||
@ -1074,8 +1108,9 @@ class TradingEnvironment:
|
||||
self.position = 'short'
|
||||
self.entry_price = self.current_price
|
||||
self.position_size = self.calculate_position_size()
|
||||
self.stop_loss = self.entry_price * (1 + STOP_LOSS_PERCENT/100)
|
||||
self.take_profit = self.entry_price * (1 - TAKE_PROFIT_PERCENT/100)
|
||||
# Use the adjusted risk parameters
|
||||
self.stop_loss = self.entry_price * (1 + self.stop_loss_pct/100)
|
||||
self.take_profit = self.entry_price * (1 - self.take_profit_pct/100)
|
||||
|
||||
# Check if this is an optimal sell point (top)
|
||||
current_idx = len(self.features['price']) - 1
|
||||
@ -1138,8 +1173,8 @@ class TradingEnvironment:
|
||||
self.position = 'short'
|
||||
self.entry_price = self.current_price
|
||||
self.position_size = self.calculate_position_size()
|
||||
self.stop_loss = self.entry_price * (1 + STOP_LOSS_PERCENT/100)
|
||||
self.take_profit = self.entry_price * (1 - TAKE_PROFIT_PERCENT/100)
|
||||
self.stop_loss = self.entry_price * (1 + self.stop_loss_pct/100)
|
||||
self.take_profit = self.entry_price * (1 - self.take_profit_pct/100)
|
||||
|
||||
# Check if this is an optimal sell point
|
||||
current_idx = len(self.features['price']) - 1
|
||||
@ -1387,26 +1422,19 @@ class TradingEnvironment:
|
||||
logger.info(f"Identified {len(bottoms)} optimal buy points and {len(tops)} optimal sell points")
|
||||
|
||||
def calculate_position_size(self):
|
||||
"""Calculate position size based on current balance and risk parameters"""
|
||||
# Use a fixed percentage of balance for each trade
|
||||
risk_percent = 5.0 # Risk 5% of balance per trade
|
||||
"""Calculate position size based on current balance and risk parameters
|
||||
|
||||
# Calculate position size with leverage
|
||||
position_size = self.balance * (risk_percent / 100) * MAX_LEVERAGE
|
||||
Returns:
|
||||
float: Position size in quote currency
|
||||
"""
|
||||
# More aggressive position sizing
|
||||
risk_amount = self.balance * (self.max_position_size_pct * random.uniform(0.7, 1.0))
|
||||
|
||||
# Apply a safety factor to avoid liquidation
|
||||
safety_factor = 0.8
|
||||
position_size *= safety_factor
|
||||
# In futures trading, adjust for leverage
|
||||
if hasattr(self, 'leverage') and self.leverage > 1:
|
||||
risk_amount = min(risk_amount * self.leverage, self.balance * 10) # Limit max risk
|
||||
|
||||
# Ensure minimum position size
|
||||
min_position = 10.0 # Minimum position size in USD
|
||||
position_size = max(position_size, min(min_position, self.balance * 0.5))
|
||||
|
||||
# Ensure position size doesn't exceed balance * leverage
|
||||
max_position = self.balance * MAX_LEVERAGE
|
||||
position_size = min(position_size, max_position)
|
||||
|
||||
return position_size
|
||||
return risk_amount
|
||||
|
||||
def calculate_fees(self, position_size):
|
||||
"""Calculate trading fees for a given position size"""
|
||||
@ -1639,6 +1667,105 @@ class TradingEnvironment:
|
||||
logger.error(f"Trade execution failed: {e}")
|
||||
return None
|
||||
|
||||
def is_volatile_market(self):
|
||||
"""Detect if the market is currently in a volatile state with significant price movements
|
||||
|
||||
Returns:
|
||||
bool: True if market is volatile, False otherwise
|
||||
"""
|
||||
if len(self.features['price']) < 20:
|
||||
return False
|
||||
|
||||
# Calculate recent price volatility
|
||||
recent_prices = self.features['price'][-20:]
|
||||
returns = np.diff(recent_prices) / recent_prices[:-1]
|
||||
volatility = np.std(returns) * 100 # Convert to percentage
|
||||
|
||||
# Calculate volume increase
|
||||
recent_volumes = self.features['volume'][-10:]
|
||||
avg_volume_prev = np.mean(self.features['volume'][-20:-10])
|
||||
avg_volume_recent = np.mean(recent_volumes)
|
||||
volume_increase = avg_volume_recent / avg_volume_prev if avg_volume_prev > 0 else 1.0
|
||||
|
||||
# Calculate ATR if available
|
||||
atr_high = False
|
||||
if len(self.features['atr']) > 5:
|
||||
recent_atr = self.features['atr'][-1]
|
||||
avg_atr = np.mean(self.features['atr'][-20:-1])
|
||||
atr_ratio = recent_atr / avg_atr if avg_atr > 0 else 1.0
|
||||
atr_high = atr_ratio > 1.5
|
||||
|
||||
# Check if price moved significantly in either direction recently
|
||||
price_range_percent = (max(recent_prices) - min(recent_prices)) / min(recent_prices) * 100
|
||||
|
||||
# Market is volatile if any of these conditions are met
|
||||
volatile = (
|
||||
volatility > 0.5 or # High standard deviation of returns
|
||||
volume_increase > 1.8 or # Volume spike
|
||||
price_range_percent > 1.5 or # Large price range
|
||||
atr_high # High ATR relative to average
|
||||
)
|
||||
|
||||
if volatile:
|
||||
logger.info(f"Volatile market detected - Volatility: {volatility:.2f}%, Volume increase: {volume_increase:.2f}x, Price range: {price_range_percent:.2f}%")
|
||||
|
||||
return volatile
|
||||
|
||||
def adapt_trading_parameters_to_market(self):
|
||||
"""Dynamically adjust trading parameters based on market conditions
|
||||
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
# Check market conditions
|
||||
is_volatile = self.is_volatile_market()
|
||||
is_trending_up = self.is_uptrend()
|
||||
is_trending_down = self.is_downtrend()
|
||||
|
||||
# Base parameters
|
||||
base_stop_loss = STOP_LOSS_PERCENT
|
||||
base_take_profit = TAKE_PROFIT_PERCENT
|
||||
base_position_size = 0.5 # 50% of max
|
||||
|
||||
# Adjust based on market conditions
|
||||
if is_volatile:
|
||||
# In volatile markets, use tighter stops but higher take profits
|
||||
self.stop_loss_pct = base_stop_loss * 0.7 # Tighter stop
|
||||
self.take_profit_pct = base_take_profit * 1.8 # Higher target
|
||||
self.max_position_size_pct = base_position_size * 1.3 # More aggressive sizing
|
||||
|
||||
elif is_trending_up:
|
||||
# In uptrends, use looser stops for longs, tighter for shorts
|
||||
if self.position == 'long' or self.position == 'flat':
|
||||
self.stop_loss_pct = base_stop_loss * 0.9
|
||||
self.take_profit_pct = base_take_profit * 1.6
|
||||
self.max_position_size_pct = base_position_size * 1.2
|
||||
else:
|
||||
# More conservative for shorts in uptrend
|
||||
self.stop_loss_pct = base_stop_loss * 0.7
|
||||
self.take_profit_pct = base_take_profit * 1.2
|
||||
self.max_position_size_pct = base_position_size * 0.8
|
||||
|
||||
elif is_trending_down:
|
||||
# In downtrends, use looser stops for shorts, tighter for longs
|
||||
if self.position == 'short' or self.position == 'flat':
|
||||
self.stop_loss_pct = base_stop_loss * 0.9
|
||||
self.take_profit_pct = base_take_profit * 1.6
|
||||
self.max_position_size_pct = base_position_size * 1.2
|
||||
else:
|
||||
# More conservative for longs in downtrend
|
||||
self.stop_loss_pct = base_stop_loss * 0.7
|
||||
self.take_profit_pct = base_take_profit * 1.2
|
||||
self.max_position_size_pct = base_position_size * 0.8
|
||||
else:
|
||||
# In sideways/uncertain markets, be more balanced
|
||||
self.stop_loss_pct = base_stop_loss * 0.8
|
||||
self.take_profit_pct = base_take_profit * 1.3
|
||||
self.max_position_size_pct = base_position_size
|
||||
|
||||
# Log the adaptation
|
||||
logger.debug(f"Adapted trading parameters - Stop loss: {self.stop_loss_pct:.2f}%, Take profit: {self.take_profit_pct:.2f}%, Max position size: {self.max_position_size_pct*100:.1f}%")
|
||||
|
||||
# Ensure GPU usage if available
|
||||
def get_device():
|
||||
"""Get the best available device (CUDA GPU or CPU)"""
|
||||
@ -2787,6 +2914,12 @@ async def process_websocket_ticks(websocket, env, agent=None, demo=True, timefra
|
||||
trades_count = 0
|
||||
step_counter = 0
|
||||
|
||||
# For tracking sudden price movements
|
||||
last_prices = []
|
||||
price_movement_threshold = 0.5 # 0.5% movement threshold
|
||||
volume_spike_threshold = 2.0 # 2x average volume
|
||||
recent_volumes = []
|
||||
|
||||
try:
|
||||
logger.info("Starting WebSocket tick processing...")
|
||||
|
||||
@ -2808,6 +2941,50 @@ async def process_websocket_ticks(websocket, env, agent=None, demo=True, timefra
|
||||
logger.warning(f"Invalid tick data received: {tick}")
|
||||
continue
|
||||
|
||||
# Track price movement for significant changes
|
||||
last_prices.append(price)
|
||||
if len(last_prices) > 20:
|
||||
last_prices.pop(0)
|
||||
|
||||
# Track volumes for volume spikes
|
||||
recent_volumes.append(volume)
|
||||
if len(recent_volumes) > 20:
|
||||
recent_volumes.pop(0)
|
||||
|
||||
# Check for significant price movement
|
||||
if len(last_prices) >= 5:
|
||||
price_change_pct = abs(price - last_prices[0]) / last_prices[0] * 100
|
||||
avg_volume = np.mean(recent_volumes[:-1]) if len(recent_volumes) > 1 else volume
|
||||
volume_ratio = volume / avg_volume if avg_volume > 0 else 1.0
|
||||
|
||||
# Log significant movements
|
||||
if price_change_pct > price_movement_threshold:
|
||||
logger.info(f"Significant price movement detected: {price_change_pct:.2f}% change")
|
||||
|
||||
if volume_ratio > volume_spike_threshold:
|
||||
logger.info(f"Volume spike detected: {volume_ratio:.2f}x average volume")
|
||||
|
||||
# Force more frequent trading decisions on significant movements
|
||||
if (price_change_pct > price_movement_threshold or volume_ratio > volume_spike_threshold) and agent is not None and current_candle is not None:
|
||||
# Create a temporary candle with current data
|
||||
temp_candle = current_candle.copy()
|
||||
temp_candle['close'] = price # Update with latest price
|
||||
|
||||
# Add to environment temporarily
|
||||
env.add_data(temp_candle)
|
||||
|
||||
# Get action
|
||||
state = env.get_state()
|
||||
# Force exploitation (no exploration) during significant movements
|
||||
action = agent.select_action(state, training=False)
|
||||
|
||||
# Execute action in environment
|
||||
next_state, reward, done, info = env.step(action)
|
||||
|
||||
# Log trading activity
|
||||
action_name = "HOLD" if action == 0 else "BUY" if action == 1 else "SELL" if action == 2 else "CLOSE"
|
||||
logger.info(f"Significant movement action: {action_name}, Price: ${price:.2f}, Balance: ${env.balance:.2f}")
|
||||
|
||||
# Convert timestamp to datetime
|
||||
tick_time = datetime.datetime.fromtimestamp(timestamp / 1000)
|
||||
|
||||
|
@ -20,7 +20,7 @@ from datetime import datetime, timedelta
|
||||
|
||||
# Configure logging with more detailed format
|
||||
logging.basicConfig(
|
||||
level=logging.DEBUG, # Changed to DEBUG for more detailed logs
|
||||
level=logging.INFO, # Changed to DEBUG for more detailed logs
|
||||
format='%(asctime)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s',
|
||||
handlers=[
|
||||
logging.StreamHandler(),
|
||||
|
Loading…
x
Reference in New Issue
Block a user