recent trades in list

This commit is contained in:
Dobromir Popov 2025-04-01 17:56:02 +03:00
parent 989e755264
commit 3eff11fd78
5 changed files with 322 additions and 27 deletions

46
access_app.py Normal file
View File

@ -0,0 +1,46 @@
import sys
import os
import time
from datetime import datetime
# Add the project root to the path
sys.path.append(os.getcwd())
# Try to access the running application's charts
from train_rl_with_realtime import charts
if not charts:
print("No charts are running. Please start the application first.")
sys.exit(1)
# Get the first chart
chart = charts[0]
print(f"Accessing chart for {chart.symbol}")
# Add some test trades
print("Adding trades...")
chart.add_trade(price=64500, timestamp=datetime.now(), pnl=0.5, action='BUY')
print("Added BUY trade 1")
time.sleep(1)
chart.add_trade(price=64800, timestamp=datetime.now(), pnl=0.7, action='SELL')
print("Added SELL trade 1")
time.sleep(1)
chart.add_trade(price=64600, timestamp=datetime.now(), pnl=0.3, action='BUY')
print("Added BUY trade 2")
time.sleep(1)
chart.add_trade(price=64900, timestamp=datetime.now(), pnl=0.6, action='SELL')
print("Added SELL trade 2")
# Try to get the current trades
print("\nCurrent trades:")
if hasattr(chart, 'trades') and chart.trades:
for i, trade in enumerate(chart.trades[-5:]):
action = trade.get('action', 'UNKNOWN')
price = trade.get('price', 'N/A')
timestamp = trade.get('timestamp', 'N/A')
pnl = trade.get('pnl', None)
close_price = trade.get('close_price', 'N/A')
print(f"Trade {i+1}: {action} @ {price}, Close: {close_price}, PnL: {pnl}, Time: {timestamp}")
else:
print("No trades found.")

53
add_test_trades.py Normal file
View File

@ -0,0 +1,53 @@
from datetime import datetime, timedelta
import random
import time
from realtime import RealTimeChart
# Create a standalone chart instance
chart = RealTimeChart('BTC/USDT')
# Base price
base_price = 65000.0
# Add 5 pairs of trades (BUY followed by SELL)
for i in range(5):
# Create a buy trade
buy_price = base_price + random.uniform(-200, 200)
buy_time = datetime.now() - timedelta(minutes=5-i) # Older to newer
buy_amount = round(random.uniform(0.05, 0.5), 2)
# Add the BUY trade
chart.add_trade(
price=buy_price,
timestamp=buy_time,
amount=buy_amount,
pnl=None, # Set to None for buys
action='BUY'
)
print(f"Added BUY trade {i+1}: Price={buy_price:.2f}, Amount={buy_amount}, Time={buy_time}")
# Wait a moment
time.sleep(0.5)
# Create a sell trade (typically at a different price)
price_change = random.uniform(-100, 300) # More likely to be positive for profit
sell_price = buy_price + price_change
sell_time = buy_time + timedelta(minutes=random.uniform(0.5, 1.5))
# Calculate PnL
pnl = (sell_price - buy_price) * buy_amount
# Add the SELL trade
chart.add_trade(
price=sell_price,
timestamp=sell_time,
amount=buy_amount, # Same amount as buy
pnl=pnl,
action='SELL'
)
print(f"Added SELL trade {i+1}: Price={sell_price:.2f}, PnL={pnl:.2f}, Time={sell_time}")
# Wait a moment before the next pair
time.sleep(0.5)
print("\nAll trades added successfully!")

11
generate_trades.py Normal file
View File

@ -0,0 +1,11 @@
from datetime import datetime
from realtime import RealTimeChart
chart = RealTimeChart('BTC/USDT')
for i in range(3):
chart.add_trade(price=65000+i*100, timestamp=datetime.now(), pnl=0.1*i, action='BUY')
chart.add_trade(price=65100+i*100, timestamp=datetime.now(), pnl=0.2*i, action='SELL')
print(f'Added trade pair {i+1}')
print('All trades added successfully')

View File

@ -1519,7 +1519,7 @@ class RealTimeChart:
'color': '#FFFFFF', 'color': '#FFFFFF',
'backgroundColor': '#222' 'backgroundColor': '#222'
}) })
], style={'marginTop': '20px', 'marginBottom': '20px', 'overflowX': 'auto'}) ], style={'marginTop': '20px', 'marginBottom': '20px', 'overflowX': 'auto'}),
# Chart acknowledgment # Chart acknowledgment
html.Div("Real-time trading chart with ML signals", style={ html.Div("Real-time trading chart with ML signals", style={
@ -2344,42 +2344,177 @@ class RealTimeChart:
def _setup_position_list_callback(self): def _setup_position_list_callback(self):
"""Callback to update the position list with the latest 5 trades""" """Callback to update the position list with the latest 5 trades"""
@self.app.callback( @self.app.callback(
Output('position-list', 'children'), Output('position-table-body', 'children'),
[Input('interval-component', 'n_intervals')] [Input('interval-component', 'n_intervals')]
) )
def update_position_list(n): def update_position_list(n):
try: try:
# Get the last 5 positions # Get the last 5 positions
if not hasattr(self, 'trades') or not self.trades: if not hasattr(self, 'trades') or not self.trades:
return [html.Li("No trades yet", style={'color': '#AAAAAA'})] return [html.Tr([html.Td("No trades yet", colSpan=6, style={'textAlign': 'center', 'color': '#AAAAAA', 'padding': '10px'})])]
last_positions = self.trades[-5:]
position_items = []
for trade in last_positions: # Collect BUY and SELL trades to pair them
buy_trades = {}
sell_trades = {}
position_rows = []
# Process all trades to match buy and sell pairs
for trade in self.trades:
action = trade.get('action', 'UNKNOWN') action = trade.get('action', 'UNKNOWN')
price = trade.get('price', 'N/A') if action == 'BUY':
timestamp = trade.get('timestamp', 'N/A') # Store buy trades by timestamp to match with sells later
pnl = trade.get('pnl', None) buy_trades[trade.get('timestamp')] = trade
elif action == 'SELL':
# Format the display # Store sell trades
pnl_str = f", PnL: {pnl:.4f}" if pnl is not None else "" sell_trades[trade.get('timestamp')] = trade
time_str = timestamp.strftime('%H:%M:%S') if isinstance(timestamp, datetime) else str(timestamp)
# Set color based on action
color = '#00FF00' if action == 'BUY' else '#FF0000'
position_items.append(
html.Li(
f"{action} @ {price} ({time_str}){pnl_str}",
style={'color': color, 'padding': '5px', 'borderBottom': '1px solid #333'}
)
)
return position_items # Create position entries (matched pairs or single trades)
position_entries = []
# First add matched pairs (BUY trades with matching close_price)
for timestamp, buy_trade in buy_trades.items():
if 'close_price' in buy_trade:
# This is a closed position
entry_price = buy_trade.get('price', 'N/A')
exit_price = buy_trade.get('close_price', 'N/A')
entry_time = buy_trade.get('timestamp')
exit_time = buy_trade.get('close_timestamp')
amount = buy_trade.get('amount', 0.1)
# Calculate PnL if not provided
pnl = buy_trade.get('pnl')
if pnl is None and isinstance(entry_price, (int, float)) and isinstance(exit_price, (int, float)):
pnl = (exit_price - entry_price) * amount
position_entries.append({
'action': 'CLOSED',
'entry_price': entry_price,
'exit_price': exit_price,
'amount': amount,
'pnl': pnl,
'time': entry_time,
'exit_time': exit_time,
'status': 'CLOSED'
})
else:
# This is an open position (BUY without a matching SELL)
current_price = self.tick_storage.get_latest_price() or buy_trade.get('price', 0)
amount = buy_trade.get('amount', 0.1)
entry_price = buy_trade.get('price', 0)
# Calculate unrealized PnL
unrealized_pnl = (current_price - entry_price) * amount if isinstance(current_price, (int, float)) and isinstance(entry_price, (int, float)) else None
position_entries.append({
'action': 'BUY',
'entry_price': entry_price,
'exit_price': current_price, # Use current price as potential exit
'amount': amount,
'pnl': unrealized_pnl,
'time': buy_trade.get('timestamp'),
'status': 'OPEN'
})
# Add standalone SELL trades that don't have a matching BUY
for timestamp, sell_trade in sell_trades.items():
# Check if this SELL is already accounted for in a closed position
already_matched = False
for entry in position_entries:
if entry.get('status') == 'CLOSED' and entry.get('exit_time') == timestamp:
already_matched = True
break
if not already_matched:
position_entries.append({
'action': 'SELL',
'entry_price': 'N/A',
'exit_price': sell_trade.get('price', 'N/A'),
'amount': sell_trade.get('amount', 0.1),
'pnl': sell_trade.get('pnl'),
'time': sell_trade.get('timestamp'),
'status': 'STANDALONE'
})
# Sort by time (most recent first) and take last 5
position_entries.sort(key=lambda x: x['time'] if isinstance(x['time'], datetime) else datetime.now(), reverse=True)
position_entries = position_entries[:5]
# Convert to table rows
for entry in position_entries:
action = entry['action']
entry_price = entry['entry_price']
exit_price = entry['exit_price']
amount = entry['amount']
pnl = entry['pnl']
time_obj = entry['time']
status = entry['status']
# Format time
if isinstance(time_obj, datetime):
# If trade is from a different day, include the date
today = datetime.now().date()
if time_obj.date() == today:
time_str = time_obj.strftime('%H:%M:%S')
else:
time_str = time_obj.strftime('%m-%d %H:%M:%S')
else:
time_str = str(time_obj)
# Format prices with proper decimal places
if isinstance(entry_price, (int, float)):
entry_price_str = f"${entry_price:.2f}"
else:
entry_price_str = str(entry_price)
if isinstance(exit_price, (int, float)):
exit_price_str = f"${exit_price:.2f}"
else:
exit_price_str = str(exit_price)
# Format PnL
if pnl is not None and isinstance(pnl, (int, float)):
pnl_str = f"${pnl:.2f}"
pnl_color = '#00FF00' if pnl >= 0 else '#FF0000'
else:
pnl_str = 'N/A'
pnl_color = '#FFFFFF'
# Set action/status color and text
if status == 'OPEN':
status_color = '#00AAFF' # Blue for open positions
status_text = "OPEN (BUY)"
elif status == 'CLOSED':
if pnl is not None and isinstance(pnl, (int, float)):
status_color = '#00FF00' if pnl >= 0 else '#FF0000' # Green/Red based on profit
else:
status_color = '#FFCC00' # Yellow if PnL unknown
status_text = "CLOSED"
elif action == 'BUY':
status_color = '#00FF00'
status_text = "BUY"
elif action == 'SELL':
status_color = '#FF0000'
status_text = "SELL"
else:
status_color = '#FFFFFF'
status_text = action
# Create table row
position_rows.append(html.Tr([
html.Td(status_text, style={'color': status_color, 'padding': '8px', 'border': '1px solid #444'}),
html.Td(f"{amount} BTC", style={'padding': '8px', 'border': '1px solid #444'}),
html.Td(entry_price_str, style={'padding': '8px', 'border': '1px solid #444'}),
html.Td(exit_price_str, style={'padding': '8px', 'border': '1px solid #444'}),
html.Td(pnl_str, style={'color': pnl_color, 'padding': '8px', 'border': '1px solid #444'}),
html.Td(time_str, style={'padding': '8px', 'border': '1px solid #444'})
]))
return position_rows
except Exception as e: except Exception as e:
logger.error(f"Error updating position list: {str(e)}") logger.error(f"Error updating position table: {str(e)}")
return [html.Li("Error loading positions", style={'color': '#FF0000'})] import traceback
logger.error(traceback.format_exc())
return [html.Tr([html.Td(f"Error: {str(e)}", colSpan=6, style={'color': '#FF0000', 'padding': '10px'})])]
def _interval_to_seconds(self, interval_key: str) -> int: def _interval_to_seconds(self, interval_key: str) -> int:
"""Convert interval key to seconds""" """Convert interval key to seconds"""

50
test_timestamps.py Normal file
View File

@ -0,0 +1,50 @@
from datetime import datetime, timedelta
from realtime import RealTimeChart
# Create a chart instance
chart = RealTimeChart('BTC/USDT')
# Add a BUY position from yesterday
yesterday = datetime.now() - timedelta(days=1)
chart.add_trade(
price=64950.25,
timestamp=yesterday,
amount=0.5,
pnl=None,
action='BUY'
)
print(f'Added BUY position from {yesterday}')
# Add a matching SELL position from yesterday (2 hours later)
yesterday_plus_2h = yesterday + timedelta(hours=2)
chart.add_trade(
price=65100.75,
timestamp=yesterday_plus_2h,
amount=0.5,
pnl=75.25,
action='SELL'
)
print(f'Added matching SELL position from {yesterday_plus_2h}')
# Add a trade from 2 days ago
two_days_ago = datetime.now() - timedelta(days=2)
chart.add_trade(
price=64800.50,
timestamp=two_days_ago,
amount=0.25,
pnl=None,
action='BUY'
)
print(f'Added BUY position from {two_days_ago}')
two_days_ago_plus_3h = two_days_ago + timedelta(hours=3)
chart.add_trade(
price=65000.75,
timestamp=two_days_ago_plus_3h,
amount=0.25,
pnl=50.06,
action='SELL'
)
print(f'Added matching SELL position from {two_days_ago_plus_3h}')
print('\nAll test trades added successfully!')