working actions dsplay, rewrite chart in realtime.py
This commit is contained in:
parent
902593b5f3
commit
44b02b4e7d
1731
realtime.py
1731
realtime.py
File diff suppressed because it is too large
Load Diff
173
realtime_old.py
173
realtime_old.py
@ -22,6 +22,7 @@ import tzlocal
|
||||
import threading
|
||||
import random
|
||||
import dash_bootstrap_components as dbc
|
||||
import uuid
|
||||
|
||||
# Configure logging with more detailed format
|
||||
logging.basicConfig(
|
||||
@ -2907,97 +2908,45 @@ class RealTimeChart:
|
||||
|
||||
logger.info(f"Added NN signal: {signal_type} at {timestamp}")
|
||||
|
||||
def add_trade(self, price, timestamp, pnl=None, amount=0.1, action=None, type=None):
|
||||
"""Add a trade to be displayed on the chart
|
||||
def add_trade(self, price, timestamp, amount, pnl=0.0, action="BUY"):
|
||||
"""Add a trade to the chart and update the positions list"""
|
||||
# Ensure the positions list exists
|
||||
if not hasattr(self, 'positions'):
|
||||
self.positions = []
|
||||
|
||||
Args:
|
||||
price: The price at which the trade was executed
|
||||
timestamp: The timestamp for the trade
|
||||
pnl: Optional profit and loss value for the trade
|
||||
amount: Amount traded
|
||||
action: The type of trade (BUY or SELL) - alternative to type parameter
|
||||
type: The type of trade (BUY or SELL) - alternative to action parameter
|
||||
"""
|
||||
# Handle both action and type parameters for backward compatibility
|
||||
trade_type = type or action
|
||||
# Create position ID
|
||||
position_id = str(uuid.uuid4())[:8]
|
||||
|
||||
# Default to BUY if trade_type is None or not specified
|
||||
if trade_type is None:
|
||||
logger.warning(f"Trade type not specified in add_trade call, defaulting to BUY. Price: {price}, Timestamp: {timestamp}")
|
||||
trade_type = "BUY"
|
||||
# Log the trade
|
||||
logger.info(f"Added {action} trade: price={price}, amount={amount}, time={timestamp}, PnL={pnl}")
|
||||
|
||||
if isinstance(trade_type, int):
|
||||
trade_type = "BUY" if trade_type == 0 else "SELL"
|
||||
# Add trade marker to the chart
|
||||
if action == "BUY":
|
||||
color = 'green'
|
||||
marker = 'triangle-up'
|
||||
else: # SELL
|
||||
color = 'red'
|
||||
marker = 'triangle-down'
|
||||
|
||||
# Ensure trade_type is uppercase if it's a string
|
||||
if isinstance(trade_type, str):
|
||||
trade_type = trade_type.upper()
|
||||
# Add to positions list
|
||||
new_position = Position(
|
||||
action=action,
|
||||
entry_price=price,
|
||||
amount=amount,
|
||||
timestamp=timestamp,
|
||||
trade_id=position_id
|
||||
)
|
||||
self.positions.append(new_position)
|
||||
|
||||
if trade_type not in ['BUY', 'SELL']:
|
||||
logger.warning(f"Invalid trade type: {trade_type} (value type: {type(trade_type).__name__}), defaulting to BUY. Price: {price}, Timestamp: {timestamp}")
|
||||
trade_type = "BUY"
|
||||
# Limit the positions list to the last 10 entries
|
||||
if len(self.positions) > 10:
|
||||
self.positions = self.positions[-10:]
|
||||
|
||||
# Convert timestamp to datetime if it's not already
|
||||
if not isinstance(timestamp, datetime):
|
||||
try:
|
||||
if isinstance(timestamp, str):
|
||||
timestamp = datetime.fromisoformat(timestamp.replace('Z', '+00:00'))
|
||||
elif isinstance(timestamp, (int, float)):
|
||||
timestamp = datetime.fromtimestamp(timestamp / 1000.0)
|
||||
except Exception as e:
|
||||
logger.error(f"Error converting timestamp for trade: {str(e)}")
|
||||
timestamp = datetime.now()
|
||||
# Add to the figure
|
||||
self._add_trade_marker(price, timestamp, color, marker)
|
||||
|
||||
# Create the trade object
|
||||
trade = {
|
||||
'price': price,
|
||||
'timestamp': timestamp,
|
||||
'pnl': pnl,
|
||||
'amount': amount,
|
||||
'action': trade_type
|
||||
}
|
||||
|
||||
# Add to our trades list
|
||||
if not hasattr(self, 'trades'):
|
||||
self.trades = []
|
||||
|
||||
# If this is a SELL trade, try to find the corresponding BUY trade and update it with close_price
|
||||
if trade_type == 'SELL' and len(self.trades) > 0:
|
||||
for i in range(len(self.trades) - 1, -1, -1):
|
||||
prev_trade = self.trades[i]
|
||||
if prev_trade.get('action') == 'BUY' and 'close_price' not in prev_trade:
|
||||
# Found a BUY trade without a close_price, consider it the matching trade
|
||||
prev_trade['close_price'] = price
|
||||
prev_trade['close_timestamp'] = timestamp
|
||||
logger.info(f"Updated BUY trade at {prev_trade['timestamp']} with close price {price}")
|
||||
break
|
||||
|
||||
self.trades.append(trade)
|
||||
|
||||
# Log the trade for debugging
|
||||
pnl_str = f" with PnL: {pnl}" if pnl is not None else ""
|
||||
logger.info(f"Added trade: {trade_type} {amount} at price {price} at time {timestamp}{pnl_str}")
|
||||
|
||||
# Trigger a more frequent update of the chart by scheduling a callback
|
||||
# This helps ensure the trade appears immediately on the chart
|
||||
if hasattr(self, 'app') and self.app is not None:
|
||||
try:
|
||||
# Only update if we have a dash app running
|
||||
# This is a workaround to make trades appear immediately
|
||||
callback_context = dash.callback_context
|
||||
# Force an update by triggering the callback
|
||||
for callback_id, callback_info in self.app.callback_map.items():
|
||||
if 'live-chart' in callback_id:
|
||||
# Found the chart callback, try to trigger it
|
||||
logger.debug(f"Triggering chart update callback after trade")
|
||||
callback_info['callback']()
|
||||
break
|
||||
except Exception as e:
|
||||
# If callback triggering fails, it's not critical
|
||||
logger.debug(f"Failed to trigger chart update: {str(e)}")
|
||||
pass
|
||||
|
||||
return trade
|
||||
# Trigger update callback
|
||||
self._update_chart_and_positions()
|
||||
|
||||
def update_trading_info(self, signal=None, position=None, balance=None, pnl=None):
|
||||
"""Update the current trading information to be displayed on the chart
|
||||
@ -3026,6 +2975,62 @@ class RealTimeChart:
|
||||
|
||||
logger.debug(f"Updated trading info: Signal={self.current_signal}, Position={self.current_position}, Balance=${self.session_balance:.2f}, PnL={self.session_pnl:.4f}")
|
||||
|
||||
def _add_trade_marker(self, price, timestamp, color, marker):
|
||||
"""Add a trade marker to the chart
|
||||
|
||||
Args:
|
||||
price: The price at which the trade was executed
|
||||
timestamp: The timestamp for the trade
|
||||
color: The color of the marker (green for buy, red for sell)
|
||||
marker: The marker symbol to use (triangle-up for buy, triangle-down for sell)
|
||||
"""
|
||||
# Convert timestamp to datetime if it's not already
|
||||
if not isinstance(timestamp, datetime):
|
||||
try:
|
||||
if isinstance(timestamp, str):
|
||||
timestamp = datetime.fromisoformat(timestamp.replace('Z', '+00:00'))
|
||||
elif isinstance(timestamp, (int, float)):
|
||||
timestamp = datetime.fromtimestamp(timestamp / 1000.0)
|
||||
except Exception as e:
|
||||
logger.error(f"Error converting timestamp for trade marker: {str(e)}")
|
||||
timestamp = datetime.now()
|
||||
|
||||
# Add marker to the figure
|
||||
self.fig.add_trace(
|
||||
go.Scatter(
|
||||
x=[timestamp],
|
||||
y=[price],
|
||||
mode='markers',
|
||||
name='BUY' if marker == 'triangle-up' else 'SELL',
|
||||
marker=dict(
|
||||
symbol=marker,
|
||||
size=12,
|
||||
color=f'rgba({0 if color == "green" else 255},{255 if color == "green" else 0},0,0.8)',
|
||||
line=dict(width=1, color='darkgreen' if color == 'green' else 'darkred')
|
||||
),
|
||||
showlegend=True
|
||||
),
|
||||
row=1, col=1
|
||||
)
|
||||
|
||||
# Update the chart
|
||||
self._update_chart_and_positions()
|
||||
|
||||
def _update_chart_and_positions(self):
|
||||
"""Update the chart and positions list"""
|
||||
try:
|
||||
# Update the chart
|
||||
self._update_chart()
|
||||
|
||||
# Update the positions list in the UI
|
||||
if hasattr(self, 'app') and self.app is not None:
|
||||
self.app.callback_context.triggered = [{'prop_id': 'interval-component.n_intervals'}]
|
||||
self.app.callback_map['position-list.children']['callback']()
|
||||
except Exception as e:
|
||||
logger.error(f"Error updating chart and positions: {str(e)}")
|
||||
import traceback
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
async def main():
|
||||
global charts # Make charts globally accessible for NN integration
|
||||
symbols = ["ETH/USDT", "BTC/USDT"]
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user