better sticks

This commit is contained in:
Dobromir Popov 2025-04-01 15:10:50 +03:00
parent 73c5ecb0d2
commit b9d2a36e50
2 changed files with 804 additions and 1278 deletions

File diff suppressed because it is too large Load Diff

View File

@ -107,6 +107,12 @@ class RLTrainingIntegrator:
self.trade_count = 0 self.trade_count = 0
self.win_count = 0 self.win_count = 0
# Add session-wide PnL tracking
self.session_pnl = 0.0
self.session_trades = 0
self.session_wins = 0
self.session_balance = 100.0 # Start with $100 balance
# Track current position state # Track current position state
self.in_position = False self.in_position = False
self.entry_price = None self.entry_price = None
@ -151,7 +157,28 @@ class RLTrainingIntegrator:
# Calculate profit if we have entry data # Calculate profit if we have entry data
pnl = None pnl = None
if self.entry_price is not None: if self.entry_price is not None:
pnl = (price - self.entry_price) / self.entry_price # Calculate percentage change
pnl_pct = (price - self.entry_price) / self.entry_price
# Cap extreme PnL values to more realistic levels (-90% to +100%)
pnl_pct = max(min(pnl_pct, 1.0), -0.9)
# Apply to current balance
trade_amount = self.session_balance * 0.1 # Use 10% of balance per trade
trade_profit = trade_amount * pnl_pct
self.session_balance += trade_profit
# Ensure session balance doesn't go below $1
self.session_balance = max(self.session_balance, 1.0)
# For normalized display in charts and logs
pnl = pnl_pct
# Update session-wide PnL
self.session_pnl += pnl
self.session_trades += 1
if pnl > 0:
self.session_wins += 1
# Log the complete trade on the chart # Log the complete trade on the chart
if self.chart: if self.chart:
@ -162,10 +189,12 @@ class RLTrainingIntegrator:
# Record the trade with PnL # Record the trade with PnL
if hasattr(self.chart, 'add_trade'): if hasattr(self.chart, 'add_trade'):
self.chart.add_trade( self.chart.add_trade(
action=action_str,
price=price, price=price,
timestamp=timestamp, timestamp=timestamp,
pnl=pnl pnl=pnl,
amount=0.1,
action=action_str,
type=action_str # Add explicit type
) )
# Update trade counts # Update trade counts
@ -185,6 +214,21 @@ class RLTrainingIntegrator:
'reward': reward, 'reward': reward,
'timestamp': timestamp.isoformat() 'timestamp': timestamp.isoformat()
}) })
else:
# Hold action
action_str = "HOLD"
timestamp = datetime.now()
# Update chart trading info
if self.chart and hasattr(self.chart, 'update_trading_info'):
# Determine current position size (0.1 if in position, 0 if not)
position_size = 0.1 if self.in_position else 0.0
self.chart.update_trading_info(
signal=action_str,
position=position_size,
balance=self.session_balance,
pnl=self.session_pnl
)
# Track reward for all actions (including hold) # Track reward for all actions (including hold)
self.reward_history.append(reward) self.reward_history.append(reward)
@ -205,6 +249,23 @@ class RLTrainingIntegrator:
logger.info(f" Win rate: {info['win_rate']:.4f}") logger.info(f" Win rate: {info['win_rate']:.4f}")
logger.info(f" Trades: {info['trades']}") logger.info(f" Trades: {info['trades']}")
# Log session-wide PnL
session_win_rate = self.session_wins / self.session_trades if self.session_trades > 0 else 0
logger.info(f" Session Balance: ${self.session_balance:.2f}")
logger.info(f" Session Total PnL: {self.session_pnl:.4f}")
logger.info(f" Session Win Rate: {session_win_rate:.4f}")
logger.info(f" Session Trades: {self.session_trades}")
# Update chart trading info with final episode information
if self.chart and hasattr(self.chart, 'update_trading_info'):
# Reset position since we're between episodes
self.chart.update_trading_info(
signal="HOLD",
position=0.0,
balance=self.session_balance,
pnl=self.session_pnl
)
# Reset position state for new episode # Reset position state for new episode
self.in_position = False self.in_position = False
self.entry_price = None self.entry_price = None
@ -441,8 +502,8 @@ async def start_realtime_chart(symbol="BTC/USDT", port=8050):
try: try:
logger.info(f"Initializing RealTimeChart for {symbol}") logger.info(f"Initializing RealTimeChart for {symbol}")
# Create the chart # Create the chart with sample data enabled and no-ticks warnings disabled
chart = RealTimeChart(symbol) chart = RealTimeChart(symbol, use_sample_data=True, log_no_ticks_warning=False)
# Start the WebSocket connection in a separate thread # Start the WebSocket connection in a separate thread
# The _start_websocket_thread method already handles this correctly # The _start_websocket_thread method already handles this correctly
@ -466,10 +527,18 @@ async def start_realtime_chart(symbol="BTC/USDT", port=8050):
logger.error(traceback.format_exc()) logger.error(traceback.format_exc())
raise raise
def run_training_thread(chart, num_episodes=5000, max_steps=2000): def run_training_thread(chart):
"""Run the RL training in a separate thread""" """Start the RL training in a separate thread"""
integrator = RLTrainingIntegrator(chart) integrator = RLTrainingIntegrator(chart)
thread = Thread(target=lambda: integrator.start_training(num_episodes, max_steps))
def training_thread_func():
try:
# Use a small number of episodes to test termination handling
integrator.start_training(num_episodes=2, max_steps=500)
except Exception as e:
logger.error(f"Error in training thread: {str(e)}")
thread = threading.Thread(target=training_thread_func)
thread.daemon = True thread.daemon = True
thread.start() thread.start()
logger.info("Started RL training thread") logger.info("Started RL training thread")
@ -490,8 +559,17 @@ def test_signals(chart):
# Add a test SELL signal # Add a test SELL signal
chart.add_nn_signal("SELL", datetime.now(), 0.85) chart.add_nn_signal("SELL", datetime.now(), 0.85)
# Add a test trade # Add a test trade if the method exists
chart.add_trade("BUY", 50000.0, datetime.now(), 0.05) if hasattr(chart, 'add_trade'):
chart.add_trade(
price=83000.0,
timestamp=datetime.now(),
pnl=0.05,
action="BUY",
type="BUY" # Add explicit type
)
else:
logger.warning("RealTimeChart has no add_trade method - skipping test trade")
async def main(): async def main():
"""Main function that coordinates the realtime chart and RL training""" """Main function that coordinates the realtime chart and RL training"""
@ -520,6 +598,18 @@ async def main():
except Exception as e: except Exception as e:
logger.error(f"Unexpected error: {str(e)}") logger.error(f"Unexpected error: {str(e)}")
finally: finally:
# Log final PnL summary
if hasattr(integrator, 'session_pnl'):
session_win_rate = integrator.session_wins / integrator.session_trades if integrator.session_trades > 0 else 0
logger.info("=" * 50)
logger.info("FINAL SESSION SUMMARY")
logger.info("=" * 50)
logger.info(f"Final Session Balance: ${integrator.session_balance:.2f}")
logger.info(f"Total Session PnL: {integrator.session_pnl:.4f}")
logger.info(f"Total Session Win Rate: {session_win_rate:.4f} ({integrator.session_wins}/{integrator.session_trades})")
logger.info(f"Total Session Trades: {integrator.session_trades}")
logger.info("=" * 50)
# Clean up # Clean up
if realtime_websocket_task: if realtime_websocket_task:
realtime_websocket_task.cancel() realtime_websocket_task.cancel()